Path: blob/master/RSDKv5/RSDK/Graphics/Scene3D.cpp
1163 views
#include "RSDK/Core/RetroEngine.hpp"12using namespace RSDK;34#if RETRO_REV0U5#include "Legacy/Scene3DLegacy.cpp"6#endif78Model RSDK::modelList[MODEL_COUNT];9Scene3D RSDK::scene3DList[SCENE3D_COUNT];1011ScanEdge RSDK::scanEdgeBuffer[SCREEN_YSIZE * 2];1213enum ModelFlags {14MODEL_NOFLAGS = 0,15MODEL_USENORMALS = 1 << 0,16MODEL_USETEXTURES = 1 << 1,17MODEL_USECOLOURS = 1 << 2,18};1920void RSDK::ProcessScanEdge(int32 x1, int32 y1, int32 x2, int32 y2)21{22int32 ix1 = FROM_FIXED(x1);23int32 iy1 = FROM_FIXED(y1);24int32 ix2 = FROM_FIXED(x2);25int32 iy2 = FROM_FIXED(y2);2627int32 top = FROM_FIXED(y1);28if (iy1 != iy2) {29if (iy1 > iy2) {30top = FROM_FIXED(y2);31ix1 = FROM_FIXED(x2);32ix2 = FROM_FIXED(x1);33iy1 = FROM_FIXED(y2);34iy2 = FROM_FIXED(y1);35}3637int32 bottom = iy2 + 1;38if (top < currentScreen->clipBound_Y2 && bottom >= currentScreen->clipBound_Y1) {39if (bottom > currentScreen->clipBound_Y2)40bottom = currentScreen->clipBound_Y2;41int32 scanPos = TO_FIXED(ix1);42int32 delta = TO_FIXED(ix2 - ix1) / (iy2 - iy1);43if (top < 0) {44scanPos -= top * delta;45top = 0;46}4748ScanEdge *edge = &scanEdgeBuffer[top];49for (int32 i = top; i < bottom; ++i) {50int32 scanX = scanPos >> 16;51if (scanX < edge->start)52edge->start = scanX;53if (scanX > edge->end)54edge->end = scanX;55scanPos += delta;56++edge;57}58}59}60}6162void RSDK::ProcessScanEdgeClr(uint32 c1, uint32 c2, int32 x1, int32 y1, int32 x2, int32 y2)63{64int32 iy1 = FROM_FIXED(y1);65int32 iy2 = FROM_FIXED(y2);66int32 ix1 = FROM_FIXED(x1);67int32 ix2 = FROM_FIXED(x2);6869int32 top = FROM_FIXED(y1);70uint32 color1 = c1;71uint32 color2 = c2;72if (iy1 != iy2) {73if (iy1 > iy2) {74top = FROM_FIXED(y2);75ix1 = FROM_FIXED(x2);76ix2 = FROM_FIXED(x1);77iy1 = FROM_FIXED(y2);78iy2 = FROM_FIXED(y1);79color1 = c2;80color2 = c1;81}8283int32 bottom = iy2 + 1;84if (top < currentScreen->clipBound_Y2 && bottom >= currentScreen->clipBound_Y1) {85if (bottom > currentScreen->clipBound_Y2)86bottom = currentScreen->clipBound_Y2;8788int32 size = iy2 - iy1;89int32 scanX = TO_FIXED(ix1);90int32 deltaX = TO_FIXED(ix2 - ix1) / size;9192int32 c1R = (color1 & 0xFF0000);93int32 c2R = (color2 & 0xFF0000);94int32 scanR = c1R;9596int32 deltaR = 0;97if (c1R != c2R)98deltaR = (c2R - c1R) / size;99100int32 c1G = (color1 & 0x00FF00) << 8;101int32 c2G = (color2 & 0x00FF00) << 8;102int32 scanG = c1G;103104int32 deltaG = 0;105if (c1G != c2G)106deltaG = (c2G - c1G) / size;107108int32 c1B = (color1 & 0x0000FF) << 16;109int32 c2B = (color2 & 0x0000FF) << 16;110int32 scanB = c1B;111112int32 deltaB = 0;113if (c1B != c2B)114deltaB = (c2B - c1B) / size;115116if (top < 0) {117scanX -= top * deltaX;118119scanR -= top * deltaR;120scanG -= top * deltaG;121scanB -= top * deltaB;122123top = 0;124}125126ScanEdge *edge = &scanEdgeBuffer[top];127for (int32 i = top; i < bottom; ++i) {128if (FROM_FIXED(scanX) < edge->start) {129edge->start = FROM_FIXED(scanX);130131edge->startR = scanR;132edge->startG = scanG;133edge->startB = scanB;134}135136if (FROM_FIXED(scanX) > edge->end) {137edge->end = FROM_FIXED(scanX);138139edge->endR = scanR;140edge->endG = scanG;141edge->endB = scanB;142}143144scanX += deltaX;145146scanR += deltaR;147scanG += deltaG;148scanB += deltaB;149150++edge;151}152}153}154}155156void RSDK::SetIdentityMatrix(Matrix *matrix)157{158matrix->values[0][0] = 0x100;159matrix->values[1][0] = 0;160matrix->values[2][0] = 0;161matrix->values[3][0] = 0;162matrix->values[0][1] = 0;163matrix->values[1][1] = 0x100;164matrix->values[2][1] = 0;165matrix->values[3][1] = 0;166matrix->values[0][2] = 0;167matrix->values[1][2] = 0;168matrix->values[2][2] = 0x100;169matrix->values[3][2] = 0;170matrix->values[0][3] = 0;171matrix->values[1][3] = 0;172matrix->values[2][3] = 0;173matrix->values[3][3] = 0x100;174}175void RSDK::MatrixMultiply(Matrix *dest, Matrix *matrixA, Matrix *matrixB)176{177int32 result[4][4];178memset(result, 0, 4 * 4 * sizeof(int32));179180for (int32 i = 0; i < 0x10; ++i) {181uint32 rowA = i / 4;182uint32 rowB = i % 4;183result[rowB][rowA] = (matrixA->values[3][rowA] * matrixB->values[rowB][3] >> 8) + (matrixA->values[2][rowA] * matrixB->values[rowB][2] >> 8)184+ (matrixA->values[1][rowA] * matrixB->values[rowB][1] >> 8)185+ (matrixA->values[0][rowA] * matrixB->values[rowB][0] >> 8);186}187188for (int32 i = 0; i < 0x10; ++i) {189uint32 rowA = i / 4;190uint32 rowB = i % 4;191dest->values[rowB][rowA] = result[rowB][rowA];192}193}194void RSDK::MatrixTranslateXYZ(Matrix *matrix, int32 x, int32 y, int32 z, bool32 setIdentity)195{196if (setIdentity) {197matrix->values[0][0] = 0x100;198matrix->values[1][0] = 0;199matrix->values[2][0] = 0;200matrix->values[0][1] = 0;201matrix->values[1][1] = 0x100;202matrix->values[2][1] = 0;203matrix->values[0][2] = 0;204matrix->values[1][2] = 0;205matrix->values[2][2] = 0x100;206matrix->values[3][0] = 0;207matrix->values[3][1] = 0;208matrix->values[3][2] = 0;209matrix->values[3][3] = 0x100;210}211212matrix->values[0][3] = x >> 8;213matrix->values[1][3] = y >> 8;214matrix->values[2][3] = z >> 8;215}216void RSDK::MatrixScaleXYZ(Matrix *matrix, int32 scaleX, int32 scaleY, int32 scaleZ)217{218matrix->values[0][0] = scaleX;219matrix->values[1][0] = 0;220matrix->values[2][0] = 0;221matrix->values[3][0] = 0;222matrix->values[0][1] = 0;223matrix->values[1][1] = scaleY;224matrix->values[2][1] = 0;225matrix->values[3][1] = 0;226matrix->values[0][2] = 0;227matrix->values[1][2] = 0;228matrix->values[2][2] = scaleZ;229matrix->values[3][2] = 0;230matrix->values[0][3] = 0;231matrix->values[1][3] = 0;232matrix->values[2][3] = 0;233matrix->values[3][3] = 0x100;234}235void RSDK::MatrixRotateX(Matrix *matrix, int16 rotationX)236{237int32 sine = sin1024LookupTable[rotationX & 0x3FF] >> 2;238int32 cosine = cos1024LookupTable[rotationX & 0x3FF] >> 2;239240matrix->values[0][0] = 0x100;241matrix->values[1][0] = 0;242matrix->values[2][0] = 0;243matrix->values[3][0] = 0;244matrix->values[0][1] = 0;245matrix->values[1][1] = cosine;246matrix->values[2][1] = sine;247matrix->values[3][1] = 0;248matrix->values[0][2] = 0;249matrix->values[1][2] = -sine;250matrix->values[2][2] = cosine;251matrix->values[3][2] = 0;252matrix->values[0][3] = 0;253matrix->values[1][3] = 0;254matrix->values[2][3] = 0;255matrix->values[3][3] = 0x100;256}257void RSDK::MatrixRotateY(Matrix *matrix, int16 rotationY)258{259int32 sine = sin1024LookupTable[rotationY & 0x3FF] >> 2;260int32 cosine = cos1024LookupTable[rotationY & 0x3FF] >> 2;261matrix->values[0][0] = cosine;262matrix->values[1][0] = 0;263matrix->values[2][0] = sine;264matrix->values[3][0] = 0;265matrix->values[0][1] = 0;266matrix->values[1][1] = 0x100;267matrix->values[2][1] = 0;268matrix->values[3][1] = 0;269matrix->values[0][2] = -sine;270matrix->values[1][2] = 0;271matrix->values[2][2] = cosine;272matrix->values[3][2] = 0;273matrix->values[0][3] = 0;274matrix->values[1][3] = 0;275matrix->values[2][3] = 0;276matrix->values[3][3] = 0x100;277}278void RSDK::MatrixRotateZ(Matrix *matrix, int16 rotationZ)279{280int32 sine = sin1024LookupTable[rotationZ & 0x3FF] >> 2;281int32 cosine = cos1024LookupTable[rotationZ & 0x3FF] >> 2;282matrix->values[0][0] = cosine;283matrix->values[1][0] = -sine;284matrix->values[2][0] = 0;285matrix->values[3][0] = 0;286matrix->values[0][1] = sine;287matrix->values[1][1] = cosine;288matrix->values[2][1] = 0;289matrix->values[3][1] = 0;290matrix->values[0][2] = 0;291matrix->values[1][2] = 0;292matrix->values[2][2] = 0x100;293matrix->values[3][2] = 0;294matrix->values[0][3] = 0;295matrix->values[1][3] = 0;296matrix->values[2][3] = 0;297matrix->values[3][3] = 0x100;298}299void RSDK::MatrixRotateXYZ(Matrix *matrix, int16 rotationX, int16 rotationY, int16 rotationZ)300{301int32 sinX = sin1024LookupTable[rotationX & 0x3FF] >> 2;302int32 cosX = cos1024LookupTable[rotationX & 0x3FF] >> 2;303int32 sinY = sin1024LookupTable[rotationY & 0x3FF] >> 2;304int32 cosY = cos1024LookupTable[rotationY & 0x3FF] >> 2;305int32 sinZ = sin1024LookupTable[rotationZ & 0x3FF] >> 2;306int32 cosZ = cos1024LookupTable[rotationZ & 0x3FF] >> 2;307308matrix->values[0][0] = (cosZ * cosY >> 8) + (sinZ * (sinY * sinX >> 8) >> 8);309matrix->values[0][1] = -(sinZ * cosX) >> 8;310matrix->values[0][2] = (sinZ * (cosY * sinX >> 8) >> 8) - (cosZ * sinY >> 8);311matrix->values[0][3] = 0;312matrix->values[1][0] = (sinZ * cosY >> 8) - (cosZ * (sinY * sinX >> 8) >> 8);313matrix->values[1][1] = cosZ * cosX >> 8;314matrix->values[1][2] = (-(sinZ * sinY) >> 8) - (cosZ * (cosY * sinX >> 8) >> 8);315matrix->values[1][3] = 0;316matrix->values[2][0] = sinY * cosX >> 8;317matrix->values[2][1] = sinX;318matrix->values[2][2] = cosY * cosX >> 8;319matrix->values[2][3] = 0;320matrix->values[3][0] = 0;321matrix->values[3][1] = 0;322matrix->values[3][2] = 0;323matrix->values[3][3] = 0x100;324}325void RSDK::MatrixInverse(Matrix *dest, Matrix *matrix)326{327double inv[16], det;328double m[16];329for (int32 y = 0; y < 4; ++y) {330for (int32 x = 0; x < 4; ++x) {331m[(y << 2) + x] = matrix->values[y][x] / 256.0;332}333}334335inv[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];336337inv[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];338339inv[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];340341inv[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];342343inv[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];344345inv[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];346347inv[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];348349inv[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];350351inv[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];352353inv[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];354355inv[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];356357inv[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];358359inv[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];360361inv[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];362363inv[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];364365inv[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];366367det = m[0] * inv[0] + m[1] * inv[4] + m[2] * inv[8] + m[3] * inv[12];368369if (det == 0)370return;371372det = 1.0 / det;373374for (int32 i = 0; i < 0x10; ++i) inv[i] = (int32)((inv[i] * det) * 256);375for (int32 i = 0; i < 0x10; ++i) dest->values[i / 4][i % 4] = (int32)inv[i];376}377378uint16 RSDK::LoadMesh(const char *filename, uint8 scope)379{380if (!scope || scope > SCOPE_STAGE)381return -1;382383char fullFilePath[0x100];384sprintf_s(fullFilePath, sizeof(fullFilePath), "Data/Meshes/%s", filename);385386RETRO_HASH_MD5(hash);387GEN_HASH_MD5(fullFilePath, hash);388389for (int32 i = 0; i < MODEL_COUNT; ++i) {390if (HASH_MATCH_MD5(hash, modelList[i].hash)) {391return i;392}393}394395uint16 id = -1;396for (id = 0; id < MODEL_COUNT; ++id) {397if (modelList[id].scope == SCOPE_NONE)398break;399}400401if (id >= MODEL_COUNT)402return -1;403404Model *model = &modelList[id];405FileInfo info;406InitFileInfo(&info);407if (LoadFile(&info, fullFilePath, FMODE_RB)) {408uint32 sig = ReadInt32(&info, false);409410if (sig != RSDK_SIGNATURE_MDL) {411CloseFile(&info);412return -1;413}414415model->scope = scope;416HASH_COPY_MD5(model->hash, hash);417418model->flags = ReadInt8(&info);419model->faceVertCount = ReadInt8(&info);420421model->vertCount = ReadInt16(&info);422model->frameCount = ReadInt16(&info);423424AllocateStorage((void **)&model->vertices, sizeof(ModelVertex) * model->vertCount * model->frameCount, DATASET_STG, true);425if (model->flags & MODEL_USETEXTURES)426AllocateStorage((void **)&model->texCoords, sizeof(TexCoord) * model->vertCount, DATASET_STG, true);427if (model->flags & MODEL_USECOLOURS)428AllocateStorage((void **)&model->colors, sizeof(Color) * model->vertCount, DATASET_STG, true);429430if (model->flags & MODEL_USETEXTURES) {431for (int32 v = 0; v < model->vertCount; ++v) {432model->texCoords[v].x = ReadSingle(&info);433model->texCoords[v].y = ReadSingle(&info);434}435}436437if (model->flags & MODEL_USECOLOURS) {438for (int32 v = 0; v < model->vertCount; ++v) {439model->colors[v].color = ReadInt32(&info, false);440}441}442443model->indexCount = ReadInt16(&info);444AllocateStorage((void **)&model->indices, sizeof(uint16) * model->indexCount, DATASET_STG, true);445for (int32 i = 0; i < model->indexCount; ++i) model->indices[i] = ReadInt16(&info);446447for (int32 f = 0; f < model->frameCount; ++f) {448for (int32 v = 0; v < model->vertCount; ++v) {449model->vertices[(f * model->vertCount) + v].x = (int32)(ReadSingle(&info) * 0x100);450model->vertices[(f * model->vertCount) + v].y = (int32)(ReadSingle(&info) * 0x100);451model->vertices[(f * model->vertCount) + v].z = (int32)(ReadSingle(&info) * 0x100);452453model->vertices[(f * model->vertCount) + v].nx = 0;454model->vertices[(f * model->vertCount) + v].ny = 0;455model->vertices[(f * model->vertCount) + v].nz = 0;456if (model->flags & MODEL_USENORMALS) {457model->vertices[(f * model->vertCount) + v].nx = (int32)(ReadSingle(&info) * 0x10000);458model->vertices[(f * model->vertCount) + v].ny = (int32)(ReadSingle(&info) * 0x10000);459model->vertices[(f * model->vertCount) + v].nz = (int32)(ReadSingle(&info) * 0x10000);460}461}462}463464CloseFile(&info);465return id;466}467return -1;468}469uint16 RSDK::Create3DScene(const char *name, uint16 vertexLimit, uint8 scope)470{471if (!scope || scope > SCOPE_STAGE)472return -1;473474RETRO_HASH_MD5(hash);475GEN_HASH_MD5(name, hash);476477for (int32 i = 0; i < SCENE3D_COUNT; ++i) {478if (HASH_MATCH_MD5(hash, scene3DList[i].hash)) {479return i;480}481}482483uint16 id = -1;484for (id = 0; id < SCENE3D_COUNT; ++id) {485if (scene3DList[id].scope == SCOPE_NONE)486break;487}488489if (id >= SCENE3D_COUNT)490return -1;491492Scene3D *scene = &scene3DList[id];493494if (vertexLimit > SCENE3D_VERT_COUNT || !vertexLimit)495vertexLimit = SCENE3D_VERT_COUNT;496497scene->scope = scope;498HASH_COPY_MD5(scene->hash, hash);499scene->vertLimit = vertexLimit;500scene->faceCount = 6;501502scene->projectionX = 8;503scene->projectionY = 8;504AllocateStorage((void **)&scene->vertices, sizeof(Scene3DVertex) * vertexLimit, DATASET_STG, true);505AllocateStorage((void **)&scene->normals, sizeof(Scene3DVertex) * vertexLimit, DATASET_STG, true);506AllocateStorage((void **)&scene->faceVertCounts, sizeof(uint8) * vertexLimit, DATASET_STG, true);507AllocateStorage((void **)&scene->faceBuffer, sizeof(Scene3DFace) * vertexLimit, DATASET_STG, true);508509return id;510}511void RSDK::AddModelToScene(uint16 modelFrames, uint16 sceneIndex, uint8 drawMode, Matrix *matWorld, Matrix *matNormals, color color)512{513if (modelFrames < MODEL_COUNT && sceneIndex < SCENE3D_COUNT) {514if (matWorld) {515Model *mdl = &modelList[modelFrames];516Scene3D *scn = &scene3DList[sceneIndex];517uint16 *indices = mdl->indices;518int32 vertID = scn->vertexCount;519uint8 *faceVertCounts = &scn->faceVertCounts[scn->faceCount];520int32 indCnt = mdl->indexCount;521if (scn->vertLimit - vertID >= indCnt) {522scn->vertexCount += mdl->indexCount;523scn->drawMode = drawMode;524scn->faceCount += indCnt / mdl->faceVertCount;525526int32 i = 0;527int32 f = 0;528switch (mdl->flags) {529default:530case MODEL_NOFLAGS:531case MODEL_USECOLOURS:532for (; i < mdl->indexCount;) {533faceVertCounts[f++] = mdl->faceVertCount;534535for (int32 c = 0; c < mdl->faceVertCount; ++c) {536ModelVertex *modelVert = &mdl->vertices[indices[i++]];537Scene3DVertex *vertex = &scn->vertices[vertID++];538539vertex->x = matWorld->values[0][3] + (modelVert->z * matWorld->values[0][2] >> 8)540+ (matWorld->values[0][0] * modelVert->x >> 8) + (matWorld->values[0][1] * modelVert->y >> 8);541vertex->y = matWorld->values[1][3] + (modelVert->y * matWorld->values[1][1] >> 8)542+ (modelVert->z * matWorld->values[1][2] >> 8) + (matWorld->values[1][0] * modelVert->x >> 8);543vertex->z = matWorld->values[2][3] + ((modelVert->x * matWorld->values[2][0]) >> 8)544+ ((matWorld->values[2][2] * modelVert->z >> 8) + (matWorld->values[2][1] * modelVert->y >> 8));545546vertex->color = color;547}548}549break;550551case MODEL_USENORMALS:552if (matNormals) {553for (; i < mdl->indexCount;) {554faceVertCounts[f++] = mdl->faceVertCount;555556for (int32 c = 0; c < mdl->faceVertCount; ++c) {557ModelVertex *modelVert = &mdl->vertices[indices[i++]];558Scene3DVertex *vertex = &scn->vertices[vertID++];559560vertex->x = matWorld->values[0][3] + (modelVert->z * matWorld->values[0][2] >> 8)561+ (modelVert->x * matWorld->values[0][0] >> 8) + (modelVert->y * matWorld->values[0][1] >> 8);562vertex->y = matWorld->values[1][3] + (modelVert->y * matWorld->values[1][1] >> 8)563+ (matWorld->values[1][0] * modelVert->x >> 8) + (modelVert->z * matWorld->values[1][2] >> 8);564vertex->z = matWorld->values[2][3] + (modelVert->x * matWorld->values[2][0] >> 8)565+ (matWorld->values[2][2] * modelVert->z >> 8) + (matWorld->values[2][1] * modelVert->y >> 8);566567vertex->nx = (modelVert->nz * matNormals->values[0][2] >> 8) + (modelVert->nx * matNormals->values[0][0] >> 8)568+ (matNormals->values[0][1] * modelVert->ny >> 8);569vertex->ny = (modelVert->ny * matNormals->values[1][1] >> 8) + (modelVert->nz * matNormals->values[1][2] >> 8)570+ (modelVert->nx * matNormals->values[1][0] >> 8);571vertex->nz =572((modelVert->ny * matNormals->values[2][1]) >> 8)573+ ((matNormals->values[2][0] * modelVert->nx >> 8) + (modelVert->nz * matNormals->values[2][2] >> 8));574575vertex->color = color;576}577}578}579else {580for (; i < mdl->indexCount;) {581faceVertCounts[f++] = mdl->faceVertCount;582583for (int32 c = 0; c < mdl->faceVertCount; ++c) {584ModelVertex *modelVert = &mdl->vertices[indices[i++]];585Scene3DVertex *vertex = &scn->vertices[vertID++];586587vertex->x = matWorld->values[0][3] + (modelVert->z * matWorld->values[0][2] >> 8)588+ (matWorld->values[0][0] * modelVert->x >> 8) + (matWorld->values[0][1] * modelVert->y >> 8);589vertex->y = matWorld->values[1][3] + (modelVert->y * matWorld->values[1][1] >> 8)590+ (modelVert->z * matWorld->values[1][2] >> 8) + (matWorld->values[1][0] * modelVert->x >> 8);591vertex->z = matWorld->values[2][3] + ((matWorld->values[2][2] * modelVert->z) >> 8)592+ ((matWorld->values[2][0] * modelVert->x >> 8) + (matWorld->values[2][1] * modelVert->y >> 8));593594vertex->color = color;595}596}597}598break;599600case MODEL_USENORMALS | MODEL_USECOLOURS:601if (matNormals) {602for (; i < mdl->indexCount;) {603faceVertCounts[f++] = mdl->faceVertCount;604605for (int32 c = 0; c < mdl->faceVertCount; ++c) {606ModelVertex *modelVert = &mdl->vertices[indices[i]];607Color *modelColor = &mdl->colors[indices[i++]];608Scene3DVertex *vertex = &scn->vertices[vertID++];609610vertex->x = matWorld->values[0][3] + (matWorld->values[0][2] * modelVert->z >> 8)611+ (modelVert->y * matWorld->values[0][1] >> 8) + (matWorld->values[0][0] * modelVert->x >> 8);612vertex->y = matWorld->values[1][3] + (matWorld->values[1][2] * modelVert->z >> 8)613+ (modelVert->y * matWorld->values[1][1] >> 8) + (matWorld->values[1][0] * modelVert->x >> 8);614vertex->z = matWorld->values[2][3] + (modelVert->x * matWorld->values[2][0] >> 8)615+ (modelVert->y * matWorld->values[2][1] >> 8) + (matWorld->values[2][2] * modelVert->z >> 8);616617vertex->nx = (matNormals->values[0][0] * modelVert->nx >> 8) + (modelVert->ny * matNormals->values[0][1] >> 8)618+ (matNormals->values[0][2] * modelVert->nz >> 8);619vertex->ny = (matNormals->values[1][0] * modelVert->nx >> 8) + (modelVert->ny * matNormals->values[1][1] >> 8)620+ (matNormals->values[1][2] * modelVert->nz >> 8);621vertex->nz =622((matNormals->values[2][2] * modelVert->nz) >> 8)623+ ((modelVert->ny * matNormals->values[2][1] >> 8) + (matNormals->values[2][0] * modelVert->nx >> 8));624625vertex->color = modelColor->color;626}627}628}629else {630for (; i < mdl->indexCount;) {631faceVertCounts[f++] = mdl->faceVertCount;632633for (int32 c = 0; c < mdl->faceVertCount; ++c) {634ModelVertex *modelVert = &mdl->vertices[indices[i]];635Color *modelColor = &mdl->colors[indices[i++]];636Scene3DVertex *vertex = &scn->vertices[vertID++];637638vertex->x = matWorld->values[0][3] + (matWorld->values[0][0] * modelVert->x >> 8)639+ (modelVert->y * matWorld->values[0][1] >> 8) + (modelVert->z * matWorld->values[0][2] >> 8);640vertex->y = matWorld->values[1][3] + (modelVert->z * matWorld->values[1][2] >> 8)641+ (matWorld->values[1][0] * modelVert->x >> 8) + (modelVert->y * matWorld->values[1][1] >> 8);642vertex->z = matWorld->values[2][3] + (matWorld->values[2][2] * modelVert->z >> 8)643+ (modelVert->y * matWorld->values[2][1] >> 8) + (modelVert->x * matWorld->values[2][0] >> 8);644645vertex->color = modelColor->color;646}647}648}649break;650}651}652}653}654}655void RSDK::AddMeshFrameToScene(uint16 modelFrames, uint16 sceneIndex, Animator *animator, uint8 drawMode, Matrix *matWorld, Matrix *matNormals,656color color)657{658if (modelFrames < MODEL_COUNT && sceneIndex < SCENE3D_COUNT) {659if (matWorld && animator) {660Model *mdl = &modelList[modelFrames];661Scene3D *scn = &scene3DList[sceneIndex];662uint16 *indices = mdl->indices;663int32 vertID = scn->vertexCount;664uint8 *faceVertCounts = &scn->faceVertCounts[scn->faceCount];665int32 indCnt = mdl->indexCount;666if (scn->vertLimit - vertID >= indCnt) {667scn->vertexCount += mdl->indexCount;668scn->drawMode = drawMode;669scn->faceCount += indCnt / mdl->faceVertCount;670671int32 nextFrame = animator->frameID + 1;672if (nextFrame >= animator->frameCount)673nextFrame = animator->loopIndex;674int32 frameOffset = animator->frameID * mdl->vertCount;675int32 nextFrameOffset = nextFrame * mdl->vertCount;676677int32 i = 0;678int32 f = 0;679int32 interpolate = animator->timer;680switch (mdl->flags) {681default:682case MODEL_NOFLAGS:683case MODEL_USECOLOURS:684for (; i < mdl->indexCount;) {685faceVertCounts[f++] = mdl->faceVertCount;686687for (int32 c = 0; c < mdl->faceVertCount; ++c) {688ModelVertex *frameVert = &mdl->vertices[frameOffset + indices[i]];689ModelVertex *nextFrameVert = &mdl->vertices[nextFrameOffset + indices[i]];690int32 x = frameVert->x + ((interpolate * (nextFrameVert->x - frameVert->x)) >> 8);691int32 y = frameVert->y + ((interpolate * (nextFrameVert->y - frameVert->y)) >> 8);692int32 z = frameVert->z + ((interpolate * (nextFrameVert->z - frameVert->z)) >> 8);693i++;694Scene3DVertex *vertex = &scn->vertices[vertID++];695vertex->x = matWorld->values[0][3] + (z * matWorld->values[0][2] >> 8) + (matWorld->values[0][0] * x >> 8)696+ (matWorld->values[0][1] * y >> 8);697vertex->y = matWorld->values[1][3] + (y * matWorld->values[1][1] >> 8) + (z * matWorld->values[1][2] >> 8)698+ (matWorld->values[1][0] * x >> 8);699vertex->z = matWorld->values[2][3] + ((x * matWorld->values[2][0]) >> 8)700+ ((matWorld->values[2][2] * z >> 8) + (matWorld->values[2][1] * y >> 8));701vertex->color = color;702}703}704break;705706case MODEL_USENORMALS:707if (matNormals) {708for (; i < mdl->indexCount;) {709faceVertCounts[f++] = mdl->faceVertCount;710711for (int32 c = 0; c < mdl->faceVertCount; ++c) {712ModelVertex *frameVert = &mdl->vertices[frameOffset + indices[i]];713ModelVertex *nextFrameVert = &mdl->vertices[nextFrameOffset + indices[i]];714int32 x = frameVert->x + ((interpolate * (nextFrameVert->x - frameVert->x)) >> 8);715int32 y = frameVert->y + ((interpolate * (nextFrameVert->y - frameVert->y)) >> 8);716int32 z = frameVert->z + ((interpolate * (nextFrameVert->z - frameVert->z)) >> 8);717int32 nx = frameVert->nx + ((interpolate * (nextFrameVert->nx - frameVert->nx)) >> 8);718int32 ny = frameVert->ny + ((interpolate * (nextFrameVert->ny - frameVert->ny)) >> 8);719int32 nz = frameVert->nz + ((interpolate * (nextFrameVert->nz - frameVert->nz)) >> 8);720i++;721722Scene3DVertex *vertex = &scn->vertices[vertID++];723vertex->x = matWorld->values[0][3] + (z * matWorld->values[0][2] >> 8) + (x * matWorld->values[0][0] >> 8)724+ (y * matWorld->values[0][1] >> 8);725vertex->y = matWorld->values[1][3] + (y * matWorld->values[1][1] >> 8) + (matWorld->values[1][0] * x >> 8)726+ (z * matWorld->values[1][2] >> 8);727vertex->z = matWorld->values[2][3] + (x * matWorld->values[2][0] >> 8) + (matWorld->values[2][2] * z >> 8)728+ (matWorld->values[2][1] * y >> 8);729vertex->nx = (nz * matNormals->values[0][2] >> 8) + (nx * matNormals->values[0][0] >> 8)730+ (matNormals->values[0][1] * ny >> 8);731vertex->ny = (ny * matNormals->values[1][1] >> 8) + (nz * matNormals->values[1][2] >> 8)732+ (nx * matNormals->values[1][0] >> 8);733vertex->nz = ((ny * matNormals->values[2][1]) >> 8)734+ ((matNormals->values[2][0] * nx >> 8) + (nz * matNormals->values[2][2] >> 8));735vertex->color = color;736}737}738}739else {740for (; i < mdl->indexCount;) {741faceVertCounts[f++] = mdl->faceVertCount;742743for (int32 c = 0; c < mdl->faceVertCount; ++c) {744ModelVertex *frameVert = &mdl->vertices[frameOffset + indices[i]];745ModelVertex *nextFrameVert = &mdl->vertices[nextFrameOffset + indices[i]];746int32 x = frameVert->x + ((interpolate * (nextFrameVert->x - frameVert->x)) >> 8);747int32 y = frameVert->y + ((interpolate * (nextFrameVert->y - frameVert->y)) >> 8);748int32 z = frameVert->z + ((interpolate * (nextFrameVert->z - frameVert->z)) >> 8);749i++;750Scene3DVertex *vertex = &scn->vertices[vertID++];751vertex->x = matWorld->values[0][3] + (z * matWorld->values[0][2] >> 8) + (matWorld->values[0][0] * x >> 8)752+ (matWorld->values[0][1] * y >> 8);753vertex->y = matWorld->values[1][3] + (y * matWorld->values[1][1] >> 8) + (z * matWorld->values[1][2] >> 8)754+ (matWorld->values[1][0] * x >> 8);755vertex->z = matWorld->values[2][3] + ((matWorld->values[2][2] * z) >> 8)756+ ((matWorld->values[2][0] * x >> 8) + (matWorld->values[2][1] * y >> 8));757vertex->color = color;758}759}760}761break;762763case MODEL_USENORMALS | MODEL_USECOLOURS:764if (matNormals) {765for (; i < mdl->indexCount;) {766faceVertCounts[f++] = mdl->faceVertCount;767768for (int32 c = 0; c < mdl->faceVertCount; ++c) {769ModelVertex *frameVert = &mdl->vertices[frameOffset + indices[i]];770ModelVertex *nextFrameVert = &mdl->vertices[nextFrameOffset + indices[i]];771int32 x = frameVert->x + ((interpolate * (nextFrameVert->x - frameVert->x)) >> 8);772int32 y = frameVert->y + ((interpolate * (nextFrameVert->y - frameVert->y)) >> 8);773int32 z = frameVert->z + ((interpolate * (nextFrameVert->z - frameVert->z)) >> 8);774int32 nx = frameVert->nx + ((interpolate * (nextFrameVert->nx - frameVert->nx)) >> 8);775int32 ny = frameVert->ny + ((interpolate * (nextFrameVert->ny - frameVert->ny)) >> 8);776int32 nz = frameVert->nz + ((interpolate * (nextFrameVert->nz - frameVert->nz)) >> 8);777778Color *modelColor = &mdl->colors[indices[i++]];779Scene3DVertex *vertex = &scn->vertices[vertID++];780vertex->x = matWorld->values[0][3] + (matWorld->values[0][2] * z >> 8) + (y * matWorld->values[0][1] >> 8)781+ (matWorld->values[0][0] * x >> 8);782vertex->y = matWorld->values[1][3] + (matWorld->values[1][2] * z >> 8) + (y * matWorld->values[1][1] >> 8)783+ (matWorld->values[1][0] * x >> 8);784vertex->z = matWorld->values[2][3] + (x * matWorld->values[2][0] >> 8) + (y * matWorld->values[2][1] >> 8)785+ (matWorld->values[2][2] * z >> 8);786vertex->nx = (matNormals->values[0][0] * nx >> 8) + (ny * matNormals->values[0][1] >> 8)787+ (matNormals->values[0][2] * nz >> 8);788vertex->ny = (matNormals->values[1][0] * nx >> 8) + (ny * matNormals->values[1][1] >> 8)789+ (matNormals->values[1][2] * nz >> 8);790vertex->nz = ((matNormals->values[2][2] * nz) >> 8)791+ ((ny * matNormals->values[2][1] >> 8) + (matNormals->values[2][0] * nx >> 8));792vertex->color = modelColor->color;793}794}795}796else {797for (; i < mdl->indexCount;) {798faceVertCounts[f++] = mdl->faceVertCount;799800for (int32 c = 0; c < mdl->faceVertCount; ++c) {801ModelVertex *frameVert = &mdl->vertices[frameOffset + indices[i]];802ModelVertex *nextFrameVert = &mdl->vertices[nextFrameOffset + indices[i]];803int32 x = frameVert->x + ((interpolate * (nextFrameVert->x - frameVert->x)) >> 8);804int32 y = frameVert->y + ((interpolate * (nextFrameVert->y - frameVert->y)) >> 8);805int32 z = frameVert->z + ((interpolate * (nextFrameVert->z - frameVert->z)) >> 8);806Color *modelColor = &mdl->colors[indices[i++]];807Scene3DVertex *vertex = &scn->vertices[vertID++];808vertex->x = matWorld->values[0][3] + (matWorld->values[0][0] * x >> 8) + (y * matWorld->values[0][1] >> 8)809+ (z * matWorld->values[0][2] >> 8);810vertex->y = matWorld->values[1][3] + (z * matWorld->values[1][2] >> 8) + (matWorld->values[1][0] * x >> 8)811+ (y * matWorld->values[1][1] >> 8);812vertex->z = matWorld->values[2][3] + (matWorld->values[2][2] * z >> 8) + (y * matWorld->values[2][1] >> 8)813+ (x * matWorld->values[2][0] >> 8);814vertex->color = modelColor->color;815}816}817}818break;819}820}821}822}823}824825void RSDK::Draw3DScene(uint16 sceneID)826{827if (sceneID < SCENE3D_COUNT) {828Entity *entity = sceneInfo.entity;829Scene3D *scn = &scene3DList[sceneID];830831// Setup face buffer.832// Each face's depth is an average of the depth of its vertices.833Scene3DVertex *vertices = scn->vertices;834Scene3DFace *faceBuffer = scn->faceBuffer;835uint8 *faceVertCounts = scn->faceVertCounts;836837int32 vertIndex = 0;838for (int32 i = 0; i < scn->faceCount; ++i) {839switch (*faceVertCounts) {840default:841case 1:842faceBuffer->depth = vertices[0].z;843vertices += *faceVertCounts;844break;845846case 2:847faceBuffer->depth = vertices[0].z >> 1;848faceBuffer->depth += vertices[1].z >> 1;849vertices += 2;850break;851852case 3:853faceBuffer->depth = vertices[0].z >> 1;854faceBuffer->depth = (faceBuffer->depth + (vertices[1].z >> 1)) >> 1;855faceBuffer->depth += vertices[2].z >> 1;856vertices += 3;857break;858859case 4:860faceBuffer->depth = vertices[0].z >> 2;861faceBuffer->depth += vertices[1].z >> 2;862faceBuffer->depth += vertices[2].z >> 2;863faceBuffer->depth += vertices[3].z >> 2;864vertices += 4;865break;866}867868faceBuffer->index = vertIndex;869vertIndex += *faceVertCounts;870871++faceBuffer;872++faceVertCounts;873}874875// Sort the face buffer. This is needed so that the faces don't overlap each other incorrectly when they're rendered.876// This is an insertion sort, taken from here:877// https://web.archive.org/web/20110108233032/http://rosettacode.org/wiki/Sorting_algorithms/Insertion_sort#C878879Scene3DFace *a = scn->faceBuffer;880881int i, j;882Scene3DFace temp;883884for(i=1; i<scn->faceCount; i++)885{886temp = a[i];887j = i-1;888while(j>=0 && a[j].depth < temp.depth)889{890a[j+1] = a[j];891j -= 1;892}893a[j+1] = temp;894}895896// Finally, display the faces.897898uint8 *vertCnt = scn->faceVertCounts;899Vector2 vertPos[4];900uint32 vertClrs[4];901902switch (scn->drawMode) {903default: break;904905case S3D_WIREFRAME:906for (int32 f = 0; f < scn->faceCount; ++f) {907Scene3DVertex *drawVert = &scn->vertices[scn->faceBuffer[f].index];908for (int32 v = 0; v < *vertCnt - 1; ++v) {909DrawLine(drawVert[v + 0].x << 8, drawVert[v + 0].y << 8, drawVert[v + 1].x << 8, drawVert[v + 1].y << 8, drawVert[0].color,910entity->alpha, entity->inkEffect, false);911}912DrawLine(drawVert[0].x << 8, drawVert[0].y << 8, drawVert[*vertCnt - 1].x << 8, drawVert[*vertCnt - 1].y << 8, drawVert[0].color,913entity->alpha, entity->inkEffect, false);914vertCnt++;915}916break;917918case S3D_SOLIDCOLOR:919for (int32 f = 0; f < scn->faceCount; ++f) {920Scene3DVertex *drawVert = &scn->vertices[scn->faceBuffer[f].index];921for (int32 v = 0; v < *vertCnt; ++v) {922vertPos[v].x = (drawVert[v].x << 8) - (currentScreen->position.x << 16);923vertPos[v].y = (drawVert[v].y << 8) - (currentScreen->position.y << 16);924}925DrawFace(vertPos, *vertCnt, (drawVert->color >> 16) & 0xFF, (drawVert->color >> 8) & 0xFF, (drawVert->color >> 0) & 0xFF,926entity->alpha, entity->inkEffect);927vertCnt++;928}929break;930931// Might have been reserved for textures?932// not sure about this, just a guess based on tex coords existing in the model format spec933case S3D_UNUSED_1: break;934case S3D_UNUSED_2: break;935936case S3D_WIREFRAME_SHADED:937for (int32 f = 0; f < scn->faceCount; ++f) {938Scene3DVertex *drawVert = &scn->vertices[scn->faceBuffer[f].index];939int32 vertCount = *vertCnt;940941int32 ny1 = 0;942for (int32 v = 0; v < vertCount; ++v) {943ny1 += drawVert[v].ny;944}945946int32 normal = ny1 / vertCount;947int32 normalVal = (normal >> 2) * (abs(normal) >> 2);948949int32 specular = normalVal >> 6 >> scn->specularIntensityX;950specular = CLAMP(specular, 0x00, 0xFF);951int32 r = specular + ((int32)((drawVert->color >> 16) & 0xFF) * ((normal >> 10) + scn->diffuseX) >> scn->diffuseIntensityX);952953specular = normalVal >> 6 >> scn->specularIntensityY;954specular = CLAMP(specular, 0x00, 0xFF);955int32 g = specular + ((int32)((drawVert->color >> 8) & 0xFF) * ((normal >> 10) + scn->diffuseY) >> scn->diffuseIntensityY);956957specular = normalVal >> 6 >> scn->specularIntensityZ;958specular = CLAMP(specular, 0x00, 0xFF);959int32 b = specular + ((int32)((drawVert->color >> 0) & 0xFF) * ((normal >> 10) + scn->diffuseZ) >> scn->diffuseIntensityZ);960961r = CLAMP(r, 0x00, 0xFF);962g = CLAMP(g, 0x00, 0xFF);963b = CLAMP(b, 0x00, 0xFF);964965uint32 color = (r << 16) | (g << 8) | (b << 0);966967for (int32 v = 0; v < vertCount - 1; ++v) {968DrawLine(drawVert[v + 0].x << 8, drawVert[v + 0].y << 8, drawVert[v + 1].x << 8, drawVert[v + 1].y << 8, color, entity->alpha,969entity->inkEffect, false);970}971DrawLine(drawVert[vertCount - 1].x << 8, drawVert[vertCount - 1].y << 8, drawVert[0].x << 8, drawVert[0].y << 8, color,972entity->alpha, entity->inkEffect, false);973974vertCnt++;975}976break;977978case S3D_SOLIDCOLOR_SHADED:979for (int32 f = 0; f < scn->faceCount; ++f) {980Scene3DVertex *drawVert = &scn->vertices[scn->faceBuffer[f].index];981int32 vertCount = *vertCnt;982983int32 ny = 0;984for (int32 v = 0; v < vertCount; ++v) {985ny += drawVert[v].ny;986vertPos[v].x = (drawVert[v].x << 8) - (currentScreen->position.x << 16);987vertPos[v].y = (drawVert[v].y << 8) - (currentScreen->position.y << 16);988}989990int32 normal = ny / vertCount;991int32 normalVal = (normal >> 2) * (abs(normal) >> 2);992993int32 specular = normalVal >> 6 >> scn->specularIntensityX;994specular = CLAMP(specular, 0x00, 0xFF);995int32 r = specular + ((int32)((drawVert->color >> 16) & 0xFF) * ((normal >> 10) + scn->diffuseX) >> scn->diffuseIntensityX);996997specular = normalVal >> 6 >> scn->specularIntensityY;998specular = CLAMP(specular, 0x00, 0xFF);999int32 g = specular + ((int32)((drawVert->color >> 8) & 0xFF) * ((normal >> 10) + scn->diffuseY) >> scn->diffuseIntensityY);10001001specular = normalVal >> 6 >> scn->specularIntensityZ;1002specular = CLAMP(specular, 0x00, 0xFF);1003int32 b = specular + ((int32)((drawVert->color >> 0) & 0xFF) * ((normal >> 10) + scn->diffuseZ) >> scn->diffuseIntensityZ);10041005r = CLAMP(r, 0x00, 0xFF);1006g = CLAMP(g, 0x00, 0xFF);1007b = CLAMP(b, 0x00, 0xFF);10081009uint32 color = (r << 16) | (g << 8) | (b << 0);10101011drawVert = &scn->vertices[scn->faceBuffer[f].index];1012DrawFace(vertPos, *vertCnt, (color >> 16) & 0xFF, (color >> 8) & 0xFF, (color >> 0) & 0xFF, entity->alpha, entity->inkEffect);10131014vertCnt++;1015}1016break;10171018case S3D_SOLIDCOLOR_SHADED_BLENDED:1019for (int32 f = 0; f < scn->faceCount; ++f) {1020Scene3DVertex *drawVert = &scn->vertices[scn->faceBuffer[f].index];1021int32 vertCount = *vertCnt;10221023for (int32 v = 0; v < vertCount; ++v) {1024vertPos[v].x = (drawVert[v].x << 8) - (currentScreen->position.x << 16);1025vertPos[v].y = (drawVert[v].y << 8) - (currentScreen->position.y << 16);10261027int32 normal = drawVert[v].ny;1028int32 normalVal = (normal >> 2) * (abs(normal) >> 2);10291030int32 specular = (normalVal >> 6) >> scn->specularIntensityX;1031specular = CLAMP(specular, 0x00, 0xFF);1032int32 r = specular + ((int32)((drawVert->color >> 16) & 0xFF) * ((normal >> 10) + scn->diffuseX) >> scn->diffuseIntensityX);10331034specular = (normalVal >> 6) >> scn->specularIntensityY;1035specular = CLAMP(specular, 0x00, 0xFF);1036int32 g = specular + ((int32)((drawVert->color >> 8) & 0xFF) * ((normal >> 10) + scn->diffuseY) >> scn->diffuseIntensityY);10371038specular = (normalVal >> 6) >> scn->specularIntensityZ;1039specular = CLAMP(specular, 0x00, 0xFF);1040int32 b = specular + ((int32)((drawVert->color >> 0) & 0xFF) * ((normal >> 10) + scn->diffuseZ) >> scn->diffuseIntensityZ);10411042r = CLAMP(r, 0x00, 0xFF);1043g = CLAMP(g, 0x00, 0xFF);1044b = CLAMP(b, 0x00, 0xFF);10451046vertClrs[v] = (r << 16) | (g << 8) | (b << 0);1047}10481049DrawBlendedFace(vertPos, vertClrs, *vertCnt, entity->alpha, entity->inkEffect);10501051vertCnt++;1052}1053break;10541055case S3D_WIREFRAME_SCREEN:1056for (int32 f = 0; f < scn->faceCount; ++f) {1057Scene3DVertex *drawVert = &scn->vertices[scn->faceBuffer[f].index];10581059int32 v = 0;1060for (; v < *vertCnt && v < 0xFF; ++v) {1061int32 vertZ = drawVert[v].z;1062if (vertZ < 0x100) {1063v = 0xFF;1064}1065else {1066vertPos[v].x = currentScreen->center.x + (drawVert[v].x << scn->projectionX) / vertZ;1067vertPos[v].y = currentScreen->center.y - (drawVert[v].y << scn->projectionY) / vertZ;1068}1069}10701071if (v < 0xFF) {1072for (int32 v = 0; v < *vertCnt - 1; ++v) {1073DrawLine(vertPos[v + 0].x, vertPos[v + 0].y, vertPos[v + 1].x, vertPos[v + 1].y, drawVert[0].color, entity->alpha,1074entity->inkEffect, true);1075}1076DrawLine(vertPos[0].x, vertPos[0].y, vertPos[*vertCnt - 1].x, vertPos[*vertCnt - 1].y, drawVert[0].color, entity->alpha,1077entity->inkEffect, true);1078}10791080vertCnt++;1081}1082break;10831084case S3D_SOLIDCOLOR_SCREEN:1085for (int32 f = 0; f < scn->faceCount; ++f) {1086Scene3DVertex *drawVert = &scn->vertices[scn->faceBuffer[f].index];1087int32 vertCount = *vertCnt;10881089int32 v = 0;1090for (; v < vertCount && v < 0xFF; ++v) {1091int32 vertZ = drawVert[v].z;1092if (vertZ < 0x100) {1093v = 0xFF;1094}1095else {1096vertPos[v].x = (currentScreen->center.x << 16) + ((drawVert[v].x << scn->projectionX) / vertZ << 16);1097vertPos[v].y = (currentScreen->center.y << 16) - ((drawVert[v].y << scn->projectionY) / vertZ << 16);1098}1099}11001101if (v < 0xFF) {1102DrawFace(vertPos, *vertCnt, (drawVert[0].color >> 16) & 0xFF, (drawVert[0].color >> 8) & 0xFF,1103(drawVert[0].color >> 0) & 0xFF, entity->alpha, entity->inkEffect);1104}1105vertCnt++;1106}1107break;11081109case S3D_WIREFRAME_SHADED_SCREEN:1110for (int32 f = 0; f < scn->faceCount; ++f) {1111Scene3DVertex *drawVert = &scn->vertices[scn->faceBuffer[f].index];1112int32 vertCount = *vertCnt;11131114int32 v = 0;1115int32 ny1 = 0;1116for (; v < *vertCnt && v < 0xFF; ++v) {1117int32 vertZ = drawVert[v].z;1118if (vertZ < 0x100) {1119v = 0xFF;1120}1121else {1122vertPos[v].x = currentScreen->center.x + (drawVert[v].x << scn->projectionX) / vertZ;1123vertPos[v].y = currentScreen->center.y - (drawVert[v].y << scn->projectionY) / vertZ;1124ny1 += drawVert[v].ny;1125}1126}11271128if (v < 0xFF) {1129int32 normal = ny1 / vertCount;1130int32 normalVal = (normal >> 2) * (abs(normal) >> 2);11311132int32 specular = normalVal >> 6 >> scn->specularIntensityX;1133specular = CLAMP(specular, 0x00, 0xFF);1134int32 r = specular + ((int32)((drawVert[0].color >> 16) & 0xFF) * ((normal >> 10) + scn->diffuseX) >> scn->diffuseIntensityX);11351136specular = normalVal >> 6 >> scn->specularIntensityY;1137specular = CLAMP(specular, 0x00, 0xFF);1138int32 g = specular + ((int32)((drawVert[0].color >> 8) & 0xFF) * ((normal >> 10) + scn->diffuseY) >> scn->diffuseIntensityY);11391140specular = normalVal >> 6 >> scn->specularIntensityZ;1141specular = CLAMP(specular, 0x00, 0xFF);1142int32 b = specular + ((int32)((drawVert[0].color >> 0) & 0xFF) * ((normal >> 10) + scn->diffuseZ) >> scn->diffuseIntensityZ);11431144r = CLAMP(r, 0x00, 0xFF);1145g = CLAMP(g, 0x00, 0xFF);1146b = CLAMP(b, 0x00, 0xFF);11471148uint32 color = (r << 16) | (g << 8) | (b << 0);11491150for (int32 v = 0; v < *vertCnt - 1; ++v) {1151DrawLine(vertPos[v + 0].x, vertPos[v + 0].y, vertPos[v + 1].x, vertPos[v + 1].y, color, entity->alpha, entity->inkEffect,1152true);1153}1154DrawLine(vertPos[*vertCnt - 1].x, vertPos[*vertCnt - 1].y, vertPos[0].x, vertPos[0].y, color, entity->alpha,1155entity->inkEffect, true);1156}11571158vertCnt++;1159}1160break;11611162case S3D_SOLIDCOLOR_SHADED_SCREEN:1163for (int32 f = 0; f < scn->faceCount; ++f) {1164Scene3DVertex *drawVert = &scn->vertices[scn->faceBuffer[f].index];1165int32 vertCount = *vertCnt;11661167int32 v = 0;1168int32 ny = 0;1169for (; v < vertCount && v < 0xFF; ++v) {1170int32 vertZ = drawVert[v].z;1171if (vertZ < 0x100) {1172v = 0xFF;1173}1174else {1175vertPos[v].x = (currentScreen->center.x << 16) + ((drawVert[v].x << scn->projectionX) / vertZ << 16);1176vertPos[v].y = (currentScreen->center.y << 16) - ((drawVert[v].y << scn->projectionY) / vertZ << 16);1177ny += drawVert[v].ny;1178}1179}11801181if (v < 0xFF) {1182int32 normal = ny / vertCount;1183int32 normalVal = (normal >> 2) * (abs(normal) >> 2);11841185int32 specular = normalVal >> 6 >> scn->specularIntensityX;1186specular = CLAMP(specular, 0x00, 0xFF);1187int32 r = specular + ((int32)((drawVert[0].color >> 16) & 0xFF) * ((normal >> 10) + scn->diffuseX) >> scn->diffuseIntensityX);11881189specular = normalVal >> 6 >> scn->specularIntensityY;1190specular = CLAMP(specular, 0x00, 0xFF);1191int32 g = specular + ((int32)((drawVert[0].color >> 8) & 0xFF) * ((normal >> 10) + scn->diffuseY) >> scn->diffuseIntensityY);11921193specular = normalVal >> 6 >> scn->specularIntensityZ;1194specular = CLAMP(specular, 0x00, 0xFF);1195int32 b = specular + ((int32)((drawVert[0].color >> 0) & 0xFF) * ((normal >> 10) + scn->diffuseZ) >> scn->diffuseIntensityZ);11961197r = CLAMP(r, 0x00, 0xFF);1198g = CLAMP(g, 0x00, 0xFF);1199b = CLAMP(b, 0x00, 0xFF);12001201uint32 color = (r << 16) | (g << 8) | (b << 0);12021203drawVert = &scn->vertices[scn->faceBuffer[f].index];1204DrawFace(vertPos, *vertCnt, (color >> 16) & 0xFF, (color >> 8) & 0xFF, (color >> 0) & 0xFF, entity->alpha, entity->inkEffect);1205}12061207vertCnt++;1208}1209break;12101211case S3D_SOLIDCOLOR_SHADED_BLENDED_SCREEN:1212for (int32 f = 0; f < scn->faceCount; ++f) {1213Scene3DVertex *drawVert = &scn->vertices[scn->faceBuffer[f].index];1214int32 vertCount = *vertCnt;12151216int32 v = 0;1217for (; v < vertCount && v < 0xFF; ++v) {1218int32 vertZ = drawVert[v].z;1219if (vertZ < 0x100) {1220v = 0xFF;1221}1222else {1223vertPos[v].x = (currentScreen->center.x << 16) + ((drawVert[v].x << scn->projectionX) / vertZ << 16);1224vertPos[v].y = (currentScreen->center.y << 16) - ((drawVert[v].y << scn->projectionY) / vertZ << 16);12251226int32 normal = drawVert[v].ny;1227int32 normalVal = (normal >> 2) * (abs(normal) >> 2);12281229int32 specular = normalVal >> 6 >> scn->specularIntensityX;1230specular = CLAMP(specular, 0x00, 0xFF);1231int32 r =1232specular + ((int32)((drawVert[v].color >> 16) & 0xFF) * ((normal >> 10) + scn->diffuseX) >> scn->diffuseIntensityX);12331234specular = normalVal >> 6 >> scn->specularIntensityY;1235specular = CLAMP(specular, 0x00, 0xFF);1236int32 g =1237specular + ((int32)((drawVert[v].color >> 8) & 0xFF) * ((normal >> 10) + scn->diffuseY) >> scn->diffuseIntensityY);12381239specular = normalVal >> 6 >> scn->specularIntensityZ;1240specular = CLAMP(specular, 0x00, 0xFF);1241int32 b =1242specular + ((int32)((drawVert[v].color >> 0) & 0xFF) * ((normal >> 10) + scn->diffuseZ) >> scn->diffuseIntensityZ);12431244r = CLAMP(r, 0x00, 0xFF);1245g = CLAMP(g, 0x00, 0xFF);1246b = CLAMP(b, 0x00, 0xFF);12471248vertClrs[v] = (r << 16) | (g << 8) | (b << 0);1249}1250}12511252if (v < 0xFF) {1253drawVert = &scn->vertices[scn->faceBuffer[f].index];1254DrawBlendedFace(vertPos, vertClrs, *vertCnt, entity->alpha, entity->inkEffect);1255}12561257vertCnt++;1258}1259break;1260}1261}1262}126312641265