re3/src/render/Sprite.cpp

554 lines
19 KiB
C++
Raw Normal View History

2019-05-15 14:52:37 +00:00
#include "common.h"
#include "patcher.h"
#include "Draw.h"
#include "Camera.h"
#include "Sprite.h"
// Get rid of bullshit windows definitions, we're not running on an 8086
#ifdef far
#undef far
#undef near
#endif
RwIm2DVertex *CSprite2d::maVertices = (RwIm2DVertex*)0x6E9168;
float &CSprite2d::RecipNearClip = *(float*)0x880DB4;
// Arguments:
// 2---3
// | |
// 0---1
void
CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3, uint32 far)
{
float screenz, z, recipz;
if(far){
screenz = RwIm2DGetFarScreenZ();
z = RwCameraGetFarClipPlane(Scene.camera);
}else{
screenz = RwIm2DGetNearScreenZ();
z = 1.0f/RecipNearClip;
}
recipz = 1.0f/z;
// This is what we draw:
// 0---1
// | / |
// 3---2
RwIm2DVertexSetScreenX(&maVertices[0], r.left);
RwIm2DVertexSetScreenY(&maVertices[0], r.bottom);
RwIm2DVertexSetScreenZ(&maVertices[0], screenz);
RwIm2DVertexSetCameraZ(&maVertices[0], z);
RwIm2DVertexSetRecipCameraZ(&maVertices[0], recipz);
RwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a);
RwIm2DVertexSetU(&maVertices[0], 0.0f, recipz);
RwIm2DVertexSetV(&maVertices[0], 0.0f, recipz);
RwIm2DVertexSetScreenX(&maVertices[1], r.right);
RwIm2DVertexSetScreenY(&maVertices[1], r.bottom);
RwIm2DVertexSetScreenZ(&maVertices[1], screenz);
RwIm2DVertexSetCameraZ(&maVertices[1], z);
RwIm2DVertexSetRecipCameraZ(&maVertices[1], recipz);
RwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a);
RwIm2DVertexSetU(&maVertices[1], 1.0f, recipz);
RwIm2DVertexSetV(&maVertices[1], 0.0f, recipz);
RwIm2DVertexSetScreenX(&maVertices[2], r.right);
RwIm2DVertexSetScreenY(&maVertices[2], r.top);
RwIm2DVertexSetScreenZ(&maVertices[2], screenz);
RwIm2DVertexSetCameraZ(&maVertices[2], z);
RwIm2DVertexSetRecipCameraZ(&maVertices[2], recipz);
RwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a);
RwIm2DVertexSetU(&maVertices[2], 1.0f, recipz);
RwIm2DVertexSetV(&maVertices[2], 1.0f, recipz);
RwIm2DVertexSetScreenX(&maVertices[3], r.left);
RwIm2DVertexSetScreenY(&maVertices[3], r.top);
RwIm2DVertexSetScreenZ(&maVertices[3], screenz);
RwIm2DVertexSetCameraZ(&maVertices[3], z);
RwIm2DVertexSetRecipCameraZ(&maVertices[3], recipz);
RwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a);
RwIm2DVertexSetU(&maVertices[3], 0.0f, recipz);
RwIm2DVertexSetV(&maVertices[3], 1.0f, recipz);
}
void
CSprite2d::SetVertices(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3,
float u0, float v0, float u1, float v1, float u3, float v3, float u2, float v2)
{
float screenz, z, recipz;
screenz = RwIm2DGetNearScreenZ();
z = 1.0f/RecipNearClip;
recipz = 1.0f/z;
// This is what we draw:
// 0---1
// | / |
// 3---2
RwIm2DVertexSetScreenX(&maVertices[0], r.left);
RwIm2DVertexSetScreenY(&maVertices[0], r.bottom);
RwIm2DVertexSetScreenZ(&maVertices[0], screenz);
RwIm2DVertexSetCameraZ(&maVertices[0], z);
RwIm2DVertexSetRecipCameraZ(&maVertices[0], recipz);
RwIm2DVertexSetIntRGBA(&maVertices[0], c2.r, c2.g, c2.b, c2.a);
RwIm2DVertexSetU(&maVertices[0], u0, recipz);
RwIm2DVertexSetV(&maVertices[0], v0, recipz);
RwIm2DVertexSetScreenX(&maVertices[1], r.right);
RwIm2DVertexSetScreenY(&maVertices[1], r.bottom);
RwIm2DVertexSetScreenZ(&maVertices[1], screenz);
RwIm2DVertexSetCameraZ(&maVertices[1], z);
RwIm2DVertexSetRecipCameraZ(&maVertices[1], recipz);
RwIm2DVertexSetIntRGBA(&maVertices[1], c3.r, c3.g, c3.b, c3.a);
RwIm2DVertexSetU(&maVertices[1], u1, recipz);
RwIm2DVertexSetV(&maVertices[1], v1, recipz);
RwIm2DVertexSetScreenX(&maVertices[2], r.right);
RwIm2DVertexSetScreenY(&maVertices[2], r.top);
RwIm2DVertexSetScreenZ(&maVertices[2], screenz);
RwIm2DVertexSetCameraZ(&maVertices[2], z);
RwIm2DVertexSetRecipCameraZ(&maVertices[2], recipz);
RwIm2DVertexSetIntRGBA(&maVertices[2], c1.r, c1.g, c1.b, c1.a);
RwIm2DVertexSetU(&maVertices[2], u2, recipz);
RwIm2DVertexSetV(&maVertices[2], v2, recipz);
RwIm2DVertexSetScreenX(&maVertices[3], r.left);
RwIm2DVertexSetScreenY(&maVertices[3], r.top);
RwIm2DVertexSetScreenZ(&maVertices[3], screenz);
RwIm2DVertexSetCameraZ(&maVertices[3], z);
RwIm2DVertexSetRecipCameraZ(&maVertices[3], recipz);
RwIm2DVertexSetIntRGBA(&maVertices[3], c0.r, c0.g, c0.b, c0.a);
RwIm2DVertexSetU(&maVertices[3], u3, recipz);
RwIm2DVertexSetV(&maVertices[3], v3, recipz);
}
void
CSprite2d::SetRenderState(void)
{
if(m_pTexture)
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, RwTextureGetRaster(m_pTexture));
else
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
}
void
CSprite2d::DrawRect(const CRect &r, const CRGBA &col)
{
SetVertices(r, col, col, col, col, false);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEFLAT);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)(col.a != 255));
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, maVertices, 4);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESHADEMODE, (void*)rwSHADEMODEGOURAUD);
}
void
CSprite2d::DrawRect(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
SetVertices(r, c0, c1, c2, c3, false);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)FALSE);
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, maVertices, 4);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
}
void
CSprite2d::DrawRectXLU(const CRect &r, const CRGBA &c0, const CRGBA &c1, const CRGBA &c2, const CRGBA &c3)
{
SetVertices(r, c0, c1, c2, c3, false);
RwRenderStateSet(rwRENDERSTATETEXTURERASTER, nil);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)FALSE);
RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA);
RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA);
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, CSprite2d::maVertices, 4);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
RwRenderStateSet(rwRENDERSTATEZWRITEENABLE, (void*)TRUE);
}
float &CSprite::m_f2DNearScreenZ = *(float*)0x8F1ABC;
float &CSprite::m_f2DFarScreenZ = *(float*)0x8F2C94;
int32 &CSprite::m_bFlushSpriteBufferSwitchZTest = *(int32*)0x8F5FB0;
float
CSprite::CalcHorizonCoors(void)
{
CVector p = TheCamera.GetPosition() + CVector(TheCamera.CamFrontXNorm, TheCamera.CamFrontYNorm, 0.0f)*3000.0f;
p.z = 0.0f;
p = TheCamera.m_viewMatrix * p;
return p.y * RsGlobal.maximumHeight / p.z;
}
bool
CSprite::CalcScreenCoors(const RwV3d &in, RwV3d *out, float *outw, float *outh, bool farclip)
{
CVector viewvec = TheCamera.m_viewMatrix * *(CVector*)∈
*out = *(RwV3d*)&viewvec;
if(out->z <= CDraw::GetNearClipZ() + 1.0f) return false;
if(out->z >= CDraw::GetFarClipZ() && farclip) return false;
float recip = 1.0f/out->z;
out->x *= RsGlobal.maximumWidth * recip;
out->y *= RsGlobal.maximumHeight * recip;
// What is this? size?
*outw = 70.0f/CDraw::GetFOV();
*outh = 70.0f/CDraw::GetFOV();
*outw *= RsGlobal.maximumWidth * recip;
*outh *= RsGlobal.maximumHeight * recip;
return true;
}
#define SPRITEBUFFERSIZE 64
static int32 &nSpriteBufferIndex = *(int32*)0x649A80;
static RwIm2DVertex *SpriteBufferVerts = (RwIm2DVertex*)0x649A84; //[SPRITEBUFFERSIZE*6];
static RwIm2DVertex *verts = (RwIm2DVertex*)0x64C484; //[4];
void
CSprite::InitSpriteBuffer(void)
{
m_f2DNearScreenZ = RwIm2DGetNearScreenZ();
m_f2DFarScreenZ = RwIm2DGetFarScreenZ();
}
void
CSprite::FlushSpriteBuffer(void)
{
if(nSpriteBufferIndex > 0){
if(m_bFlushSpriteBufferSwitchZTest){
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)FALSE);
RwIm2DRenderPrimitive(rwPRIMTYPETRILIST, SpriteBufferVerts, nSpriteBufferIndex*6);
RwRenderStateSet(rwRENDERSTATEZTESTENABLE, (void*)TRUE);
}else
RwIm2DRenderPrimitive(rwPRIMTYPETRILIST, SpriteBufferVerts, nSpriteBufferIndex*6);
nSpriteBufferIndex = 0;
}
}
void
CSprite::RenderOneXLUSprite(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, uint8 a)
{
static short indices[] = { 0, 1, 2, 3 };
// 0---3
// | |
// 1---2
float xs[4];
float ys[4];
float us[4];
float vs[4];
int i;
xs[0] = x-w; us[0] = 0.0f;
xs[1] = x-w; us[1] = 0.0f;
xs[2] = x+w; us[2] = 1.0f;
xs[3] = x+w; us[3] = 1.0f;
ys[0] = y-h; vs[0] = 0.0f;
ys[1] = y+h; vs[1] = 1.0f;
ys[2] = y+h; vs[2] = 1.0f;
ys[3] = y-h; vs[3] = 0.0f;
// clip
for(i = 0; i < 4; i++){
if(xs[i] < 0.0f){
us[i] = -xs[i] / (2.0f*w);
xs[i] = 0.0f;
}
if(xs[i] > RsGlobal.maximumWidth){
us[i] = 1.0f - (xs[i]-RsGlobal.maximumWidth) / (2.0f*w);
xs[i] = RsGlobal.maximumWidth;
}
if(ys[i] < 0.0f){
vs[i] = -ys[i] / (2.0f*h);
ys[i] = 0.0f;
}
if(ys[i] > RsGlobal.maximumHeight){
vs[i] = 1.0f - (ys[i]-RsGlobal.maximumHeight) / (2.0f*h);
ys[i] = RsGlobal.maximumHeight;
}
}
// (DrawZ - DrawNear)/(DrawFar - DrawNear) = (SpriteZ-SpriteNear)/(SpriteFar-SpriteNear)
// So to calculate SpriteZ:
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);
for(i = 0; i < 4; i++){
RwIm2DVertexSetScreenX(&verts[i], xs[i]);
RwIm2DVertexSetScreenY(&verts[i], ys[i]);
RwIm2DVertexSetScreenZ(&verts[i], screenz);
RwIm2DVertexSetCameraZ(&verts[i], z);
RwIm2DVertexSetRecipCameraZ(&verts[i], recipz);
RwIm2DVertexSetIntRGBA(&verts[i], r*intens>>8, g*intens>>8, b*intens>>8, a);
RwIm2DVertexSetU(&verts[i], us[i], recipz);
RwIm2DVertexSetV(&verts[i], vs[i], recipz);
}
RwIm2DRenderPrimitive(rwPRIMTYPETRIFAN, verts, 4);
}
void
CSprite::RenderBufferedOneXLUSprite(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, uint8 a)
{
m_bFlushSpriteBufferSwitchZTest = 0;
// 0---3
// | |
// 1---2
float xs[4];
float ys[4];
float us[4];
float vs[4];
int i;
xs[0] = x-w; us[0] = 0.0f;
xs[1] = x-w; us[1] = 0.0f;
xs[2] = x+w; us[2] = 1.0f;
xs[3] = x+w; us[3] = 1.0f;
ys[0] = y-h; vs[0] = 0.0f;
ys[1] = y+h; vs[1] = 1.0f;
ys[2] = y+h; vs[2] = 1.0f;
ys[3] = y-h; vs[3] = 0.0f;
// clip
for(i = 0; i < 4; i++){
if(xs[i] < 0.0f){
us[i] = -xs[i] / (2.0f*w);
xs[i] = 0.0f;
}
if(xs[i] > RsGlobal.maximumWidth){
us[i] = 1.0f - (xs[i]-RsGlobal.maximumWidth) / (2.0f*w);
xs[i] = RsGlobal.maximumWidth;
}
if(ys[i] < 0.0f){
vs[i] = -ys[i] / (2.0f*h);
ys[i] = 0.0f;
}
if(ys[i] > RsGlobal.maximumHeight){
vs[i] = 1.0f - (ys[i]-RsGlobal.maximumHeight) / (2.0f*h);
ys[i] = RsGlobal.maximumHeight;
}
}
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);
RwIm2DVertex *vert = &SpriteBufferVerts[nSpriteBufferIndex*6];
static int indices[6] = { 0, 1, 2, 3, 0, 2 };
for(i = 0; i < 6; i++){
RwIm2DVertexSetScreenX(&vert[i], xs[indices[i]]);
RwIm2DVertexSetScreenY(&vert[i], ys[indices[i]]);
RwIm2DVertexSetScreenZ(&vert[i], screenz);
RwIm2DVertexSetCameraZ(&vert[i], z);
RwIm2DVertexSetRecipCameraZ(&vert[i], recipz);
RwIm2DVertexSetIntRGBA(&vert[i], r*intens>>8, g*intens>>8, b*intens>>8, a);
RwIm2DVertexSetU(&vert[i], us[indices[i]], recipz);
RwIm2DVertexSetV(&vert[i], vs[indices[i]], recipz);
}
nSpriteBufferIndex++;
if(nSpriteBufferIndex >= SPRITEBUFFERSIZE)
FlushSpriteBuffer();
}
void
CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float rotation, uint8 a)
{
m_bFlushSpriteBufferSwitchZTest = 0;
// TODO: replace with lookup
float c = cos(DEGTORAD(rotation));
float s = sin(DEGTORAD(rotation));
float xs[4];
float ys[4];
float us[4];
float vs[4];
int i;
xs[0] = x - c*w - s*h; us[0] = 0.0f;
xs[1] = x - c*w + s*h; us[1] = 0.0f;
xs[2] = x + c*w + s*h; us[2] = 1.0f;
xs[3] = x + c*w - s*h; us[3] = 1.0f;
ys[0] = y - c*h + s*w; vs[0] = 0.0f;
ys[1] = y + c*h + s*w; vs[1] = 1.0f;
ys[2] = y + c*h - s*w; vs[2] = 1.0f;
ys[3] = y - c*h - s*w; vs[3] = 0.0f;
// No clipping, just culling
if(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;
if(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;
if(xs[0] > RsGlobal.maximumWidth && xs[1] > RsGlobal.maximumWidth &&
xs[2] > RsGlobal.maximumWidth && xs[3] > RsGlobal.maximumWidth) return;
if(ys[0] > RsGlobal.maximumHeight && ys[1] > RsGlobal.maximumHeight &&
ys[2] > RsGlobal.maximumHeight && ys[3] > RsGlobal.maximumHeight) return;
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);
RwIm2DVertex *vert = &SpriteBufferVerts[nSpriteBufferIndex*6];
static int indices[6] = { 0, 1, 2, 3, 0, 2 };
for(i = 0; i < 6; i++){
RwIm2DVertexSetScreenX(&vert[i], xs[indices[i]]);
RwIm2DVertexSetScreenY(&vert[i], ys[indices[i]]);
RwIm2DVertexSetScreenZ(&vert[i], screenz);
RwIm2DVertexSetCameraZ(&vert[i], z);
RwIm2DVertexSetRecipCameraZ(&vert[i], recipz);
RwIm2DVertexSetIntRGBA(&vert[i], r*intens>>8, g*intens>>8, b*intens>>8, a);
RwIm2DVertexSetU(&vert[i], us[indices[i]], recipz);
RwIm2DVertexSetV(&vert[i], vs[indices[i]], recipz);
}
nSpriteBufferIndex++;
if(nSpriteBufferIndex >= SPRITEBUFFERSIZE)
FlushSpriteBuffer();
}
void
CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect(float x, float y, float z, float w, float h, uint8 r, uint8 g, uint8 b, int16 intens, float recipz, float rotation, uint8 a)
{
m_bFlushSpriteBufferSwitchZTest = 0;
float c = cos(DEGTORAD(rotation));
float s = sin(DEGTORAD(rotation));
float xs[4];
float ys[4];
float us[4];
float vs[4];
int i;
xs[0] = x + w*(-c-s); us[0] = 0.0f;
xs[1] = x + w*(-c+s); us[1] = 0.0f;
xs[2] = x + w*(+c+s); us[2] = 1.0f;
xs[3] = x + w*(+c-s); us[3] = 1.0f;
ys[0] = y + h*(-c+s); vs[0] = 0.0f;
ys[1] = y + h*(+c+s); vs[1] = 1.0f;
ys[2] = y + h*(+c-s); vs[2] = 1.0f;
ys[3] = y + h*(-c-s); vs[3] = 0.0f;
// No clipping, just culling
if(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;
if(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;
if(xs[0] > RsGlobal.maximumWidth && xs[1] > RsGlobal.maximumWidth &&
xs[2] > RsGlobal.maximumWidth && xs[3] > RsGlobal.maximumWidth) return;
if(ys[0] > RsGlobal.maximumHeight && ys[1] > RsGlobal.maximumHeight &&
ys[2] > RsGlobal.maximumHeight && ys[3] > RsGlobal.maximumHeight) return;
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);
RwIm2DVertex *vert = &SpriteBufferVerts[nSpriteBufferIndex*6];
static int indices[6] = { 0, 1, 2, 3, 0, 2 };
for(i = 0; i < 6; i++){
RwIm2DVertexSetScreenX(&vert[i], xs[indices[i]]);
RwIm2DVertexSetScreenY(&vert[i], ys[indices[i]]);
RwIm2DVertexSetScreenZ(&vert[i], screenz);
RwIm2DVertexSetCameraZ(&vert[i], z);
RwIm2DVertexSetRecipCameraZ(&vert[i], recipz);
RwIm2DVertexSetIntRGBA(&vert[i], r*intens>>8, g*intens>>8, b*intens>>8, a);
RwIm2DVertexSetU(&vert[i], us[indices[i]], recipz);
RwIm2DVertexSetV(&vert[i], vs[indices[i]], recipz);
}
nSpriteBufferIndex++;
if(nSpriteBufferIndex >= SPRITEBUFFERSIZE)
FlushSpriteBuffer();
}
void
CSprite::RenderBufferedOneXLUSprite_Rotate_2Colours(float x, float y, float z, float w, float h, uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2, float cx, float cy, float recipz, float rotation, uint8 a)
{
m_bFlushSpriteBufferSwitchZTest = 0;
float c = cos(DEGTORAD(rotation));
float s = sin(DEGTORAD(rotation));
float xs[4];
float ys[4];
float us[4];
float vs[4];
float cf[4];
int i;
xs[0] = x + w*(-c-s); us[0] = 0.0f;
xs[1] = x + w*(-c+s); us[1] = 0.0f;
xs[2] = x + w*(+c+s); us[2] = 1.0f;
xs[3] = x + w*(+c-s); us[3] = 1.0f;
ys[0] = y + h*(-c+s); vs[0] = 0.0f;
ys[1] = y + h*(+c+s); vs[1] = 1.0f;
ys[2] = y + h*(+c-s); vs[2] = 1.0f;
ys[3] = y + h*(-c-s); vs[3] = 0.0f;
// No clipping, just culling
if(xs[0] < 0.0f && xs[1] < 0.0f && xs[2] < 0.0f && xs[3] < 0.0f) return;
if(ys[0] < 0.0f && ys[1] < 0.0f && ys[2] < 0.0f && ys[3] < 0.0f) return;
if(xs[0] > RsGlobal.maximumWidth && xs[1] > RsGlobal.maximumWidth &&
xs[2] > RsGlobal.maximumWidth && xs[3] > RsGlobal.maximumWidth) return;
if(ys[0] > RsGlobal.maximumHeight && ys[1] > RsGlobal.maximumHeight &&
ys[2] > RsGlobal.maximumHeight && ys[3] > RsGlobal.maximumHeight) return;
// Colour factors, cx/y is the direction in which colours change from rgb1 to rgb2
cf[0] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f;
cf[0] = clamp(cf[0], 0.0f, 1.0f);
cf[1] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f;
cf[1] = clamp(cf[1], 0.0f, 1.0f);
cf[2] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f;
cf[2] = clamp(cf[2], 0.0f, 1.0f);
cf[3] = (cx*(-c-s) + cy*(-c+s))*0.5f + 0.5f;
cf[3] = clamp(cf[3], 0.0f, 1.0f);
float screenz = m_f2DNearScreenZ +
(z-CDraw::GetNearClipZ())*(m_f2DFarScreenZ-m_f2DNearScreenZ)*CDraw::GetFarClipZ() /
((CDraw::GetFarClipZ()-CDraw::GetNearClipZ())*z);
RwIm2DVertex *vert = &SpriteBufferVerts[nSpriteBufferIndex*6];
static int indices[6] = { 0, 1, 2, 3, 0, 2 };
for(i = 0; i < 6; i++){
RwIm2DVertexSetScreenX(&vert[i], xs[indices[i]]);
RwIm2DVertexSetScreenY(&vert[i], ys[indices[i]]);
RwIm2DVertexSetScreenZ(&vert[i], screenz);
RwIm2DVertexSetCameraZ(&vert[i], z);
RwIm2DVertexSetRecipCameraZ(&vert[i], recipz);
RwIm2DVertexSetIntRGBA(&vert[i],
r1*cf[indices[i]] + r2*(1.0f - cf[indices[i]]),
g1*cf[indices[i]] + g2*(1.0f - cf[indices[i]]),
b1*cf[indices[i]] + b2*(1.0f - cf[indices[i]]),
a);
RwIm2DVertexSetU(&vert[i], us[indices[i]], recipz);
RwIm2DVertexSetV(&vert[i], vs[indices[i]], recipz);
}
nSpriteBufferIndex++;
if(nSpriteBufferIndex >= SPRITEBUFFERSIZE)
FlushSpriteBuffer();
}
STARTPATCHES
InjectHook(0x51EE90, (void (*)(const CRect&, const CRGBA&, const CRGBA&, const CRGBA&, const CRGBA&, uint32))CSprite2d::SetVertices, PATCH_JUMP);
InjectHook(0x51F220, (void (*)(const CRect&, const CRGBA&, const CRGBA&, const CRGBA&, const CRGBA&,
float, float, float, float, float, float, float, float))CSprite2d::SetVertices, PATCH_JUMP);
InjectHook(0x51F970, (void (*)(const CRect&, const CRGBA&))CSprite2d::DrawRect, PATCH_JUMP);
InjectHook(0x51FA00, (void (*)(const CRect&, const CRGBA&, const CRGBA&, const CRGBA&, const CRGBA&))CSprite2d::DrawRect, PATCH_JUMP);
InjectHook(0x51FA80, CSprite2d::DrawRectXLU, PATCH_JUMP);
InjectHook(0x51C4A0, CSprite::CalcHorizonCoors, PATCH_JUMP);
InjectHook(0x51C3A0, CSprite::CalcScreenCoors, PATCH_JUMP);
InjectHook(0x51C590, CSprite::InitSpriteBuffer, PATCH_JUMP);
InjectHook(0x51C520, CSprite::FlushSpriteBuffer, PATCH_JUMP);
InjectHook(0x51C960, CSprite::RenderOneXLUSprite, PATCH_JUMP);
InjectHook(0x51C5D0, CSprite::RenderBufferedOneXLUSprite, PATCH_JUMP);
InjectHook(0x51D5B0, CSprite::RenderBufferedOneXLUSprite_Rotate_Dimension, PATCH_JUMP);
InjectHook(0x51CCD0, CSprite::RenderBufferedOneXLUSprite_Rotate_Aspect, PATCH_JUMP);
InjectHook(0x51D9E0, CSprite::RenderBufferedOneXLUSprite_Rotate_2Colours, PATCH_JUMP);
ENDPATCHES