Path: blob/main/RSDKv4/Scene3D.cpp
817 views
#include "RetroEngine.hpp"12int vertexCount = 0;3int faceCount = 0;45Matrix matFinal = Matrix();6Matrix matWorld = Matrix();7Matrix matView = Matrix();8Matrix matTemp = Matrix();910Face faceBuffer[FACEBUFFER_SIZE];11Vertex vertexBuffer[VERTEXBUFFER_SIZE];12Vertex vertexBufferT[VERTEXBUFFER_SIZE];1314DrawListEntry3D drawList3D[FACEBUFFER_SIZE];1516int projectionX = 136;17int projectionY = 160;18int fogColor = 0;19int fogStrength = 0;2021int faceLineStart[SCREEN_YSIZE];22int faceLineEnd[SCREEN_YSIZE];23int faceLineStartU[SCREEN_YSIZE];24int faceLineEndU[SCREEN_YSIZE];25int faceLineStartV[SCREEN_YSIZE];26int faceLineEndV[SCREEN_YSIZE];2728void SetIdentityMatrix(Matrix *matrix)29{30matrix->values[0][0] = 0x100;31matrix->values[0][1] = 0;32matrix->values[0][2] = 0;33matrix->values[0][3] = 0;3435matrix->values[1][0] = 0;36matrix->values[1][1] = 0x100;37matrix->values[1][2] = 0;38matrix->values[1][3] = 0;3940matrix->values[2][0] = 0;41matrix->values[2][1] = 0;42matrix->values[2][2] = 0x100;43matrix->values[2][3] = 0;4445matrix->values[3][0] = 0;46matrix->values[3][1] = 0;47matrix->values[3][2] = 0;48matrix->values[3][3] = 0x100;49}50void MatrixMultiply(Matrix *matrixA, Matrix *matrixB)51{52int output[16];5354for (int i = 0; i < 0x10; ++i) {55uint rowA = i / 4;56uint rowB = i % 4;57output[i] = (matrixA->values[rowA][3] * matrixB->values[3][rowB] >> 8) + (matrixA->values[rowA][2] * matrixB->values[2][rowB] >> 8)58+ (matrixA->values[rowA][1] * matrixB->values[1][rowB] >> 8) + (matrixA->values[rowA][0] * matrixB->values[0][rowB] >> 8);59}6061for (int i = 0; i < 0x10; ++i) matrixA->values[i / 4][i % 4] = output[i];62}63void MatrixTranslateXYZ(Matrix *matrix, int XPos, int YPos, int ZPos)64{65matrix->values[0][0] = 0x100;66matrix->values[0][1] = 0;67matrix->values[0][2] = 0;68matrix->values[0][3] = 0;6970matrix->values[1][0] = 0;71matrix->values[1][1] = 0x100;72matrix->values[1][2] = 0;73matrix->values[1][3] = 0;7475matrix->values[2][0] = 0;76matrix->values[2][1] = 0;77matrix->values[2][2] = 0x100;78matrix->values[2][3] = 0;7980matrix->values[3][0] = XPos;81matrix->values[3][1] = YPos;82matrix->values[3][2] = ZPos;83matrix->values[3][3] = 0x100;84}85void MatrixScaleXYZ(Matrix *matrix, int scaleX, int scaleY, int scaleZ)86{87matrix->values[0][0] = scaleX;88matrix->values[0][1] = 0;89matrix->values[0][2] = 0;90matrix->values[0][3] = 0;9192matrix->values[1][0] = 0;93matrix->values[1][1] = scaleY;94matrix->values[1][2] = 0;95matrix->values[1][3] = 0;9697matrix->values[2][0] = 0;98matrix->values[2][1] = 0;99matrix->values[2][2] = scaleZ;100matrix->values[2][3] = 0;101102matrix->values[3][0] = 0;103matrix->values[3][1] = 0;104matrix->values[3][2] = 0;105matrix->values[3][3] = 0x100;106}107void MatrixRotateX(Matrix *matrix, int rotationX)108{109int sine = sin512LookupTable[rotationX & 0x1FF] >> 1;110int cosine = cos512LookupTable[rotationX & 0x1FF] >> 1;111112matrix->values[0][0] = 0x100;113matrix->values[0][1] = 0;114matrix->values[0][2] = 0;115matrix->values[0][3] = 0;116117matrix->values[1][0] = 0;118matrix->values[1][1] = cosine;119matrix->values[1][2] = sine;120matrix->values[1][3] = 0;121122matrix->values[2][0] = 0;123matrix->values[2][1] = -sine;124matrix->values[2][2] = cosine;125matrix->values[2][3] = 0;126127matrix->values[3][0] = 0;128matrix->values[3][1] = 0;129matrix->values[3][2] = 0;130matrix->values[3][3] = 0x100;131}132void MatrixRotateY(Matrix *matrix, int rotationY)133{134int sine = sin512LookupTable[rotationY & 0x1FF] >> 1;135int cosine = cos512LookupTable[rotationY & 0x1FF] >> 1;136137matrix->values[0][0] = cosine;138matrix->values[0][1] = 0;139matrix->values[0][2] = sine;140matrix->values[0][3] = 0;141142matrix->values[1][0] = 0;143matrix->values[1][1] = 0x100;144matrix->values[1][2] = 0;145matrix->values[1][3] = 0;146147matrix->values[2][0] = -sine;148matrix->values[2][1] = 0;149matrix->values[2][2] = cosine;150matrix->values[2][3] = 0;151152matrix->values[3][0] = 0;153matrix->values[3][1] = 0;154matrix->values[3][2] = 0;155matrix->values[3][3] = 0x100;156}157void MatrixRotateZ(Matrix *matrix, int rotationZ)158{159int sine = sin512LookupTable[rotationZ & 0x1FF] >> 1;160int cosine = cos512LookupTable[rotationZ & 0x1FF] >> 1;161matrix->values[0][0] = cosine;162matrix->values[0][1] = 0;163matrix->values[0][2] = sine;164matrix->values[0][3] = 0;165166matrix->values[1][0] = 0;167matrix->values[1][1] = 0x100;168matrix->values[1][2] = 0;169matrix->values[1][3] = 0;170171matrix->values[2][0] = -sine;172matrix->values[2][1] = 0;173matrix->values[2][2] = cosine;174matrix->values[2][3] = 0;175176matrix->values[3][0] = 0;177matrix->values[3][1] = 0;178matrix->values[3][2] = 0;179matrix->values[3][3] = 0x100;180}181void MatrixRotateXYZ(Matrix *matrix, short rotationX, short rotationY, short rotationZ)182{183int sinX = sin512LookupTable[rotationX & 0x1FF] >> 1;184int cosX = cos512LookupTable[rotationX & 0x1FF] >> 1;185int sinY = sin512LookupTable[rotationY & 0x1FF] >> 1;186int cosY = cos512LookupTable[rotationY & 0x1FF] >> 1;187int sinZ = sin512LookupTable[rotationZ & 0x1FF] >> 1;188int cosZ = cos512LookupTable[rotationZ & 0x1FF] >> 1;189190matrix->values[0][0] = (cosZ * cosY >> 8) + (sinZ * (sinY * sinX >> 8) >> 8);191matrix->values[0][1] = (sinZ * cosY >> 8) - (cosZ * (sinY * sinX >> 8) >> 8);192matrix->values[0][2] = sinY * cosX >> 8;193matrix->values[0][3] = 0;194195matrix->values[1][0] = sinZ * -cosX >> 8;196matrix->values[1][1] = cosZ * cosX >> 8;197matrix->values[1][2] = sinX;198matrix->values[1][3] = 0;199200matrix->values[2][0] = (sinZ * (cosY * sinX >> 8) >> 8) - (cosZ * sinY >> 8);201matrix->values[2][1] = (sinZ * -sinY >> 8) - (cosZ * (cosY * sinX >> 8) >> 8);202matrix->values[2][2] = cosY * cosX >> 8;203matrix->values[2][3] = 0;204205matrix->values[3][0] = 0;206matrix->values[3][1] = 0;207matrix->values[3][2] = 0;208matrix->values[3][3] = 0x100;209}210#if !RETRO_REV00211void MatrixInverse(Matrix *matrix)212{213double inv[16], det;214double m[16];215for (int y = 0; y < 4; ++y) {216for (int x = 0; x < 4; ++x) {217m[(y << 2) + x] = matrix->values[y][x] / 256.0;218}219}220221inv[0] = m[5] * m[10] * m[15] - m[5] * m[11] * m[14] - m[9] * m[6] * m[15] + m[9] * m[7] * m[14] + m[13] * m[6] * m[11] - m[13] * m[7] * m[10];222223inv[4] = -m[4] * m[10] * m[15] + m[4] * m[11] * m[14] + m[8] * m[6] * m[15] - m[8] * m[7] * m[14] - m[12] * m[6] * m[11] + m[12] * m[7] * m[10];224225inv[8] = m[4] * m[9] * m[15] - m[4] * m[11] * m[13] - m[8] * m[5] * m[15] + m[8] * m[7] * m[13] + m[12] * m[5] * m[11] - m[12] * m[7] * m[9];226227inv[12] = -m[4] * m[9] * m[14] + m[4] * m[10] * m[13] + m[8] * m[5] * m[14] - m[8] * m[6] * m[13] - m[12] * m[5] * m[10] + m[12] * m[6] * m[9];228229inv[1] = -m[1] * m[10] * m[15] + m[1] * m[11] * m[14] + m[9] * m[2] * m[15] - m[9] * m[3] * m[14] - m[13] * m[2] * m[11] + m[13] * m[3] * m[10];230231inv[5] = m[0] * m[10] * m[15] - m[0] * m[11] * m[14] - m[8] * m[2] * m[15] + m[8] * m[3] * m[14] + m[12] * m[2] * m[11] - m[12] * m[3] * m[10];232233inv[9] = -m[0] * m[9] * m[15] + m[0] * m[11] * m[13] + m[8] * m[1] * m[15] - m[8] * m[3] * m[13] - m[12] * m[1] * m[11] + m[12] * m[3] * m[9];234235inv[13] = m[0] * m[9] * m[14] - m[0] * m[10] * m[13] - m[8] * m[1] * m[14] + m[8] * m[2] * m[13] + m[12] * m[1] * m[10] - m[12] * m[2] * m[9];236237inv[2] = m[1] * m[6] * m[15] - m[1] * m[7] * m[14] - m[5] * m[2] * m[15] + m[5] * m[3] * m[14] + m[13] * m[2] * m[7] - m[13] * m[3] * m[6];238239inv[6] = -m[0] * m[6] * m[15] + m[0] * m[7] * m[14] + m[4] * m[2] * m[15] - m[4] * m[3] * m[14] - m[12] * m[2] * m[7] + m[12] * m[3] * m[6];240241inv[10] = m[0] * m[5] * m[15] - m[0] * m[7] * m[13] - m[4] * m[1] * m[15] + m[4] * m[3] * m[13] + m[12] * m[1] * m[7] - m[12] * m[3] * m[5];242243inv[14] = -m[0] * m[5] * m[14] + m[0] * m[6] * m[13] + m[4] * m[1] * m[14] - m[4] * m[2] * m[13] - m[12] * m[1] * m[6] + m[12] * m[2] * m[5];244245inv[3] = -m[1] * m[6] * m[11] + m[1] * m[7] * m[10] + m[5] * m[2] * m[11] - m[5] * m[3] * m[10] - m[9] * m[2] * m[7] + m[9] * m[3] * m[6];246247inv[7] = m[0] * m[6] * m[11] - m[0] * m[7] * m[10] - m[4] * m[2] * m[11] + m[4] * m[3] * m[10] + m[8] * m[2] * m[7] - m[8] * m[3] * m[6];248249inv[11] = -m[0] * m[5] * m[11] + m[0] * m[7] * m[9] + m[4] * m[1] * m[11] - m[4] * m[3] * m[9] - m[8] * m[1] * m[7] + m[8] * m[3] * m[5];250251inv[15] = m[0] * m[5] * m[10] - m[0] * m[6] * m[9] - m[4] * m[1] * m[10] + m[4] * m[2] * m[9] + m[8] * m[1] * m[6] - m[8] * m[2] * m[5];252253det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];254255if (det == 0)256return;257258det = 1.0 / det;259260for (int i = 0; i < 0x10; ++i) inv[i] = (int)((inv[i] * det) * 256);261for (int i = 0; i < 0x10; ++i) matrix->values[i / 4][i % 4] = inv[i];262}263#endif264void TransformVertexBuffer()265{266matFinal.values[0][0] = matWorld.values[0][0];267matFinal.values[0][1] = matWorld.values[0][1];268matFinal.values[0][2] = matWorld.values[0][2];269matFinal.values[0][3] = matWorld.values[0][3];270271matFinal.values[1][0] = matWorld.values[1][0];272matFinal.values[1][1] = matWorld.values[1][1];273matFinal.values[1][2] = matWorld.values[1][2];274matFinal.values[1][3] = matWorld.values[1][3];275276matFinal.values[2][0] = matWorld.values[2][0];277matFinal.values[2][1] = matWorld.values[2][1];278matFinal.values[2][2] = matWorld.values[2][2];279matFinal.values[2][3] = matWorld.values[2][3];280281matFinal.values[3][0] = matWorld.values[3][0];282matFinal.values[3][1] = matWorld.values[3][1];283matFinal.values[3][2] = matWorld.values[3][2];284matFinal.values[3][3] = matWorld.values[3][3];285MatrixMultiply(&matFinal, &matView);286287for (int v = 0; v < vertexCount; ++v) {288int vx = vertexBuffer[v].x;289int vy = vertexBuffer[v].y;290int vz = vertexBuffer[v].z;291292vertexBufferT[v].x =293(vx * matFinal.values[0][0] >> 8) + (vy * matFinal.values[1][0] >> 8) + (vz * matFinal.values[2][0] >> 8) + matFinal.values[3][0];294vertexBufferT[v].y =295(vx * matFinal.values[0][1] >> 8) + (vy * matFinal.values[1][1] >> 8) + (vz * matFinal.values[2][1] >> 8) + matFinal.values[3][1];296vertexBufferT[v].z =297(vx * matFinal.values[0][2] >> 8) + (vy * matFinal.values[1][2] >> 8) + (vz * matFinal.values[2][2] >> 8) + matFinal.values[3][2];298}299}300void TransformVertices(Matrix *matrix, int startIndex, int endIndex)301{302for (int v = startIndex; v < endIndex; ++v) {303int vx = vertexBuffer[v].x;304int vy = vertexBuffer[v].y;305int vz = vertexBuffer[v].z;306Vertex *vert = &vertexBuffer[v];307vert->x = (vx * matrix->values[0][0] >> 8) + (vy * matrix->values[1][0] >> 8) + (vz * matrix->values[2][0] >> 8) + matrix->values[3][0];308vert->y = (vx * matrix->values[0][1] >> 8) + (vy * matrix->values[1][1] >> 8) + (vz * matrix->values[2][1] >> 8) + matrix->values[3][1];309vert->z = (vx * matrix->values[0][2] >> 8) + (vy * matrix->values[1][2] >> 8) + (vz * matrix->values[2][2] >> 8) + matrix->values[3][2];310}311}312void Sort3DDrawList()313{314for (int i = 0; i < faceCount; ++i) {315drawList3D[i].depth = (vertexBufferT[faceBuffer[i].d].z + vertexBufferT[faceBuffer[i].c].z + vertexBufferT[faceBuffer[i].b].z316+ vertexBufferT[faceBuffer[i].a].z)317>> 2;318drawList3D[i].faceID = i;319}320321for (int i = 0; i < faceCount; ++i) {322for (int j = faceCount - 1; j > i; --j) {323if (drawList3D[j].depth > drawList3D[j - 1].depth) {324int faceID = drawList3D[j].faceID;325int depth = drawList3D[j].depth;326drawList3D[j].faceID = drawList3D[j - 1].faceID;327drawList3D[j].depth = drawList3D[j - 1].depth;328drawList3D[j - 1].faceID = faceID;329drawList3D[j - 1].depth = depth;330}331}332}333}334void Draw3DScene(int spriteSheetID)335{336Vertex quad[4];337for (int i = 0; i < faceCount; ++i) {338Face *face = &faceBuffer[drawList3D[i].faceID];339memset(quad, 0, 4 * sizeof(Vertex));340switch (face->flag) {341default: break;342case FACE_FLAG_TEXTURED_3D:343if (vertexBufferT[face->a].z > 0 && vertexBufferT[face->b].z > 0 && vertexBufferT[face->c].z > 0 && vertexBufferT[face->d].z > 0) {344quad[0].x = SCREEN_CENTERX + projectionX * vertexBufferT[face->a].x / vertexBufferT[face->a].z;345quad[0].y = SCREEN_CENTERY - projectionY * vertexBufferT[face->a].y / vertexBufferT[face->a].z;346quad[1].x = SCREEN_CENTERX + projectionX * vertexBufferT[face->b].x / vertexBufferT[face->b].z;347quad[1].y = SCREEN_CENTERY - projectionY * vertexBufferT[face->b].y / vertexBufferT[face->b].z;348quad[2].x = SCREEN_CENTERX + projectionX * vertexBufferT[face->c].x / vertexBufferT[face->c].z;349quad[2].y = SCREEN_CENTERY - projectionY * vertexBufferT[face->c].y / vertexBufferT[face->c].z;350quad[3].x = SCREEN_CENTERX + projectionX * vertexBufferT[face->d].x / vertexBufferT[face->d].z;351quad[3].y = SCREEN_CENTERY - projectionY * vertexBufferT[face->d].y / vertexBufferT[face->d].z;352quad[0].u = vertexBuffer[face->a].u;353quad[0].v = vertexBuffer[face->a].v;354quad[1].u = vertexBuffer[face->b].u;355quad[1].v = vertexBuffer[face->b].v;356quad[2].u = vertexBuffer[face->c].u;357quad[2].v = vertexBuffer[face->c].v;358quad[3].u = vertexBuffer[face->d].u;359quad[3].v = vertexBuffer[face->d].v;360DrawTexturedFace(quad, spriteSheetID);361}362break;363case FACE_FLAG_TEXTURED_2D:364if (vertexBufferT[face->a].z >= 0 && vertexBufferT[face->b].z >= 0 && vertexBufferT[face->c].z >= 0365&& vertexBufferT[face->d].z >= 0) {366quad[0].x = vertexBufferT[face->a].x;367quad[0].y = vertexBufferT[face->a].y;368quad[1].x = vertexBufferT[face->b].x;369quad[1].y = vertexBufferT[face->b].y;370quad[2].x = vertexBufferT[face->c].x;371quad[2].y = vertexBufferT[face->c].y;372quad[3].x = vertexBufferT[face->d].x;373quad[3].y = vertexBufferT[face->d].y;374quad[0].u = vertexBuffer[face->a].u;375quad[0].v = vertexBuffer[face->a].v;376quad[1].u = vertexBuffer[face->b].u;377quad[1].v = vertexBuffer[face->b].v;378quad[2].u = vertexBuffer[face->c].u;379quad[2].v = vertexBuffer[face->c].v;380quad[3].u = vertexBuffer[face->d].u;381quad[3].v = vertexBuffer[face->d].v;382DrawTexturedFace(quad, spriteSheetID);383}384break;385case FACE_FLAG_COLORED_3D:386if (vertexBufferT[face->a].z > 0 && vertexBufferT[face->b].z > 0 && vertexBufferT[face->c].z > 0 && vertexBufferT[face->d].z > 0) {387quad[0].x = SCREEN_CENTERX + projectionX * vertexBufferT[face->a].x / vertexBufferT[face->a].z;388quad[0].y = SCREEN_CENTERY - projectionY * vertexBufferT[face->a].y / vertexBufferT[face->a].z;389quad[1].x = SCREEN_CENTERX + projectionX * vertexBufferT[face->b].x / vertexBufferT[face->b].z;390quad[1].y = SCREEN_CENTERY - projectionY * vertexBufferT[face->b].y / vertexBufferT[face->b].z;391quad[2].x = SCREEN_CENTERX + projectionX * vertexBufferT[face->c].x / vertexBufferT[face->c].z;392quad[2].y = SCREEN_CENTERY - projectionY * vertexBufferT[face->c].y / vertexBufferT[face->c].z;393quad[3].x = SCREEN_CENTERX + projectionX * vertexBufferT[face->d].x / vertexBufferT[face->d].z;394quad[3].y = SCREEN_CENTERY - projectionY * vertexBufferT[face->d].y / vertexBufferT[face->d].z;395DrawFace(quad, face->color);396}397break;398case FACE_FLAG_COLORED_2D:399if (vertexBufferT[face->a].z >= 0 && vertexBufferT[face->b].z >= 0 && vertexBufferT[face->c].z >= 0400&& vertexBufferT[face->d].z >= 0) {401quad[0].x = vertexBufferT[face->a].x;402quad[0].y = vertexBufferT[face->a].y;403quad[1].x = vertexBufferT[face->b].x;404quad[1].y = vertexBufferT[face->b].y;405quad[2].x = vertexBufferT[face->c].x;406quad[2].y = vertexBufferT[face->c].y;407quad[3].x = vertexBufferT[face->d].x;408quad[3].y = vertexBufferT[face->d].y;409DrawFace(quad, face->color);410}411break;412case FACE_FLAG_FADED:413if (vertexBufferT[face->a].z > 0 && vertexBufferT[face->b].z > 0 && vertexBufferT[face->c].z > 0 && vertexBufferT[face->d].z > 0) {414quad[0].x = SCREEN_CENTERX + projectionX * vertexBufferT[face->a].x / vertexBufferT[face->a].z;415quad[0].y = SCREEN_CENTERY - projectionY * vertexBufferT[face->a].y / vertexBufferT[face->a].z;416quad[1].x = SCREEN_CENTERX + projectionX * vertexBufferT[face->b].x / vertexBufferT[face->b].z;417quad[1].y = SCREEN_CENTERY - projectionY * vertexBufferT[face->b].y / vertexBufferT[face->b].z;418quad[2].x = SCREEN_CENTERX + projectionX * vertexBufferT[face->c].x / vertexBufferT[face->c].z;419quad[2].y = SCREEN_CENTERY - projectionY * vertexBufferT[face->c].y / vertexBufferT[face->c].z;420quad[3].x = SCREEN_CENTERX + projectionX * vertexBufferT[face->d].x / vertexBufferT[face->d].z;421quad[3].y = SCREEN_CENTERY - projectionY * vertexBufferT[face->d].y / vertexBufferT[face->d].z;422423int fogStr = 0;424if ((drawList3D[i].depth - 0x8000) >> 8 >= 0)425fogStr = (drawList3D[i].depth - 0x8000) >> 8;426if (fogStr > fogStrength)427fogStr = fogStrength;428429DrawFadedFace(quad, face->color, fogColor, 0xFF - fogStr);430}431break;432case FACE_FLAG_TEXTURED_C:433if (vertexBufferT[face->a].z > 0) {434// [face->a].uv == sprite center435// [face->b].uv == ???436// [face->c].uv == sprite extend (how far to each edge X & Y)437// [face->d].uv == unused438439quad[0].x = SCREEN_CENTERX + projectionX * (vertexBufferT[face->a].x - vertexBuffer[face->b].u) / vertexBufferT[face->a].z;440quad[0].y = SCREEN_CENTERY - projectionY * (vertexBufferT[face->a].y + vertexBuffer[face->b].v) / vertexBufferT[face->a].z;441quad[1].x = SCREEN_CENTERX + projectionX * (vertexBufferT[face->a].x + vertexBuffer[face->b].u) / vertexBufferT[face->a].z;442quad[1].y = SCREEN_CENTERY - projectionY * (vertexBufferT[face->a].y + vertexBuffer[face->b].v) / vertexBufferT[face->a].z;443quad[2].x = SCREEN_CENTERX + projectionX * (vertexBufferT[face->a].x - vertexBuffer[face->b].u) / vertexBufferT[face->a].z;444quad[2].y = SCREEN_CENTERY - projectionY * (vertexBufferT[face->a].y - vertexBuffer[face->b].v) / vertexBufferT[face->a].z;445quad[3].x = SCREEN_CENTERX + projectionX * (vertexBufferT[face->a].x + vertexBuffer[face->b].u) / vertexBufferT[face->a].z;446quad[3].y = SCREEN_CENTERY - projectionY * (vertexBufferT[face->a].y - vertexBuffer[face->b].v) / vertexBufferT[face->a].z;447448quad[0].u = vertexBuffer[face->a].u - vertexBuffer[face->c].u;449quad[0].v = vertexBuffer[face->a].v - vertexBuffer[face->c].v;450quad[1].u = vertexBuffer[face->a].u + vertexBuffer[face->c].u;451quad[1].v = vertexBuffer[face->a].v - vertexBuffer[face->c].v;452quad[2].u = vertexBuffer[face->a].u - vertexBuffer[face->c].u;453quad[2].v = vertexBuffer[face->a].v + vertexBuffer[face->c].v;454quad[3].u = vertexBuffer[face->a].u + vertexBuffer[face->c].u;455quad[3].v = vertexBuffer[face->a].v + vertexBuffer[face->c].v;456457DrawTexturedFace(quad, spriteSheetID);458}459break;460case FACE_FLAG_TEXTURED_C_BLEND:461if (vertexBufferT[face->a].z > 0) {462// See above, its the same just blended463464quad[0].x = SCREEN_CENTERX + projectionX * (vertexBufferT[face->a].x - vertexBuffer[face->b].u) / vertexBufferT[face->a].z;465quad[0].y = SCREEN_CENTERY - projectionY * (vertexBufferT[face->a].y + vertexBuffer[face->b].v) / vertexBufferT[face->a].z;466quad[1].x = SCREEN_CENTERX + projectionX * (vertexBufferT[face->a].x + vertexBuffer[face->b].u) / vertexBufferT[face->a].z;467quad[1].y = SCREEN_CENTERY - projectionY * (vertexBufferT[face->a].y + vertexBuffer[face->b].v) / vertexBufferT[face->a].z;468quad[2].x = SCREEN_CENTERX + projectionX * (vertexBufferT[face->a].x - vertexBuffer[face->b].u) / vertexBufferT[face->a].z;469quad[2].y = SCREEN_CENTERY - projectionY * (vertexBufferT[face->a].y - vertexBuffer[face->b].v) / vertexBufferT[face->a].z;470quad[3].x = SCREEN_CENTERX + projectionX * (vertexBufferT[face->a].x + vertexBuffer[face->b].u) / vertexBufferT[face->a].z;471quad[3].y = SCREEN_CENTERY - projectionY * (vertexBufferT[face->a].y - vertexBuffer[face->b].v) / vertexBufferT[face->a].z;472473quad[0].u = vertexBuffer[face->a].u - vertexBuffer[face->c].u;474quad[0].v = vertexBuffer[face->a].v - vertexBuffer[face->c].v;475quad[1].u = vertexBuffer[face->a].u + vertexBuffer[face->c].u;476quad[1].v = vertexBuffer[face->a].v - vertexBuffer[face->c].v;477quad[2].u = vertexBuffer[face->a].u - vertexBuffer[face->c].u;478quad[2].v = vertexBuffer[face->a].v + vertexBuffer[face->c].v;479quad[3].u = vertexBuffer[face->a].u + vertexBuffer[face->c].u;480quad[3].v = vertexBuffer[face->a].v + vertexBuffer[face->c].v;481482DrawTexturedFaceBlended(quad, spriteSheetID);483}484break;485case FACE_FLAG_3DSPRITE:486if (vertexBufferT[face->a].z > 0) {487int xpos = SCREEN_CENTERX + projectionX * vertexBufferT[face->a].x / vertexBufferT[face->a].z;488int ypos = SCREEN_CENTERY - projectionY * vertexBufferT[face->a].y / vertexBufferT[face->a].z;489490ObjectScript *scriptInfo = &objectScriptList[vertexBuffer[face->a].u];491SpriteFrame *frame = &scriptFrames[scriptInfo->frameListOffset + vertexBuffer[face->b].u];492493switch (vertexBuffer[face->a].v) {494case FX_SCALE:495DrawSpriteScaled(vertexBuffer[face->b].v, xpos, ypos, -frame->pivotX, -frame->pivotY, vertexBuffer[face->c].u,496vertexBuffer[face->c].u, frame->width, frame->height, frame->sprX, frame->sprY,497scriptInfo->spriteSheetID);498break;499case FX_ROTATE:500DrawSpriteRotated(vertexBuffer[face->b].v, xpos, ypos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY,501frame->width, frame->height, vertexBuffer[face->c].v, scriptInfo->spriteSheetID);502break;503case FX_ROTOZOOM:504DrawSpriteRotozoom(vertexBuffer[face->b].v, xpos, ypos, -frame->pivotX, -frame->pivotY, frame->sprX, frame->sprY,505frame->width, frame->height, vertexBuffer[face->c].v, vertexBuffer[face->c].u,506scriptInfo->spriteSheetID);507break;508}509}510break;511}512}513}514515void ProcessScanEdge(Vertex *vertA, Vertex *vertB)516{517int bottom, top;518519if (vertA->y == vertB->y)520return;521if (vertA->y >= vertB->y) {522top = vertB->y;523bottom = vertA->y + 1;524}525else {526top = vertA->y;527bottom = vertB->y + 1;528}529if (top > SCREEN_YSIZE - 1 || bottom < 0)530return;531if (bottom > SCREEN_YSIZE)532bottom = SCREEN_YSIZE;533int fullX = vertA->x << 16;534int deltaX = ((vertB->x - vertA->x) << 16) / (vertB->y - vertA->y);535if (top < 0) {536fullX -= top * deltaX;537top = 0;538}539for (int i = top; i < bottom; ++i) {540int trueX = fullX >> 16;541if (trueX < faceLineStart[i])542faceLineStart[i] = trueX;543if (trueX > faceLineEnd[i])544faceLineEnd[i] = trueX;545fullX += deltaX;546}547}548void ProcessScanEdgeUV(Vertex *vertA, Vertex *vertB)549{550int bottom, top;551552if (vertA->y == vertB->y)553return;554if (vertA->y >= vertB->y) {555top = vertB->y;556bottom = vertA->y + 1;557}558else {559top = vertA->y;560bottom = vertB->y + 1;561}562if (top > SCREEN_YSIZE - 1 || bottom < 0)563return;564if (bottom > SCREEN_YSIZE)565bottom = SCREEN_YSIZE;566567int fullX = vertA->x << 16;568int fullU = vertA->u << 16;569int fullV = vertA->v << 16;570int deltaX = ((vertB->x - vertA->x) << 16) / (vertB->y - vertA->y);571572int deltaU = 0;573if (vertA->u != vertB->u)574deltaU = ((vertB->u - vertA->u) << 16) / (vertB->y - vertA->y);575576int deltaV = 0;577if (vertA->v != vertB->v) {578deltaV = ((vertB->v - vertA->v) << 16) / (vertB->y - vertA->y);579}580581if (top < 0) {582fullX -= top * deltaX;583fullU -= top * deltaU;584fullV -= top * deltaV;585top = 0;586}587for (int i = top; i < bottom; ++i) {588int trueX = fullX >> 16;589if (trueX < faceLineStart[i]) {590faceLineStart[i] = trueX;591faceLineStartU[i] = fullU;592faceLineStartV[i] = fullV;593}594if (trueX > faceLineEnd[i]) {595faceLineEnd[i] = trueX;596faceLineEndU[i] = fullU;597faceLineEndV[i] = fullV;598}599fullX += deltaX;600fullU += deltaU;601fullV += deltaV;602}603}604605606