From 9d1a7b90872f02fa7b152eddb824be41a7269d4e Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Fri, 13 Sep 2019 19:25:31 -0500 Subject: [PATCH] Optimized object update. --- j3d/j3d.c | 437 +++++++++++++++++++++++++++-------------------------- j3d/j3d.h | 21 ++- j3d/main.c | 6 +- 3 files changed, 237 insertions(+), 227 deletions(-) diff --git a/j3d/j3d.c b/j3d/j3d.c index f2fe9dc..15f1f92 100644 --- a/j3d/j3d.c +++ b/j3d/j3d.c @@ -78,8 +78,7 @@ static float _j3VarAmbientLight = 6; static j3Matrix4x4T _j3VarCameraMatrix; static j3VertexT _j3VarCameraLocation; static j3FacingT _j3VarCameraAngle; -static bool _j3VarCameraLocationDirty = true; -static bool _j3VarCameraAngleDirty = true; +static j3DirtynessT _j3VarCameraHowDirty = DIRTYNESS_ALL; static j3VertexT _j3VarSunLocation; @@ -94,7 +93,7 @@ void j3CameraMove(float x, float y, float z) { _j3VarCameraLocation.x += x; _j3VarCameraLocation.y += y; _j3VarCameraLocation.z += z; - _j3VarCameraLocationDirty = true; + _j3VarCameraHowDirty |= DIRTYNESS_TRANSLATE; } @@ -102,7 +101,7 @@ void j3CameraMoveTo(float x, float y, float z) { _j3VarCameraLocation.x = x; _j3VarCameraLocation.y = y; _j3VarCameraLocation.z = z; - _j3VarCameraLocationDirty = true; + _j3VarCameraHowDirty |= DIRTYNESS_TRANSLATE; } @@ -110,7 +109,7 @@ void j3CameraRotate(float x, float y, float z) { _j3VarCameraAngle.x += x; _j3VarCameraAngle.y += y; _j3VarCameraAngle.z += z; - _j3VarCameraAngleDirty = true; + _j3VarCameraHowDirty |= DIRTYNESS_ROTATE; } @@ -118,7 +117,7 @@ void j3CameraRotateTo(float x, float y, float z) { _j3VarCameraAngle.x = (jint16)x; _j3VarCameraAngle.y = (jint16)y; _j3VarCameraAngle.z = (jint16)z; - _j3VarCameraAngleDirty = true; + _j3VarCameraHowDirty |= DIRTYNESS_ROTATE; } @@ -475,7 +474,7 @@ void _j3ObjectMove(j3ObjectT *o, float x, float y, float z) { o->position.x += x; o->position.y += y; o->position.z += z; - o->positionDirty = true; + o->howDirty |= DIRTYNESS_TRANSLATE; } @@ -483,7 +482,7 @@ void _j3ObjectMoveTo(j3ObjectT *o, float x, float y, float z) { o->position.x = x; o->position.y = y; o->position.z = z; - o->positionDirty = true; + o->howDirty |= DIRTYNESS_TRANSLATE; } @@ -500,9 +499,7 @@ void _j3ObjectReset(j3ObjectT *o) { o->scale.y = 1; o->scale.z = 1; - o->positionDirty = true; - o->rotationDirty = true; - o->scaleDirty = true; + o->howDirty = DIRTYNESS_ALL; } @@ -510,7 +507,7 @@ void _j3ObjectRotate(j3ObjectT *o, float x, float y, float z) { o->rotation.x += x; j3MathWrapBounds(o->rotation.x, 0, 360); o->rotation.y += y; j3MathWrapBounds(o->rotation.y, 0, 360); o->rotation.z += z; j3MathWrapBounds(o->rotation.z, 0, 360); - o->rotationDirty = true; + o->howDirty |= DIRTYNESS_ROTATE; } @@ -518,7 +515,7 @@ void _j3ObjectRotateTo(j3ObjectT *o, float x, float y, float z) { o->rotation.x = x; j3MathWrapBounds(o->rotation.x, 0, 360); o->rotation.y = y; j3MathWrapBounds(o->rotation.y, 0, 360); o->rotation.z = z; j3MathWrapBounds(o->rotation.z, 0, 360); - o->rotationDirty = true; + o->howDirty |= DIRTYNESS_ROTATE; } @@ -526,7 +523,7 @@ void _j3ObjectScale(j3ObjectT *o, float x, float y, float z) { o->scale.x += x; o->scale.y += y; o->scale.z += z; - o->scaleDirty = true; + o->howDirty |= DIRTYNESS_SCALE; } @@ -534,7 +531,7 @@ void _j3ObjectScaleTo(j3ObjectT *o, float x, float y, float z) { o->scale.x = x; o->scale.y = y; o->scale.z = z; - o->scaleDirty = true; + o->howDirty |= DIRTYNESS_SCALE; } @@ -563,220 +560,226 @@ void _j3ObjectUpdate(j3WorldT *w, jint16 index) { j3Matrix4x4T translate; j3ObjectT *o; - //***TODO*** Add more copies of data and make this very incremental - // original -> scaled -> rotated -> translated -> camera - o = &w->objects[index]; - // === ROTATION === - - x = (jint16)o->rotation.x; - y = (jint16)o->rotation.y; - z = (jint16)o->rotation.z; - - j3MathMatrix4x4Identity(final); - - // What angles are we rotating on? By knowing this we can optimize some. - if (x) axis += 4; - if (y) axis += 2; - if (z) axis += 1; - - switch (axis) { - case 1: // Final matrix = z - final[0][0] = cosTable[z]; - final[0][1] = sinTable[z]; - final[1][0] = -sinTable[z]; - final[1][1] = cosTable[z]; - for (i=0; ivertexCount; i++) { - o->vertices[i].world.x = o->vertices[i].local.x * final[0][0] + o->vertices[i].local.y * final[1][0]; - o->vertices[i].world.y = o->vertices[i].local.x * final[0][1] + o->vertices[i].local.y * final[1][1]; - o->vertices[i].world.z = o->vertices[i].local.z; - } - break; - - case 2: // Final matrix = y - final[0][0] = cosTable[y]; - final[0][2] = -sinTable[y]; - final[2][0] = sinTable[y]; - final[2][2] = cosTable[y]; - for (i=0; ivertexCount; i++) { - o->vertices[i].world.x = o->vertices[i].local.x * final[0][0] + o->vertices[i].local.z * final[2][0]; - o->vertices[i].world.y = o->vertices[i].local.y; - o->vertices[i].world.z = o->vertices[i].local.x * final[0][2] + o->vertices[i].local.z * final[2][2]; - } - break; - - case 3: // Final matrix = y * z - final[0][0] = cosTable[y] * cosTable[z]; - final[0][1] = cosTable[y] * sinTable[z]; - final[0][2] = -sinTable[y]; - - final[1][0] = -sinTable[z]; - final[1][1] = cosTable[z]; - - final[2][0] = sinTable[y] * cosTable[z]; - final[2][1] = sinTable[y] * sinTable[z]; - final[2][2] = cosTable[y]; - - for (i=0; ivertexCount; i++) { - o->vertices[i].world.x = o->vertices[i].local.x * final[0][0] + o->vertices[i].local.y * final[1][0] + o->vertices[i].local.z * final[2][0]; - o->vertices[i].world.y = o->vertices[i].local.x * final[0][1] + o->vertices[i].local.y * final[1][1] + o->vertices[i].local.z * final[2][1]; - o->vertices[i].world.z = o->vertices[i].local.x * final[0][2] + o->vertices[i].local.z * final[2][2]; - } - break; - - case 4: // Final matrix = x - final[1][1] = cosTable[x]; - final[1][2] = sinTable[x]; - final[2][1] = -sinTable[x]; - final[2][2] = cosTable[x]; - for (i=0; ivertexCount; i++) { - o->vertices[i].world.x = o->vertices[i].local.x; - o->vertices[i].world.y = o->vertices[i].local.y * final[1][1] + o->vertices[i].local.z * final[2][1]; - o->vertices[i].world.z = o->vertices[i].local.y * final[1][2] + o->vertices[i].local.z * final[2][2]; - } - break; - - case 5: // Final matrix = x * z - final[0][0] = cosTable[z]; - final[0][1] = sinTable[z]; - - final[1][0] = -cosTable[x] * sinTable[z]; - final[1][1] = cosTable[x] * cosTable[z]; - final[1][2] = sinTable[x]; - - final[2][0] = sinTable[x] * sinTable[z]; - final[2][1] = -sinTable[x] * cosTable[z]; - final[2][2] = cosTable[x]; - - for (i=0; ivertexCount; i++) { - o->vertices[i].world.x = o->vertices[i].local.x * final[0][0] + o->vertices[i].local.y * final[1][0] + o->vertices[i].local.z * final[2][0]; - o->vertices[i].world.y = o->vertices[i].local.x * final[0][1] + o->vertices[i].local.y * final[1][1] + o->vertices[i].local.z * final[2][1]; - o->vertices[i].world.z = o->vertices[i].local.y * final[1][2] + o->vertices[i].local.z * final[2][2]; - } - break; - - case 6: // Final matrix = x * y - final[0][0] = cosTable[y]; - final[0][2] = -sinTable[y]; - - final[1][0] = sinTable[x] * sinTable[y]; - final[1][1] = cosTable[x]; - final[1][2] = sinTable[x] * cosTable[y]; - - final[2][0] = cosTable[x] * sinTable[y]; - final[2][1] = -sinTable[x]; - final[2][2] = cosTable[x] * cosTable[y]; - - for (i=0; ivertexCount; i++) { - o->vertices[i].world.x = o->vertices[i].local.x * final[0][0] + o->vertices[i].local.y * final[1][0] + o->vertices[i].local.z * final[2][0]; - o->vertices[i].world.y = o->vertices[i].local.y * final[1][1] + o->vertices[i].local.z * final[2][1]; - o->vertices[i].world.z = o->vertices[i].local.x * final[0][2] + o->vertices[i].local.y * final[1][2] + o->vertices[i].local.z * final[2][2]; - } - break; - - case 7: // Final matrix = x * y * z - j3MathMatrix4x4Identity(rotateX); - rotateX[1][1] = cosTable[x]; - rotateX[1][2] = sinTable[x]; - rotateX[2][1] = -sinTable[x]; - rotateX[2][2] = cosTable[x]; - - j3MathMatrix4x4Identity(rotateY); - rotateY[0][0] = cosTable[y]; - rotateY[0][2] = -sinTable[y]; - rotateY[2][0] = sinTable[y]; - rotateY[2][2] = cosTable[y]; - - j3MathMatrix4x4Identity(rotateZ); - rotateZ[0][0] = cosTable[z]; - rotateZ[0][1] = sinTable[z]; - rotateZ[1][0] = -sinTable[z]; - rotateZ[1][1] = cosTable[z]; - - j3MathMatrix4x4Mult(rotateX, rotateY, temp); - j3MathMatrix4x4Mult(temp, rotateZ, final); - - for (i=0; ivertexCount; i++) { - o->vertices[i].world.x = o->vertices[i].local.x * final[0][0] + o->vertices[i].local.y * final[1][0] + o->vertices[i].local.z * final[2][0]; - o->vertices[i].world.y = o->vertices[i].local.x * final[0][1] + o->vertices[i].local.y * final[1][1] + o->vertices[i].local.z * final[2][1]; - o->vertices[i].world.z = o->vertices[i].local.x * final[0][2] + o->vertices[i].local.y * final[1][2] + o->vertices[i].local.z * final[2][2]; - } - break; - - default: - break; + // === SCALE === + if (o->howDirty & DIRTYNESS_SCALE) { + for (i=0; ivertexCount; i++) { + o->vertices[i].scaled.x = o->vertices[i].original.x * o->scale.x; + o->vertices[i].scaled.y = o->vertices[i].original.y * o->scale.y; + o->vertices[i].scaled.z = o->vertices[i].original.z * o->scale.z; + } } - // === SCALE & TRANSLATION === + // === ROTATION === + if (o->howDirty & DIRTYNESS_ROTATE) { + x = (jint16)o->rotation.x; + y = (jint16)o->rotation.y; + z = (jint16)o->rotation.z; - for (i=0; ivertexCount; i++) { - o->vertices[i].world.x = o->vertices[i].world.x * o->scale.x + o->position.x; - o->vertices[i].world.y = o->vertices[i].world.y * o->scale.y + o->position.y; - o->vertices[i].world.z = o->vertices[i].world.z * o->scale.z + o->position.z; + j3MathMatrix4x4Identity(final); + + // What angles are we rotating on? By knowing this we can optimize some. + if (x) axis += 4; + if (y) axis += 2; + if (z) axis += 1; + + switch (axis) { + case 1: // Final matrix = z + final[0][0] = cosTable[z]; + final[0][1] = sinTable[z]; + final[1][0] = -sinTable[z]; + final[1][1] = cosTable[z]; + for (i=0; ivertexCount; i++) { + o->vertices[i].rotated.x = o->vertices[i].scaled.x * final[0][0] + o->vertices[i].scaled.y * final[1][0]; + o->vertices[i].rotated.y = o->vertices[i].scaled.x * final[0][1] + o->vertices[i].scaled.y * final[1][1]; + o->vertices[i].rotated.z = o->vertices[i].scaled.z; + } + break; + + case 2: // Final matrix = y + final[0][0] = cosTable[y]; + final[0][2] = -sinTable[y]; + final[2][0] = sinTable[y]; + final[2][2] = cosTable[y]; + for (i=0; ivertexCount; i++) { + o->vertices[i].rotated.x = o->vertices[i].scaled.x * final[0][0] + o->vertices[i].scaled.z * final[2][0]; + o->vertices[i].rotated.y = o->vertices[i].scaled.y; + o->vertices[i].rotated.z = o->vertices[i].scaled.x * final[0][2] + o->vertices[i].scaled.z * final[2][2]; + } + break; + + case 3: // Final matrix = y * z + final[0][0] = cosTable[y] * cosTable[z]; + final[0][1] = cosTable[y] * sinTable[z]; + final[0][2] = -sinTable[y]; + + final[1][0] = -sinTable[z]; + final[1][1] = cosTable[z]; + + final[2][0] = sinTable[y] * cosTable[z]; + final[2][1] = sinTable[y] * sinTable[z]; + final[2][2] = cosTable[y]; + + for (i=0; ivertexCount; i++) { + o->vertices[i].rotated.x = o->vertices[i].scaled.x * final[0][0] + o->vertices[i].scaled.y * final[1][0] + o->vertices[i].scaled.z * final[2][0]; + o->vertices[i].rotated.y = o->vertices[i].scaled.x * final[0][1] + o->vertices[i].scaled.y * final[1][1] + o->vertices[i].scaled.z * final[2][1]; + o->vertices[i].rotated.z = o->vertices[i].scaled.x * final[0][2] + o->vertices[i].scaled.z * final[2][2]; + } + break; + + case 4: // Final matrix = x + final[1][1] = cosTable[x]; + final[1][2] = sinTable[x]; + final[2][1] = -sinTable[x]; + final[2][2] = cosTable[x]; + for (i=0; ivertexCount; i++) { + o->vertices[i].rotated.x = o->vertices[i].scaled.x; + o->vertices[i].rotated.y = o->vertices[i].scaled.y * final[1][1] + o->vertices[i].scaled.z * final[2][1]; + o->vertices[i].rotated.z = o->vertices[i].scaled.y * final[1][2] + o->vertices[i].scaled.z * final[2][2]; + } + break; + + case 5: // Final matrix = x * z + final[0][0] = cosTable[z]; + final[0][1] = sinTable[z]; + + final[1][0] = -cosTable[x] * sinTable[z]; + final[1][1] = cosTable[x] * cosTable[z]; + final[1][2] = sinTable[x]; + + final[2][0] = sinTable[x] * sinTable[z]; + final[2][1] = -sinTable[x] * cosTable[z]; + final[2][2] = cosTable[x]; + + for (i=0; ivertexCount; i++) { + o->vertices[i].rotated.x = o->vertices[i].scaled.x * final[0][0] + o->vertices[i].scaled.y * final[1][0] + o->vertices[i].scaled.z * final[2][0]; + o->vertices[i].rotated.y = o->vertices[i].scaled.x * final[0][1] + o->vertices[i].scaled.y * final[1][1] + o->vertices[i].scaled.z * final[2][1]; + o->vertices[i].rotated.z = o->vertices[i].scaled.y * final[1][2] + o->vertices[i].scaled.z * final[2][2]; + } + break; + + case 6: // Final matrix = x * y + final[0][0] = cosTable[y]; + final[0][2] = -sinTable[y]; + + final[1][0] = sinTable[x] * sinTable[y]; + final[1][1] = cosTable[x]; + final[1][2] = sinTable[x] * cosTable[y]; + + final[2][0] = cosTable[x] * sinTable[y]; + final[2][1] = -sinTable[x]; + final[2][2] = cosTable[x] * cosTable[y]; + + for (i=0; ivertexCount; i++) { + o->vertices[i].rotated.x = o->vertices[i].scaled.x * final[0][0] + o->vertices[i].scaled.y * final[1][0] + o->vertices[i].scaled.z * final[2][0]; + o->vertices[i].rotated.y = o->vertices[i].scaled.y * final[1][1] + o->vertices[i].scaled.z * final[2][1]; + o->vertices[i].rotated.z = o->vertices[i].scaled.x * final[0][2] + o->vertices[i].scaled.y * final[1][2] + o->vertices[i].scaled.z * final[2][2]; + } + break; + + case 7: // Final matrix = x * y * z + j3MathMatrix4x4Identity(rotateX); + rotateX[1][1] = cosTable[x]; + rotateX[1][2] = sinTable[x]; + rotateX[2][1] = -sinTable[x]; + rotateX[2][2] = cosTable[x]; + + j3MathMatrix4x4Identity(rotateY); + rotateY[0][0] = cosTable[y]; + rotateY[0][2] = -sinTable[y]; + rotateY[2][0] = sinTable[y]; + rotateY[2][2] = cosTable[y]; + + j3MathMatrix4x4Identity(rotateZ); + rotateZ[0][0] = cosTable[z]; + rotateZ[0][1] = sinTable[z]; + rotateZ[1][0] = -sinTable[z]; + rotateZ[1][1] = cosTable[z]; + + j3MathMatrix4x4Mult(rotateX, rotateY, temp); + j3MathMatrix4x4Mult(temp, rotateZ, final); + + for (i=0; ivertexCount; i++) { + o->vertices[i].rotated.x = o->vertices[i].scaled.x * final[0][0] + o->vertices[i].scaled.y * final[1][0] + o->vertices[i].scaled.z * final[2][0]; + o->vertices[i].rotated.y = o->vertices[i].scaled.x * final[0][1] + o->vertices[i].scaled.y * final[1][1] + o->vertices[i].scaled.z * final[2][1]; + o->vertices[i].rotated.z = o->vertices[i].scaled.x * final[0][2] + o->vertices[i].scaled.y * final[1][2] + o->vertices[i].scaled.z * final[2][2]; + } + break; + + default: + break; + } + } + + // === TRANSLATION === + if (o->howDirty & DIRTYNESS_TRANSLATE) { + for (i=0; ivertexCount; i++) { + o->vertices[i].translated.x = o->vertices[i].rotated.x + o->position.x; + o->vertices[i].translated.y = o->vertices[i].rotated.y + o->position.y; + o->vertices[i].translated.z = o->vertices[i].rotated.z + o->position.z; + } } // === CAMERA SPACE === + if ((_j3VarCameraHowDirty & DIRTYNESS_ROTATE) || (_j3VarCameraHowDirty & DIRTYNESS_TRANSLATE)) { + // Create the global inverse transformation matrix used to transform world coordinate to camera coordinates + j3MathMatrix4x4Identity(translate); + j3MathMatrix4x4Identity(rotateX); + j3MathMatrix4x4Identity(rotateY); + j3MathMatrix4x4Identity(rotateZ); - //***TODO*** Move this when we add multiple object stuff and re-do this function - // Create the global inverse transformation matrix used to transform world coordinate to camera coordinates - j3MathMatrix4x4Identity(translate); - j3MathMatrix4x4Identity(rotateX); - j3MathMatrix4x4Identity(rotateY); - j3MathMatrix4x4Identity(rotateZ); + translate[3][0] = -_j3VarCameraLocation.x; + translate[3][1] = -_j3VarCameraLocation.y; + translate[3][2] = -_j3VarCameraLocation.z; - translate[3][0] = -_j3VarCameraLocation.x; - translate[3][1] = -_j3VarCameraLocation.y; - translate[3][2] = -_j3VarCameraLocation.z; + // X matrix + rotateX[1][1] = ( cosTable[_j3VarCameraAngle.x]); + rotateX[1][2] = -( sinTable[_j3VarCameraAngle.x]); + rotateX[2][1] = -(-sinTable[_j3VarCameraAngle.x]); + rotateX[2][2] = ( cosTable[_j3VarCameraAngle.x]); - // X matrix - rotateX[1][1] = ( cosTable[_j3VarCameraAngle.x]); - rotateX[1][2] = -( sinTable[_j3VarCameraAngle.x]); - rotateX[2][1] = -(-sinTable[_j3VarCameraAngle.x]); - rotateX[2][2] = ( cosTable[_j3VarCameraAngle.x]); + // Y matrix + rotateY[0][0] = ( cosTable[_j3VarCameraAngle.y]); + rotateY[0][2] = -(-sinTable[_j3VarCameraAngle.y]); + rotateY[2][0] = -( sinTable[_j3VarCameraAngle.y]); + rotateY[2][2] = ( cosTable[_j3VarCameraAngle.y]); - // Y matrix - rotateY[0][0] = ( cosTable[_j3VarCameraAngle.y]); - rotateY[0][2] = -(-sinTable[_j3VarCameraAngle.y]); - rotateY[2][0] = -( sinTable[_j3VarCameraAngle.y]); - rotateY[2][2] = ( cosTable[_j3VarCameraAngle.y]); + // Z matrix + rotateZ[0][0] = ( cosTable[_j3VarCameraAngle.z]); + rotateZ[0][1] = -( sinTable[_j3VarCameraAngle.z]); + rotateZ[1][0] = -(-sinTable[_j3VarCameraAngle.z]); + rotateZ[1][1] = ( cosTable[_j3VarCameraAngle.z]); - // Z matrix - rotateZ[0][0] = ( cosTable[_j3VarCameraAngle.z]); - rotateZ[0][1] = -( sinTable[_j3VarCameraAngle.z]); - rotateZ[1][0] = -(-sinTable[_j3VarCameraAngle.z]); - rotateZ[1][1] = ( cosTable[_j3VarCameraAngle.z]); - - j3MathMatrix4x4Mult(translate, rotateX, result1); - j3MathMatrix4x4Mult(result1, rotateY, result2); - j3MathMatrix4x4Mult(result2, rotateZ, _j3VarCameraMatrix); - - _j3VarCameraLocationDirty = false; - _j3VarCameraAngleDirty = false; + j3MathMatrix4x4Mult(translate, rotateX, result1); + j3MathMatrix4x4Mult(result1, rotateY, result2); + j3MathMatrix4x4Mult(result2, rotateZ, _j3VarCameraMatrix); + _j3VarCameraHowDirty = DIRTYNESS_CLEAN; + } for (i=0; ivertexCount; i++) { o->vertices[i].camera.x = - o->vertices[i].world.x * _j3VarCameraMatrix[0][0] + - o->vertices[i].world.y * _j3VarCameraMatrix[1][0] + - o->vertices[i].world.z * _j3VarCameraMatrix[2][0] + + o->vertices[i].translated.x * _j3VarCameraMatrix[0][0] + + o->vertices[i].translated.y * _j3VarCameraMatrix[1][0] + + o->vertices[i].translated.z * _j3VarCameraMatrix[2][0] + _j3VarCameraMatrix[3][0]; o->vertices[i].camera.y = - o->vertices[i].world.x * _j3VarCameraMatrix[0][1] + - o->vertices[i].world.y * _j3VarCameraMatrix[1][1] + - o->vertices[i].world.z * _j3VarCameraMatrix[2][1] + + o->vertices[i].translated.x * _j3VarCameraMatrix[0][1] + + o->vertices[i].translated.y * _j3VarCameraMatrix[1][1] + + o->vertices[i].translated.z * _j3VarCameraMatrix[2][1] + _j3VarCameraMatrix[3][1]; o->vertices[i].camera.z = - o->vertices[i].world.x * _j3VarCameraMatrix[0][2] + - o->vertices[i].world.y * _j3VarCameraMatrix[1][2] + - o->vertices[i].world.z * _j3VarCameraMatrix[2][2] + + o->vertices[i].translated.x * _j3VarCameraMatrix[0][2] + + o->vertices[i].translated.y * _j3VarCameraMatrix[1][2] + + o->vertices[i].translated.z * _j3VarCameraMatrix[2][2] + _j3VarCameraMatrix[3][2]; } - // === REMOVE BACKFACES & LIGHT === + // === REMOVE BACKFACES & LIGHT === for (i=0; itriangleCount; i++) { // If the scale changed, we need a new normal length - if (o->scaleDirty) { + if (o->howDirty & DIRTYNESS_SCALE) { _j3ObjectUpdateNormalLength(o, (juint16)i); } // If it's two sided, there are no backfaces @@ -787,16 +790,16 @@ void _j3ObjectUpdate(j3WorldT *w, jint16 index) { vertex1 = o->triangles[i].index[1]; vertex2 = o->triangles[i].index[2]; // Vector u = v0->v1 - j3MathMakeVector3D((j3VertexT *)&o->vertices[vertex0].world, (j3VertexT *)&o->vertices[vertex1].world, (j3Vector3DT *)&u); + j3MathMakeVector3D((j3VertexT *)&o->vertices[vertex0].translated, (j3VertexT *)&o->vertices[vertex1].translated, (j3Vector3DT *)&u); // Vector v = v0->v2 - j3MathMakeVector3D((j3VertexT *)&o->vertices[vertex0].world, (j3VertexT *)&o->vertices[vertex2].world, (j3Vector3DT *)&v); + j3MathMakeVector3D((j3VertexT *)&o->vertices[vertex0].translated, (j3VertexT *)&o->vertices[vertex2].translated, (j3Vector3DT *)&v); // Normal v x u j3MathCrossProduct3D((j3Vector3DT *)&v, (j3Vector3DT *)&u, (j3Vector3DT *)&normal); // Compute the line of sight vector, since all coordinates are world all // object vertices are already relative to (0,0,0), thus - sight.x = _j3VarCameraLocation.x - o->vertices[vertex0].world.x; - sight.y = _j3VarCameraLocation.y - o->vertices[vertex0].world.y; - sight.z = _j3VarCameraLocation.z - o->vertices[vertex0].world.z; + sight.x = _j3VarCameraLocation.x - o->vertices[vertex0].translated.x; + sight.y = _j3VarCameraLocation.y - o->vertices[vertex0].translated.y; + sight.z = _j3VarCameraLocation.z - o->vertices[vertex0].translated.z; // Compute the dot product between line of sight vector and normal to surface dot = j3MathDotProduct3D((j3Vector3DT *)&normal, (j3Vector3DT *)&sight); @@ -843,9 +846,9 @@ void _j3ObjectUpdate(j3WorldT *w, jint16 index) { vertex1 = o->triangles[i].index[1]; vertex2 = o->triangles[i].index[2]; // Vector u = v0->v1 - j3MathMakeVector3D((j3VertexT *)&o->vertices[vertex0].world, (j3VertexT *)&o->vertices[vertex1].world, (j3Vector3DT *)&u); + j3MathMakeVector3D((j3VertexT *)&o->vertices[vertex0].translated, (j3VertexT *)&o->vertices[vertex1].translated, (j3Vector3DT *)&u); // Vector v = v0->v2 - j3MathMakeVector3D((j3VertexT *)&o->vertices[vertex0].world, (j3VertexT *)&o->vertices[vertex2].world, (j3Vector3DT *)&v); + j3MathMakeVector3D((j3VertexT *)&o->vertices[vertex0].translated, (j3VertexT *)&o->vertices[vertex2].translated, (j3Vector3DT *)&v); // Normal v x u j3MathCrossProduct3D((j3Vector3DT *)&v, (j3Vector3DT *)&u, (j3Vector3DT *)&normal); // Compute the dot product between the light source vector and normal vector to surface @@ -890,9 +893,7 @@ void _j3ObjectUpdate(j3WorldT *w, jint16 index) { // Z Sort the visible polygon list qsort((void *)w->polygons, w->polygonCount, sizeof(j3PolyListT), (j3qsortCastT)_j3PolyCompare); - o->positionDirty = false; - o->rotationDirty = false; - o->scaleDirty = false; + o->howDirty = DIRTYNESS_CLEAN; } @@ -909,8 +910,8 @@ void _j3ObjectUpdateNormalLength(j3ObjectT *object, juint16 triangle) { vertex1 = object->triangles[triangle].index[1]; vertex2 = object->triangles[triangle].index[2]; - j3MathMakeVector3D((j3VertexT *)&object->vertices[vertex0].local, (j3VertexT *)&object->vertices[vertex1].local, (j3Vector3DT *)&u); - j3MathMakeVector3D((j3VertexT *)&object->vertices[vertex0].local, (j3VertexT *)&object->vertices[vertex2].local, (j3Vector3DT *)&v); + j3MathMakeVector3D((j3VertexT *)&object->vertices[vertex0].scaled, (j3VertexT *)&object->vertices[vertex1].scaled, (j3Vector3DT *)&u); + j3MathMakeVector3D((j3VertexT *)&object->vertices[vertex0].scaled, (j3VertexT *)&object->vertices[vertex2].scaled, (j3Vector3DT *)&v); j3MathCrossProduct3D((j3Vector3DT *)&v, (j3Vector3DT *)&u, (j3Vector3DT *)&normal); // Compute magnitude of normal, take its inverse and multiply it by @@ -1342,9 +1343,9 @@ jint16 _j3WorldAddProp(j3WorldT **world, j3PropT *prop) { // Copy vertex data for (z=0; zpieces[y].vertexCount; z++) { - (*world)->objects[x].vertices[z].local.x = prop->pieces[y].vertices[z].x; - (*world)->objects[x].vertices[z].local.y = prop->pieces[y].vertices[z].y; - (*world)->objects[x].vertices[z].local.z = prop->pieces[y].vertices[z].z; + (*world)->objects[x].vertices[z].original.x = prop->pieces[y].vertices[z].x; + (*world)->objects[x].vertices[z].original.y = prop->pieces[y].vertices[z].y; + (*world)->objects[x].vertices[z].original.z = prop->pieces[y].vertices[z].z; } // Triangles diff --git a/j3d/j3d.h b/j3d/j3d.h index cb74799..aae60de 100644 --- a/j3d/j3d.h +++ b/j3d/j3d.h @@ -27,6 +27,14 @@ #include "joey.h" +typedef enum { + DIRTYNESS_CLEAN = 0x00, + DIRTYNESS_SCALE = 0x01, + DIRTYNESS_ROTATE = 0x03, + DIRTYNESS_TRANSLATE = 0x07, + DIRTYNESS_ALL = 0xFF +} j3DirtynessT; + typedef float j3Matrix4x4T[4][4]; typedef struct { @@ -42,9 +50,12 @@ typedef struct { } j3VertexT, j3Vector3DT; typedef struct { - j3VertexT local; // Original vertex positions - j3VertexT world; // After rotation, scale, translation (in that order) - j3VertexT camera; // Camera space + // original -> scaled -> rotated -> translated -> camera + j3VertexT original; // Original vertex positions + j3VertexT scaled; // After scaling + j3VertexT rotated; // After rotation (aka "local") + j3VertexT translated; // After translation (aka "world") + j3VertexT camera; // Camera space } j3CoordinatesT; typedef struct { @@ -74,9 +85,7 @@ typedef struct { j3VertexT position; // Position of object in world j3VertexT rotation; // Rotation of object in world j3VertexT scale; // Scale of object in world - bool positionDirty; // Did the position change? - bool rotationDirty; // Did the rotation change? - bool scaleDirty; // Did the scale change? + j3DirtynessT howDirty; // How much do we need to recalculate? } j3ObjectT; typedef struct { diff --git a/j3d/main.c b/j3d/main.c index f1f0797..4935b3a 100644 --- a/j3d/main.c +++ b/j3d/main.c @@ -105,9 +105,9 @@ int main(void) { for (y=0; yobjects[x].vertexCount; y++) { printf(" Vertex %d: %f %f %f\n", y, - (double)world->objects[x].vertices[y].local.x, - (double)world->objects[x].vertices[y].local.y, - (double)world->objects[x].vertices[y].local.z + (double)world->objects[x].vertices[y].original.x, + (double)world->objects[x].vertices[y].original.y, + (double)world->objects[x].vertices[y].original.z ); } printf(" Triangles: %d\n", world->objects[x].triangleCount);