From 63932bab34f1ed2d586d4dcb5962d626d297c4f8 Mon Sep 17 00:00:00 2001 From: Scott Duensing Date: Mon, 9 Sep 2019 22:01:23 -0500 Subject: [PATCH] "World" and "Prop" are now separate concepts. Lots of code cleanup and bug fixes. --- BuildTables/main.c | 4 +- j3d/j3d.c | 766 ++++++++++++++++++++++++++------------------- j3d/j3d.h | 158 ++++------ j3d/j3dtbls.h | 4 +- j3d/main.c | 38 ++- 5 files changed, 511 insertions(+), 459 deletions(-) diff --git a/BuildTables/main.c b/BuildTables/main.c index 9d6ac6b..50afd69 100644 --- a/BuildTables/main.c +++ b/BuildTables/main.c @@ -62,7 +62,7 @@ int main(void) { " * 3. This notice may not be removed or altered from any source distribution.\n" \ "*/\n\n\n" \ "#ifndef H_J3DTBLS_\n" \ - "#define H_J3DTBLS_\n\n\nstatic float sin_table[] = {\n\t" \ + "#define H_J3DTBLS_\n\n\nstatic float sinTable[] = {\n\t" \ ); // Build look-up tables for speed later @@ -82,7 +82,7 @@ int main(void) { } fprintf(out, "\n};\n\n"); if (pass == 0) { - fprintf(out, "static float cos_table[] = {\n\t"); + fprintf(out, "static float cosTable[] = {\n\t"); } } diff --git a/j3d/j3d.c b/j3d/j3d.c index 85e17b2..f2fe9dc 100644 --- a/j3d/j3d.c +++ b/j3d/j3d.c @@ -26,10 +26,9 @@ //***TODO*** -// Allow multiple objects to be loaded into a world +// Not all faces are rendering until they rotate out and back in // Store original vertex data so we can do local rotations and save them -// Rename verticies to vertices -// Remove _ from sin_table and cos_table +// Some fields like objectCount are juint16 but should be jint16 #include @@ -58,29 +57,30 @@ segment "j3d"; typedef int (*j3qsortCastT)(const void *, const void *); -int _j3PolyCompare(j3PolyListT *arg1, j3PolyListT *arg2); +// Private Prototypes +void _j3DrawTriangleBottom(jint16 x1, jint16 y1, jint16 x2,jint16 y2, jint16 x3, jint16 y3); +void _j3DrawTriangleTop(jint16 x1, jint16 y1, jint16 x2,jint16 y2, jint16 x3, jint16 y3); +void _j3ObjectUpdateNormalLength(j3ObjectT *object, juint16 triangle); +void _j3ObjectUpdate(j3WorldT *w, jint16 index); +int _j3PolyCompare(j3PolyListT *arg1, j3PolyListT *arg2); +bool _j3UtilClipLine(jint16 *x1, jint16 *y1, jint16 *x2, jint16 *y2); // Module global data -jint16 _j3VarClipMinX = 0; -jint16 _j3VarClipMinY = 0; -jint16 _j3VarClipMinZ = 100; -jint16 _j3VarClipMaxX = 319; -jint16 _j3VarClipMaxY = 199; -jint16 _j3VarClipMaxZ = 3000; -jint16 _j3VarViewDistance = 200; -float _j3VarAmbientLight = 6; -j3Matrix4x4T _j3VarCameraMatrix; -j3VertexT _j3VarCameraLocation; -j3FacingT _j3VarCameraAngle; -bool _j3VarCameraLocationDirty = true; -bool _j3VarCameraAngleDirty = true; -j3VertexT _j3VarSunLocation; - -//***TODO*** None of this should be global - put inside world -j3PolyListT *_j3Polygons = NULL; -juint16 _j3PolygonCount = 0; // Current visible polygons -juint16 _j3TriangleCount = 0; // Current triangles in world +static jint16 _j3VarClipMinX = 0; +static jint16 _j3VarClipMinY = 0; +static jint16 _j3VarClipMinZ = 100; +static jint16 _j3VarClipMaxX = 319; +static jint16 _j3VarClipMaxY = 199; +static jint16 _j3VarClipMaxZ = 3000; +static jint16 _j3VarViewDistance = 200; +static float _j3VarAmbientLight = 6; +static j3Matrix4x4T _j3VarCameraMatrix; +static j3VertexT _j3VarCameraLocation; +static j3FacingT _j3VarCameraAngle; +static bool _j3VarCameraLocationDirty = true; +static bool _j3VarCameraAngleDirty = true; +static j3VertexT _j3VarSunLocation; #define ASPECT_RATIO (float)0.8 @@ -90,59 +90,43 @@ juint16 _j3TriangleCount = 0; // Current triangles in world #define HALF_SCREEN_HEIGHT 100 -void _j3DrawSolid(j3ObjectT *o) { - jint16 t; - juint16 vertex1; - juint16 vertex2; - juint16 vertex3; - float x1; - float y1; - float z1; - float x2; - float y2; - float z2; - float x3; - float y3; - float z3; +void j3CameraMove(float x, float y, float z) { + _j3VarCameraLocation.x += x; + _j3VarCameraLocation.y += y; + _j3VarCameraLocation.z += z; + _j3VarCameraLocationDirty = true; +} - for (t=0; ttriangleCount; t++) { - // Is this triangle even visible? - if (!o->triangles[t].visible) { - continue; - } +void j3CameraMoveTo(float x, float y, float z) { + _j3VarCameraLocation.x = x; + _j3VarCameraLocation.y = y; + _j3VarCameraLocation.z = z; + _j3VarCameraLocationDirty = true; +} - vertex1 = o->triangles[t].index[0]; - vertex2 = o->triangles[t].index[1]; - vertex3 = o->triangles[t].index[2]; - z1 = o->verticies[vertex1].camera.z; - z2 = o->verticies[vertex2].camera.z; - z3 = o->verticies[vertex3].camera.z; +void j3CameraRotate(float x, float y, float z) { + _j3VarCameraAngle.x += x; + _j3VarCameraAngle.y += y; + _j3VarCameraAngle.z += z; + _j3VarCameraAngleDirty = true; +} - // Perform z clipping - if ((z1 < _j3VarClipMinZ && z2 < _j3VarClipMinZ && z3 < _j3VarClipMinZ) || (z1 > _j3VarClipMaxZ && z2 > _j3VarClipMaxZ && z3 > _j3VarClipMaxZ)) { - continue; - } - // Extract points of triangle - x1 = o->verticies[vertex1].camera.x; - y1 = o->verticies[vertex1].camera.y; - x2 = o->verticies[vertex2].camera.x; - y2 = o->verticies[vertex2].camera.y; - x3 = o->verticies[vertex3].camera.x; - y3 = o->verticies[vertex3].camera.y; +void j3CameraRotateTo(float x, float y, float z) { + _j3VarCameraAngle.x = (jint16)x; + _j3VarCameraAngle.y = (jint16)y; + _j3VarCameraAngle.z = (jint16)z; + _j3VarCameraAngleDirty = true; +} - // Screen position of points - x1 = HALF_SCREEN_WIDTH + x1 * _j3VarViewDistance / z1; - y1 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y1 * _j3VarViewDistance / z1; - x2 = HALF_SCREEN_WIDTH + x2 * _j3VarViewDistance / z2; - y2 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y2 * _j3VarViewDistance / z2; - x3 = HALF_SCREEN_WIDTH + x3 * _j3VarViewDistance / z3; - y3 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y3 * _j3VarViewDistance / z3; - j3DrawTriangle2D((jint16)x1, (jint16)y1, (jint16)x2, (jint16)y2, (jint16)x3, (jint16)y3, o->triangles[t].shade); - } +void j3CameraSetClippingBounds(jint16 x1, jint16 y1, jint16 x2, jint16 y2) { + _j3VarClipMinX = x1; j3MathCheckBounds(_j3VarClipMinX, 0, 319); + _j3VarClipMinY = y1; j3MathCheckBounds(_j3VarClipMinY, 0, 199); + _j3VarClipMaxX = x2; j3MathCheckBounds(_j3VarClipMaxX, 0, 319); + _j3VarClipMaxY = y2; j3MathCheckBounds(_j3VarClipMaxY, 0, 199); } @@ -364,57 +348,6 @@ void _j3DrawTriangleTop(jint16 x1, jint16 y1, jint16 x2,jint16 y2, jint16 x3, ji } -void _j3DrawWireframePair(j3ObjectT *o, juint16 v1, juint16 v2) { - float x1; - float y1; - float z1; - float x2; - float y2; - float z2; - jint16 ix1; - jint16 iy1; - jint16 ix2; - jint16 iy2; - j3VertexT v; - - v = o->verticies[v1].camera; - x1 = v.x; - y1 = v.y; - z1 = v.z; - - v = o->verticies[v2].camera; - x2 = v.x; - y2 = v.y; - z2 = v.z; - - x1 = HALF_SCREEN_WIDTH + x1 * _j3VarViewDistance / z1; - y1 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y1 * _j3VarViewDistance / z1; - - x2 = HALF_SCREEN_WIDTH + x2 * _j3VarViewDistance / z2; - y2 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y2 * _j3VarViewDistance / z2; - - ix1 = (jint16)x1; - iy1 = (jint16)y1; - ix2 = (jint16)x2; - iy2 = (jint16)y2; - - if (_j3UtilClipLine(&ix1, &iy1, &ix2, &iy2)) { - jlDrawLine(ix1, iy1, ix2, iy2); - } -} - - -void _j3DrawWireframe(j3ObjectT *o) { - jint16 t; // Current triangle - - for (t=0; ttriangleCount; t++) { - _j3DrawWireframePair(o, o->triangles[t].index[0], o->triangles[t].index[1]); - _j3DrawWireframePair(o, o->triangles[t].index[1], o->triangles[t].index[2]); - _j3DrawWireframePair(o, o->triangles[t].index[2], o->triangles[t].index[0]); - } -} - - void j3DrawWorld(j3WorldT *w) { jint16 i; juint16 vertex1; @@ -432,21 +365,26 @@ void j3DrawWorld(j3WorldT *w) { j3ObjectT *o; j3PolyListT *p; - //***TODO*** Fix - (void)w; + w->polygonCount = 0; - for (i=0; i<_j3PolygonCount; i++) { + // Update all our math + for (i=0; iobjectCount; i++) { + _j3ObjectUpdate(w, i); + } + + // Render it + for (i=0; ipolygonCount; i++) { // Dereference - p = &_j3Polygons[i]; + p = &w->polygons[i]; o = p->object; vertex1 = o->triangles[p->triangleNumber].index[0]; vertex2 = o->triangles[p->triangleNumber].index[1]; vertex3 = o->triangles[p->triangleNumber].index[2]; - z1 = o->verticies[vertex1].camera.z; - z2 = o->verticies[vertex2].camera.z; - z3 = o->verticies[vertex3].camera.z; + z1 = o->vertices[vertex1].camera.z; + z2 = o->vertices[vertex2].camera.z; + z3 = o->vertices[vertex3].camera.z; // Perform z clipping if ((z1 < _j3VarClipMinZ && z2 < _j3VarClipMinZ && z3 < _j3VarClipMinZ) || (z1 > _j3VarClipMaxZ && z2 > _j3VarClipMaxZ && z3 > _j3VarClipMaxZ)) { @@ -454,12 +392,12 @@ void j3DrawWorld(j3WorldT *w) { } // Extract points of triangle - x1 = o->verticies[vertex1].camera.x; - y1 = o->verticies[vertex1].camera.y; - x2 = o->verticies[vertex2].camera.x; - y2 = o->verticies[vertex2].camera.y; - x3 = o->verticies[vertex3].camera.x; - y3 = o->verticies[vertex3].camera.y; + x1 = o->vertices[vertex1].camera.x; + y1 = o->vertices[vertex1].camera.y; + x2 = o->vertices[vertex2].camera.x; + y2 = o->vertices[vertex2].camera.y; + x3 = o->vertices[vertex3].camera.x; + y3 = o->vertices[vertex3].camera.y; // Screen position of points x1 = HALF_SCREEN_WIDTH + x1 * _j3VarViewDistance / z1; @@ -533,6 +471,22 @@ float j3MathVectorMagnatude3D(j3Vector3DT *v) { } +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; +} + + +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; +} + + void _j3ObjectReset(j3ObjectT *o) { o->position.x = 0; o->position.y = 0; @@ -552,29 +506,67 @@ void _j3ObjectReset(j3ObjectT *o) { } -void _j3ObjectUpdate(j3ObjectT *o) { - jint16 x; - jint16 y; - jint16 z; - jint16 i; - juint16 vertex0; - juint16 vertex1; - juint16 vertex2; - float dot; - float intensity; - j3Vector3DT u; - j3Vector3DT v; - j3Vector3DT normal; - j3Vector3DT sight; - byte axis = 0; - j3Matrix4x4T rotateX; - j3Matrix4x4T rotateY; - j3Matrix4x4T rotateZ; - j3Matrix4x4T final; - j3Matrix4x4T temp; - j3Matrix4x4T result1; - j3Matrix4x4T result2; - j3Matrix4x4T translate; +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; +} + + +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; +} + + +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; +} + + +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; +} + + +void _j3ObjectUpdate(j3WorldT *w, jint16 index) { + jint16 x; + jint16 y; + jint16 z; + jint16 i; + juint16 vertex0; + juint16 vertex1; + juint16 vertex2; + float dot; + float intensity; + j3Vector3DT u; + j3Vector3DT v; + j3Vector3DT normal; + j3Vector3DT sight; + byte axis = 0; + j3Matrix4x4T rotateX; + j3Matrix4x4T rotateY; + j3Matrix4x4T rotateZ; + j3Matrix4x4T final; + j3Matrix4x4T temp; + j3Matrix4x4T result1; + j3Matrix4x4T result2; + 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 === @@ -591,124 +583,124 @@ void _j3ObjectUpdate(j3ObjectT *o) { switch (axis) { case 1: // Final matrix = z - final[0][0] = cos_table[z]; - final[0][1] = sin_table[z]; - final[1][0] = -sin_table[z]; - final[1][1] = cos_table[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->verticies[i].world.x = o->verticies[i].local.x * final[0][0] + o->verticies[i].local.y * final[1][0]; - o->verticies[i].world.y = o->verticies[i].local.x * final[0][1] + o->verticies[i].local.y * final[1][1]; - o->verticies[i].world.z = o->verticies[i].local.z; + 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] = cos_table[y]; - final[0][2] = -sin_table[y]; - final[2][0] = sin_table[y]; - final[2][2] = cos_table[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->verticies[i].world.x = o->verticies[i].local.x * final[0][0] + o->verticies[i].local.z * final[2][0]; - o->verticies[i].world.y = o->verticies[i].local.y; - o->verticies[i].world.z = o->verticies[i].local.x * final[0][2] + o->verticies[i].local.z * final[2][2]; + 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] = cos_table[y] * cos_table[z]; - final[0][1] = cos_table[y] * sin_table[z]; - final[0][2] = -sin_table[y]; + final[0][0] = cosTable[y] * cosTable[z]; + final[0][1] = cosTable[y] * sinTable[z]; + final[0][2] = -sinTable[y]; - final[1][0] = -sin_table[z]; - final[1][1] = cos_table[z]; + final[1][0] = -sinTable[z]; + final[1][1] = cosTable[z]; - final[2][0] = sin_table[y] * cos_table[z]; - final[2][1] = sin_table[y] * sin_table[z]; - final[2][2] = cos_table[y]; + 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->verticies[i].world.x = o->verticies[i].local.x * final[0][0] + o->verticies[i].local.y * final[1][0] + o->verticies[i].local.z * final[2][0]; - o->verticies[i].world.y = o->verticies[i].local.x * final[0][1] + o->verticies[i].local.y * final[1][1] + o->verticies[i].local.z * final[2][1]; - o->verticies[i].world.z = o->verticies[i].local.x * final[0][2] + o->verticies[i].local.z * final[2][2]; + 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] = cos_table[x]; - final[1][2] = sin_table[x]; - final[2][1] = -sin_table[x]; - final[2][2] = cos_table[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->verticies[i].world.x = o->verticies[i].local.x; - o->verticies[i].world.y = o->verticies[i].local.y * final[1][1] + o->verticies[i].local.z * final[2][1]; - o->verticies[i].world.z = o->verticies[i].local.y * final[1][2] + o->verticies[i].local.z * final[2][2]; + 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] = cos_table[z]; - final[0][1] = sin_table[z]; + final[0][0] = cosTable[z]; + final[0][1] = sinTable[z]; - final[1][0] = -cos_table[x] * sin_table[z]; - final[1][1] = cos_table[x] * cos_table[z]; - final[1][2] = sin_table[x]; + final[1][0] = -cosTable[x] * sinTable[z]; + final[1][1] = cosTable[x] * cosTable[z]; + final[1][2] = sinTable[x]; - final[2][0] = sin_table[x] * sin_table[z]; - final[2][1] = -sin_table[x] * cos_table[z]; - final[2][2] = cos_table[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->verticies[i].world.x = o->verticies[i].local.x * final[0][0] + o->verticies[i].local.y * final[1][0] + o->verticies[i].local.z * final[2][0]; - o->verticies[i].world.y = o->verticies[i].local.x * final[0][1] + o->verticies[i].local.y * final[1][1] + o->verticies[i].local.z * final[2][1]; - o->verticies[i].world.z = o->verticies[i].local.y * final[1][2] + o->verticies[i].local.z * final[2][2]; + 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] = cos_table[y]; - final[0][2] = -sin_table[y]; + final[0][0] = cosTable[y]; + final[0][2] = -sinTable[y]; - final[1][0] = sin_table[x] * sin_table[y]; - final[1][1] = cos_table[x]; - final[1][2] = sin_table[x] * cos_table[y]; + final[1][0] = sinTable[x] * sinTable[y]; + final[1][1] = cosTable[x]; + final[1][2] = sinTable[x] * cosTable[y]; - final[2][0] = cos_table[x] * sin_table[y]; - final[2][1] = -sin_table[x]; - final[2][2] = cos_table[x] * cos_table[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->verticies[i].world.x = o->verticies[i].local.x * final[0][0] + o->verticies[i].local.y * final[1][0] + o->verticies[i].local.z * final[2][0]; - o->verticies[i].world.y = o->verticies[i].local.y * final[1][1] + o->verticies[i].local.z * final[2][1]; - o->verticies[i].world.z = o->verticies[i].local.x * final[0][2] + o->verticies[i].local.y * final[1][2] + o->verticies[i].local.z * final[2][2]; + 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] = cos_table[x]; - rotateX[1][2] = sin_table[x]; - rotateX[2][1] = -sin_table[x]; - rotateX[2][2] = cos_table[x]; + 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] = cos_table[y]; - rotateY[0][2] = -sin_table[y]; - rotateY[2][0] = sin_table[y]; - rotateY[2][2] = cos_table[y]; + 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] = cos_table[z]; - rotateZ[0][1] = sin_table[z]; - rotateZ[1][0] = -sin_table[z]; - rotateZ[1][1] = cos_table[z]; + 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->verticies[i].world.x = o->verticies[i].local.x * final[0][0] + o->verticies[i].local.y * final[1][0] + o->verticies[i].local.z * final[2][0]; - o->verticies[i].world.y = o->verticies[i].local.x * final[0][1] + o->verticies[i].local.y * final[1][1] + o->verticies[i].local.z * final[2][1]; - o->verticies[i].world.z = o->verticies[i].local.x * final[0][2] + o->verticies[i].local.y * final[1][2] + o->verticies[i].local.z * final[2][2]; + 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; @@ -719,9 +711,9 @@ void _j3ObjectUpdate(j3ObjectT *o) { // === SCALE & TRANSLATION === for (i=0; ivertexCount; i++) { - o->verticies[i].world.x = o->verticies[i].world.x * o->scale.x + o->position.x; - o->verticies[i].world.y = o->verticies[i].world.y * o->scale.y + o->position.y; - o->verticies[i].world.z = o->verticies[i].world.z * o->scale.z + o->position.z; + 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; } // === CAMERA SPACE === @@ -738,22 +730,22 @@ void _j3ObjectUpdate(j3ObjectT *o) { translate[3][2] = -_j3VarCameraLocation.z; // X matrix - rotateX[1][1] = ( cos_table[_j3VarCameraAngle.x]); - rotateX[1][2] = -( sin_table[_j3VarCameraAngle.x]); - rotateX[2][1] = -(-sin_table[_j3VarCameraAngle.x]); - rotateX[2][2] = ( cos_table[_j3VarCameraAngle.x]); + 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] = ( cos_table[_j3VarCameraAngle.y]); - rotateY[0][2] = -(-sin_table[_j3VarCameraAngle.y]); - rotateY[2][0] = -( sin_table[_j3VarCameraAngle.y]); - rotateY[2][2] = ( cos_table[_j3VarCameraAngle.y]); + 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] = ( cos_table[_j3VarCameraAngle.z]); - rotateZ[0][1] = -( sin_table[_j3VarCameraAngle.z]); - rotateZ[1][0] = -(-sin_table[_j3VarCameraAngle.z]); - rotateZ[1][1] = ( cos_table[_j3VarCameraAngle.z]); + 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); @@ -763,20 +755,20 @@ void _j3ObjectUpdate(j3ObjectT *o) { _j3VarCameraAngleDirty = false; for (i=0; ivertexCount; i++) { - o->verticies[i].camera.x = - o->verticies[i].world.x * _j3VarCameraMatrix[0][0] + - o->verticies[i].world.y * _j3VarCameraMatrix[1][0] + - o->verticies[i].world.z * _j3VarCameraMatrix[2][0] + + 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] + _j3VarCameraMatrix[3][0]; - o->verticies[i].camera.y = - o->verticies[i].world.x * _j3VarCameraMatrix[0][1] + - o->verticies[i].world.y * _j3VarCameraMatrix[1][1] + - o->verticies[i].world.z * _j3VarCameraMatrix[2][1] + + 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] + _j3VarCameraMatrix[3][1]; - o->verticies[i].camera.z = - o->verticies[i].world.x * _j3VarCameraMatrix[0][2] + - o->verticies[i].world.y * _j3VarCameraMatrix[1][2] + - o->verticies[i].world.z * _j3VarCameraMatrix[2][2] + + 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] + _j3VarCameraMatrix[3][2]; } @@ -795,16 +787,16 @@ void _j3ObjectUpdate(j3ObjectT *o) { vertex1 = o->triangles[i].index[1]; vertex2 = o->triangles[i].index[2]; // Vector u = v0->v1 - j3MathMakeVector3D((j3VertexT *)&o->verticies[vertex0].world, (j3VertexT *)&o->verticies[vertex1].world, (j3Vector3DT *)&u); + j3MathMakeVector3D((j3VertexT *)&o->vertices[vertex0].world, (j3VertexT *)&o->vertices[vertex1].world, (j3Vector3DT *)&u); // Vector v = v0->v2 - j3MathMakeVector3D((j3VertexT *)&o->verticies[vertex0].world, (j3VertexT *)&o->verticies[vertex2].world, (j3Vector3DT *)&v); + j3MathMakeVector3D((j3VertexT *)&o->vertices[vertex0].world, (j3VertexT *)&o->vertices[vertex2].world, (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->verticies[vertex0].world.x; - sight.y = _j3VarCameraLocation.y - o->verticies[vertex0].world.y; - sight.z = _j3VarCameraLocation.z - o->verticies[vertex0].world.z; + 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; // Compute the dot product between line of sight vector and normal to surface dot = j3MathDotProduct3D((j3Vector3DT *)&normal, (j3Vector3DT *)&sight); @@ -851,9 +843,9 @@ void _j3ObjectUpdate(j3ObjectT *o) { vertex1 = o->triangles[i].index[1]; vertex2 = o->triangles[i].index[2]; // Vector u = v0->v1 - j3MathMakeVector3D((j3VertexT *)&o->verticies[vertex0].world, (j3VertexT *)&o->verticies[vertex1].world, (j3Vector3DT *)&u); + j3MathMakeVector3D((j3VertexT *)&o->vertices[vertex0].world, (j3VertexT *)&o->vertices[vertex1].world, (j3Vector3DT *)&u); // Vector v = v0->v2 - j3MathMakeVector3D((j3VertexT *)&o->verticies[vertex0].world, (j3VertexT *)&o->verticies[vertex2].world, (j3Vector3DT *)&v); + j3MathMakeVector3D((j3VertexT *)&o->vertices[vertex0].world, (j3VertexT *)&o->vertices[vertex2].world, (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 @@ -880,23 +872,23 @@ void _j3ObjectUpdate(j3ObjectT *o) { } // Did this triangle survive culling? - //***TODO*** Our visible flag is backwards for some reason. Not sure why yet. + //***TODO*** Our visible flag is backwards for some reason. Winding direction wrong? if (!o->triangles[i].visible) { // Find average z depth in camera space vertex0 = o->triangles[i].index[0]; vertex1 = o->triangles[i].index[1]; vertex2 = o->triangles[i].index[2]; - o->triangles[i].averageDepth = (float)0.3333333 * (o->verticies[vertex0].camera.z + o->verticies[vertex1].camera.z + o->verticies[vertex2].camera.z); + o->triangles[i].averageDepth = (float)0.3333333 * (o->vertices[vertex0].camera.z + o->vertices[vertex1].camera.z + o->vertices[vertex2].camera.z); // Add to visible polygon list - _j3Polygons[_j3PolygonCount].object = o; - _j3Polygons[_j3PolygonCount].triangleNumber = (juint16)i; - _j3PolygonCount++; + w->polygons[w->polygonCount].object = o; + w->polygons[w->polygonCount].triangleNumber = (juint16)i; + w->polygonCount++; } } // for i // Z Sort the visible polygon list - qsort((void *)_j3Polygons, _j3PolygonCount, sizeof(j3PolyListT), (j3qsortCastT)_j3PolyCompare); + qsort((void *)w->polygons, w->polygonCount, sizeof(j3PolyListT), (j3qsortCastT)_j3PolyCompare); o->positionDirty = false; o->rotationDirty = false; @@ -917,8 +909,8 @@ void _j3ObjectUpdateNormalLength(j3ObjectT *object, juint16 triangle) { vertex1 = object->triangles[triangle].index[1]; vertex2 = object->triangles[triangle].index[2]; - j3MathMakeVector3D((j3VertexT *)&object->verticies[vertex0].local, (j3VertexT *)&object->verticies[vertex1].local, (j3Vector3DT *)&u); - j3MathMakeVector3D((j3VertexT *)&object->verticies[vertex0].local, (j3VertexT *)&object->verticies[vertex2].local, (j3Vector3DT *)&v); + 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); j3MathCrossProduct3D((j3Vector3DT *)&v, (j3Vector3DT *)&u, (j3Vector3DT *)&normal); // Compute magnitude of normal, take its inverse and multiply it by @@ -1135,10 +1127,7 @@ bool _j3UtilClipLine(jint16 *x1, jint16 *y1, jint16 *x2, jint16 *y2) { void j3UtilShutdown(void) { - // Free visible polygon list - if (_j3Polygons != NULL) { - jlFree(_j3Polygons); - } + // Nothing } @@ -1157,27 +1146,27 @@ void j3UtilStartup(void) { } -void _j3WorldFree(j3WorldT **world) { +void _j3PropFree(j3PropT **prop) { int x; - if ((*world)) { - for (x=0; x<(*world)->objectCount; x++) { - if ((*world)->objects[x].triangles) { - jlFree((*world)->objects[x].triangles); + if ((*prop)) { + for (x=0; x<(*prop)->pieceCount; x++) { + if ((*prop)->pieces[x].triangles) { + jlFree((*prop)->pieces[x].triangles); } - if ((*world)->objects[x].verticies) { - jlFree((*world)->objects[x].verticies); + if ((*prop)->pieces[x].vertices) { + jlFree((*prop)->pieces[x].vertices); } } - if ((*world)->objects) { - jlFree((*world)->objects); + if ((*prop)->pieces) { + jlFree((*prop)->pieces); } - jlFree(*world); + jlFree(*prop); } } -bool _j3WorldLoad(j3WorldT **world, char *file) { +jint16 _j3PropLoad(j3PropT **prop, char *file) { juint16 x; juint16 y; juint16 z; @@ -1193,52 +1182,52 @@ bool _j3WorldLoad(j3WorldT **world, char *file) { return false; } - // Do we have a world? - if (*world != NULL) { + // Do we have this prop? + if (*prop != NULL) { // Free this one - j3WorldFree(world); + j3PropFree(prop); } - // Allocate world object - *world = (j3WorldT *)jlMalloc(sizeof(j3WorldT)); - if (*world) { - // Initialize world object & create an initial object to read data into - (*world)->objectCount = 0;; - (*world)->objects = NULL; + // Allocate prop object + *prop = (j3PropT *)jlMalloc(sizeof(j3PropT)); + if (*prop) { + // Initialize prop object & create an initial piece to read data into + (*prop)->pieceCount = 0;; + (*prop)->pieces = NULL; - // Is this a valid world file? + // Is this a valid prop file? if (fread(buffer, sizeof(byte), 4, in) == 4) { if ((buffer[0] == 'J') && (buffer[1] == '3') && (buffer[2] == 'D') && (buffer[3] <= 0)) { - // Get object count - if (fread(&(*world)->objectCount, sizeof(juint16), 1, in) == 1) { + // Get piece count + if (fread(&(*prop)->pieceCount, sizeof(juint16), 1, in) == 1) { - // Allocate memory for objects - (*world)->objects = (j3ObjectT *)jlMalloc(sizeof(j3ObjectT) * (*world)->objectCount); - if ((*world)->objects) { + // Allocate memory for pieces + (*prop)->pieces = (j3PieceT *)jlMalloc(sizeof(j3PieceT) * (*prop)->pieceCount); + if ((*prop)->pieces) { - // Iterate across objects in file - for (x=0; x<(*world)->objectCount; x++) { + // Iterate across pieces in file + for (x=0; x<(*prop)->pieceCount; x++) { // Get vertex count - if (fread(&(*world)->objects[x].vertexCount, sizeof(juint16), 1, in) == 1) { + if (fread(&(*prop)->pieces[x].vertexCount, sizeof(juint16), 1, in) == 1) { // Allocate memory for vertex data - (*world)->objects->verticies = (j3CoordinatesT *)jlMalloc(sizeof(j3CoordinatesT) * (*world)->objects[x].vertexCount); - if ((*world)->objects->verticies) { + (*prop)->pieces[x].vertices = (j3VertexT *)jlMalloc(sizeof(j3VertexT) * (*prop)->pieces[x].vertexCount); + if ((*prop)->pieces[x].vertices) { - // Iterate and read verticies - for (y=0; y<(*world)->objects[x].vertexCount; y++) { + // Iterate and read vertices + for (y=0; y<(*prop)->pieces[x].vertexCount; y++) { // Read one at a time in case the struct gets padded - if (fread(&(*world)->objects[x].verticies[y].local.x, sizeof(float), 1, in) != 1) { + if (fread(&(*prop)->pieces[x].vertices[y].x, sizeof(float), 1, in) != 1) { failed = true; break; } - if (fread(&(*world)->objects[x].verticies[y].local.y, sizeof(float), 1, in) != 1) { + if (fread(&(*prop)->pieces[x].vertices[y].y, sizeof(float), 1, in) != 1) { failed = true; break; } - if (fread(&(*world)->objects[x].verticies[y].local.z, sizeof(float), 1, in) != 1) { + if (fread(&(*prop)->pieces[x].vertices[y].z, sizeof(float), 1, in) != 1) { failed = true; break; } @@ -1252,38 +1241,31 @@ bool _j3WorldLoad(j3WorldT **world, char *file) { if (!failed) { // Get triangle count - if (fread(&(*world)->objects[x].triangleCount, sizeof(juint16), 1, in) == 1) { + if (fread(&(*prop)->pieces[x].triangleCount, sizeof(juint16), 1, in) == 1) { // Allocate memory for triangle data - (*world)->objects->triangles = (j3TriangleT *)jlMalloc(sizeof(j3TriangleT) * (*world)->objects[x].triangleCount); - if ((*world)->objects->triangles) { - - //***TODO*** This will have to be moved/improved - // Add to world count & increase potential polygon list - _j3TriangleCount += (*world)->objects[x].triangleCount; - _j3Polygons = (j3PolyListT *)jlRealloc(_j3Polygons, sizeof(j3PolyListT) * _j3TriangleCount); + (*prop)->pieces[x].triangles = (j3TriangleThinT *)jlMalloc(sizeof(j3TriangleThinT) * (*prop)->pieces[x].triangleCount); + if ((*prop)->pieces[x].triangles) { // Iterate and read triangles - for (y=0; y<(*world)->objects[x].triangleCount; y++) { + for (y=0; y<(*prop)->pieces[x].triangleCount; y++) { // Read one at a time in case the struct gets padded for (z=0; z<3; z++) { - if (fread(&(*world)->objects[x].triangles[y].index[z], sizeof(juint16), 1, in) != 1) { + if (fread(&(*prop)->pieces[x].triangles[y].index[z], sizeof(juint16), 1, in) != 1) { failed = true; break; } } if (failed) break; - _j3ObjectUpdateNormalLength(&(*world)->objects[x], y); - - // Triangles begin life un-lit - (*world)->objects[x].triangles[y].lit = false; + //***TODO*** Triangles begin life un-lit + (*prop)->pieces[x].triangles[y].lit = false; //***TODO*** All triangles are one-sided for now - (*world)->objects[x].triangles[y].twoSided = false; + (*prop)->pieces[x].triangles[y].twoSided = false; //***TODO*** All triangles are white for now - (*world)->objects[x].triangles[y].color = 15; + (*prop)->pieces[x].triangles[y].color = 15; } } else { @@ -1294,25 +1276,149 @@ bool _j3WorldLoad(j3WorldT **world, char *file) { } } - if (!failed) { - _j3ObjectReset(&(*world)->objects[x]); - } else { + if (failed) { break; // Stop iterating } - } // object iterator - } // objects alloc - } // Object count + } // piece iterator + } // pieces alloc + } // pieces count } // Valid file } // Read header - } // world alloc + } // prop alloc // Finished! Clean up. fclose(in); - return !failed; + if (failed) { + return -1; + } + + return (jint16)(*prop)->pieceCount; } + +jint16 _j3WorldAddProp(j3WorldT **world, j3PropT *prop) { + + juint16 x; + juint16 y; + juint16 z; + juint16 oldObjectCount = 0; + bool result = true; + + // Is this world valid yet? + if (*world == NULL) { + *world = (j3WorldT *)jlMalloc(sizeof(j3WorldT)); + (*world)->objectCount = 0; + (*world)->polygonCount = 0; + (*world)->triangleCount = 0; + (*world)->objects = NULL; + (*world)->polygons = NULL; + } + + // Add new prop pieces to world as objects + oldObjectCount = (*world)->objectCount; + (*world)->objectCount += prop->pieceCount; + + // Allocate memory for objects + (*world)->objects = (j3ObjectT *)jlRealloc((*world)->objects, sizeof(j3ObjectT) * (*world)->objectCount); + if (!(*world)->objects) { + return -1; + } + + // Copy pieces into objects + y = 0; + for (x=oldObjectCount; x<(*world)->objectCount; x++) { + + // Vertices + (*world)->objects[x].vertexCount = prop->pieces[y].vertexCount; + + // Allocate memory for vertex data + (*world)->objects[x].vertices = (j3CoordinatesT *)jlMalloc(sizeof(j3CoordinatesT) * (*world)->objects[x].vertexCount); + if (!(*world)->objects[x].vertices) { + result = false; + break; + } + + // 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; + } + + // Triangles + (*world)->objects[x].triangleCount = prop->pieces[y].triangleCount; + + // Allocate memory for triangle data + (*world)->objects[x].triangles = (j3TriangleT *)jlMalloc(sizeof(j3TriangleT) * (*world)->objects[x].triangleCount); + if (!(*world)->objects[x].triangles) { + result = false; + break; + } + + // Copy triangle data + for (z=0; zpieces[y].triangleCount; z++) { + (*world)->objects[x].triangles[z].index[0] = prop->pieces[y].triangles[z].index[0]; + (*world)->objects[x].triangles[z].index[1] = prop->pieces[y].triangles[z].index[1]; + (*world)->objects[x].triangles[z].index[2] = prop->pieces[y].triangles[z].index[2]; + (*world)->objects[x].triangles[z].lit = prop->pieces[y].triangles[z].lit; + (*world)->objects[x].triangles[z].color = prop->pieces[y].triangles[z].color; + (*world)->objects[x].triangles[z].twoSided = prop->pieces[y].triangles[z].twoSided; + (*world)->objects[x].triangles[z].normalLength = prop->pieces[y].triangles[z].normalLength; + + _j3ObjectUpdateNormalLength(&(*world)->objects[x], z); + + // Triangles begin life visible + (*world)->objects[x].triangles[z].visible = true; + } + + // Add to world count & increase potential polygon list + (*world)->triangleCount += (*world)->objects[x].triangleCount; + (*world)->polygons = (j3PolyListT *)jlRealloc((*world)->polygons, sizeof(j3PolyListT) * (*world)->triangleCount); + if (!(*world)->polygons) { + result = false; + break; + } + + _j3ObjectReset(&(*world)->objects[x]); + + // Next piece + y++; + + } // Pieces + + if (!result) { + return -1; + } + + return (jint16)oldObjectCount; +} + + +void _j3WorldFree(j3WorldT **world) { + int x; + + if ((*world)) { + for (x=0; x<(*world)->objectCount; x++) { + if ((*world)->objects[x].triangles) { + jlFree((*world)->objects[x].triangles); + } + if ((*world)->objects[x].vertices) { + jlFree((*world)->objects[x].vertices); + } + } + if ((*world)->objects) { + jlFree((*world)->objects); + } + if ((*world)->polygons != NULL) { + jlFree((*world)->polygons); + } + jlFree(*world); + } +} + + #ifndef JOEY_IIGS #pragma GCC diagnostic pop #endif diff --git a/j3d/j3d.h b/j3d/j3d.h index 4646d9f..cb74799 100644 --- a/j3d/j3d.h +++ b/j3d/j3d.h @@ -58,10 +58,18 @@ typedef struct { juint16 index[3]; // We do this instead of just a typedef so it works with stretch_buffer } j3TriangleT; +typedef struct { + jint16 color; // Assigned color of this face + bool lit; // Do we care about lighting? + bool twoSided; // Are both sides visible? + float normalLength; // Magnatude of surface normal + juint16 index[3]; // We do this instead of just a typedef so it works with stretch_buffer +} j3TriangleThinT; + typedef struct { juint16 vertexCount; // How many verticies are in the list juint16 triangleCount; // How many triangles are in the list - j3CoordinatesT *verticies; // List of verticies as loaded from disk (more v1, v2, v3 than x, y, z) + j3CoordinatesT *vertices; // List of vertices as loaded from disk (more v1, v2, v3 than x, y, z) j3TriangleT *triangles; // Triangles built from vertex list j3VertexT position; // Position of object in world j3VertexT rotation; // Rotation of object in world @@ -77,60 +85,26 @@ typedef struct { } j3PolyListT; typedef struct { - juint16 objectCount; - j3ObjectT *objects; + juint16 objectCount; // Number of objects in world + j3ObjectT *objects; // Objects data + j3PolyListT *polygons; // Polygons to render + juint16 polygonCount; // Current visible polygons + juint16 triangleCount; // Current triangles in world } j3WorldT; +typedef struct { + juint16 vertexCount; // How many verticies are in the list + juint16 triangleCount; // How many triangles are in the list + j3VertexT *vertices; // List of vertices as loaded from disk (more v1, v2, v3 than x, y, z) + j3TriangleThinT *triangles; // Triangles built from vertex list +} j3PieceT; -extern jint16 _j3VarClipMinX; -extern jint16 _j3VarClipMinY; -extern jint16 _j3VarClipMinZ; -extern jint16 _j3VarClipMaxX; -extern jint16 _j3VarClipMaxY; -extern jint16 _j3VarClipMaxZ; -extern jint16 _j3VarViewDistance; -extern float _j3VarAmbientLight; -extern j3Matrix4x4T _j3VarCameraMatrix; -extern j3VertexT _j3VarCameraLocation; -extern j3FacingT _j3VarCameraAngle; -extern bool _j3VarCameraLocationDirty; -extern bool _j3VarCameraAngleDirty; -extern j3VertexT _j3VarSunLocation; -extern j3PolyListT *_j3Polygons; -extern juint16 _j3PolygonCount; -extern juint16 _j3TriangleCount; - - -#define j3CameraMove(ob, px, py, pz) \ - _j3VarCameraLocation.x += (px); \ - _j3VarCameraLocation.y += (py); \ - _j3VarCameraLocation.z += (pz); \ - _j3VarCameraLocationDirty = true - -#define j3CameraMoveTo(ob, px, py, pz) \ - _j3VarCameraLocation.x = (px); \ - _j3VarCameraLocation.y = (py); \ - _j3VarCameraLocation.z = (pz); \ - _j3VarCameraLocationDirty = true - -#define j3CameraRotate(ob, px, py, pz) \ - _j3VarCameraAngle.x += (px); j3MathWrapBounds(_j3VarCameraAngle.x, 0, 360); \ - _j3VarCameraAngle.y += (py); j3MathWrapBounds(_j3VarCameraAngle.y, 0, 360); \ - _j3VarCameraAngle.z += (pz); j3MathWrapBounds(_j3VarCameraAngle.z, 0, 360); \ - _j3VarCameraAngleDirty = true - -#define j3CameraRotateTo(ob, px, py, pz) \ - _j3VarCameraAngle.x = (px); j3MathWrapBounds(_j3VarCameraAngle.x, 0, 360); \ - _j3VarCameraAngle.y = (py); j3MathWrapBounds(_j3VarCameraAngle.y, 0, 360); \ - _j3VarCameraAngle.z = (pz); j3MathWrapBounds(_j3VarCameraAngle.z, 0, 360); \ - _j3VarCameraAngleDirty = true - -#define j3CameraSetClippingBounds(x1, y1, x2, y2) \ - _j3VarClipMinX = (x1); j3MathCheckBounds(_j3VarClipMinX, 0, 319); \ - _j3VarClipMinY = (y1); j3MathCheckBounds(_j3VarClipMiny, 0, 199); \ - _j3VarClipMaxX = (x2); j3MathCheckBounds(_j3VarClipMaxX, 0, 319); \ - _j3VarClipMaxY = (y2); j3MathCheckBounds(_j3VarClipMaxy, 0, 199) +typedef struct { + juint16 pieceCount; // Number of pieces in the prop + j3PieceT *pieces; // Piece data +} j3PropT; +// Couple inline routines #define j3MathCheckBounds(value, min, max) \ if (value < (min)) value = (min); \ if (value > (max)) value = (max) @@ -139,54 +113,28 @@ extern juint16 _j3TriangleCount; if (value < (min)) value += (max); \ if (value > (max)) value -= (max) -#define j3ObjectMove(ob, px, py, pz) \ - ob.position.x += (px); \ - ob.position.y += (py); \ - ob.position.z += (pz); \ - ob.positionDirty = true - -#define j3ObjectMoveTo(ob, px, py, pz) \ - ob.position.x = (px); \ - ob.position.y = (py); \ - ob.position.z = (pz); \ - ob.positionDirty = true - -#define j3ObjectRotate(ob, px, py, pz) \ - ob.rotation.x += (px); j3MathWrapBounds(ob.rotation.x, 0, 360); \ - ob.rotation.y += (py); j3MathWrapBounds(ob.rotation.y, 0, 360); \ - ob.rotation.z += (pz); j3MathWrapBounds(ob.rotation.z, 0, 360); \ - ob.rotationDirty = true - -#define j3ObjectRotateTo(ob, px, py, pz) \ - ob.rotation.x = (px); j3MathWrapBounds(ob.rotation.x, 0, 360); \ - ob.rotation.y = (py); j3MathWrapBounds(ob.rotation.y, 0, 360); \ - ob.rotation.z = (pz); j3MathWrapBounds(ob.rotation.z, 0, 360); \ - ob.rotationDirty = true - -#define j3ObjectScale(ob, px, py, pz) \ - ob.scale.x += (px); \ - ob.scale.y += (py); \ - ob.scale.z += (pz); \ - ob.scaleDirty = true - -#define j3ObjectScaleTo(ob, px, py, pz) \ - ob.scale.x = (px); \ - ob.scale.y = (py); \ - ob.scale.z = (pz); \ - ob.scaleDirty = true - // Syntatic sugar -#define j3DrawSolid(o) _j3DrawSolid(&(o)) -#define j3DrawWireframe(o) _j3DrawWireframe(&(o)) -#define j3ObjectReset(o) _j3ObjectReset(&(o)) -#define j3ObjectUpdate(o) _j3ObjectUpdate(&(o)) -#define j3WorldFree(w) _j3WorldFree((j3WorldT **)&(w)) -#define j3WorldLoad(w, f) _j3WorldLoad((j3WorldT **)&(w), (f)) +#define j3ObjectMove(o, px, py, pz) _j3ObjectMove(&(o), (px), (py), (pz)) +#define j3ObjectMoveTo(o, px, py, pz) _j3ObjectMoveTo(&(o), (px), (py), (pz)) +#define j3ObjectReset(o) _j3ObjectReset(&(o)) +#define j3ObjectRotate(o, px, py, pz) _j3ObjectRotate(&(o), (px), (py), (pz)) +#define j3ObjectRotateTo(o, px, py, pz) _j3ObjectRotateTo(&(o), (px), (py), (pz)) +#define j3ObjectScale(o, px, py, pz) _j3ObjectScale(&(o), (px), (py), (pz)) +#define j3ObjectScaleTo(o, px, py, pz) _j3ObjectScaleTo(&(o), (px), (py), (pz)) +#define j3PropFree(p) _j3PropFree((j3PropT **)&(p)) +#define j3PropLoad(p, f) _j3PropLoad((j3PropT **)&(p), (f)) +#define j3WorldAddProp(w, p) _j3WorldAddProp((j3WorldT **)&(w), (p)) +#define j3WorldFree(w) _j3WorldFree((j3WorldT **)&(w)) // Prototypes -void j3DrawTriangle2D(jint16 x1, jint16 y1, jint16 x2,jint16 y2, jint16 x3, jint16 y3, jint16 color); +void j3CameraMove(float x, float y, float z); +void j3CameraMoveTo(float x, float y, float z); +void j3CameraRotate(float x, float y, float z); +void j3CameraRotateTo(float x, float y, float z); +void j3CameraSetClippingBounds(jint16 x1, jint16 y1, jint16 x2, jint16 y2); +void j3DrawTriangle2D(jint16 x1, jint16 y1, jint16 x2, jint16 y2, jint16 x3, jint16 y3, jint16 color); void j3DrawWorld(j3WorldT *w); void j3MathCrossProduct3D(j3Vector3DT *u, j3Vector3DT *v, j3Vector3DT *normal); float j3MathDotProduct3D(j3Vector3DT *u, j3Vector3DT *v); @@ -199,17 +147,17 @@ void j3UtilStartup(void); // Private Prototypes -void _j3DrawSolid(j3ObjectT *o); -void _j3DrawTriangleBottom(jint16 x1, jint16 y1, jint16 x2,jint16 y2, jint16 x3, jint16 y3); -void _j3DrawTriangleTop(jint16 x1, jint16 y1, jint16 x2,jint16 y2, jint16 x3, jint16 y3); -void _j3DrawWireframePair(j3ObjectT *o, juint16 v1, juint16 v2); -void _j3DrawWireframe(j3ObjectT *o); -void _j3ObjectReset(j3ObjectT *o); -void _j3ObjectUpdateNormalLength(j3ObjectT *object, juint16 triangle); -void _j3ObjectUpdate(j3ObjectT *o); -bool _j3UtilClipLine(jint16 *x1, jint16 *y1, jint16 *x2, jint16 *y2); -void _j3WorldFree(j3WorldT **world); -bool _j3WorldLoad(j3WorldT **world, char *file); +void _j3ObjectMove(j3ObjectT *o, float x, float y, float z); +void _j3ObjectMoveTo(j3ObjectT *o, float x, float y, float z); +void _j3ObjectReset(j3ObjectT *o); +void _j3ObjectRotate(j3ObjectT *o, float x, float y, float z); +void _j3ObjectRotateTo(j3ObjectT *o, float x, float y, float z); +void _j3ObjectScale(j3ObjectT *o, float x, float y, float z); +void _j3ObjectScaleTo(j3ObjectT *o, float x, float y, float z); +void _j3PropFree(j3PropT **prop); +jint16 _j3PropLoad(j3PropT **prop, char *file); +jint16 _j3WorldAddProp(j3WorldT **world, j3PropT *prop); +void _j3WorldFree(j3WorldT **world); #endif // H_J3D_ diff --git a/j3d/j3dtbls.h b/j3d/j3dtbls.h index 1efd044..db2a260 100644 --- a/j3d/j3dtbls.h +++ b/j3d/j3dtbls.h @@ -24,7 +24,7 @@ #define H_J3DTBLS_ -static float sin_table[] = { +static float sinTable[] = { 0.0000000, 0.0174524, 0.0348995, 0.0523360, 0.0697565, 0.0871557, 0.1045285, 0.1218693, 0.1391731, 0.1564345, 0.1736482, 0.1908090, 0.2079117, 0.2249510, 0.2419219, 0.2588190, 0.2756374, 0.2923717, @@ -88,7 +88,7 @@ static float sin_table[] = { -0.0000003 }; -static float cos_table[] = { +static float cosTable[] = { 1.0000000, 0.9998477, 0.9993908, 0.9986295, 0.9975641, 0.9961947, 0.9945219, 0.9925462, 0.9902681, 0.9876883, 0.9848078, 0.9816272, 0.9781476, 0.9743701, 0.9702957, 0.9659258, 0.9612617, 0.9563048, diff --git a/j3d/main.c b/j3d/main.c index c4a3722..f1f0797 100644 --- a/j3d/main.c +++ b/j3d/main.c @@ -61,9 +61,11 @@ int main(void) { jint16 x; jint16 y; jint16 c; - jlStaT *font = NULL; - j3WorldT *world = NULL; - bool r; + jint16 cubeId; + jint16 cubePieces; + jlStaT *font = NULL; + j3PropT *cube = NULL; + j3WorldT *world = NULL; jlUtilStartup("JoeyLib 3D"); jlStaLoad(font, "font"); @@ -74,8 +76,8 @@ int main(void) { printAt(font, 1, 1, "Loading object... "); jlDisplayPresent(); - r = j3WorldLoad(world, "cube"); - if (!r) { + cubePieces = j3PropLoad(cube, "cube"); + if (cubePieces < 0) { printAt(font, 1, 1, "Object loading: Failed."); jlDisplayPresent(); jlKeyWaitForAny(); @@ -83,14 +85,15 @@ int main(void) { printAt(font, 1, 1, "Object loading: Success!"); jlDisplayPresent(); + // Add prop to world + cubeId = j3WorldAddProp(world, cube); + // Assign fake colors until we can read them from the J3D c = 1; - for (x=0; xobjectCount; x++) { - for (y=0; yobjects[x].triangleCount; y++) { - world->objects[x].triangles[y].color = c++; - if (c > 15) { - c = 1; - } + for (y=0; yobjects[cubeId].triangleCount; y++) { + world->objects[cubeId].triangles[y].color = c++; + if (c > 15) { + c = 1; } } @@ -102,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].verticies[y].local.x, - (double)world->objects[x].verticies[y].local.y, - (double)world->objects[x].verticies[y].local.z + (double)world->objects[x].vertices[y].local.x, + (double)world->objects[x].vertices[y].local.y, + (double)world->objects[x].vertices[y].local.z ); } printf(" Triangles: %d\n", world->objects[x].triangleCount); @@ -130,14 +133,8 @@ int main(void) { jlDrawColor(15); jlDrawBox(0, 0, 319, 199); - //***TODO*** HACK!!! - _j3PolygonCount = 0; - for (x=0; xobjectCount; x++) { j3ObjectRotate(world->objects[x], 2, 4, 6); // Matching values in code I'm studying - j3ObjectUpdate(world->objects[x]); - //j3DrawWireframe(world->objects[x]); - //j3DrawSolid(world->objects[x]); j3DrawWorld(world); } @@ -157,6 +154,7 @@ int main(void) { jlKeyRead(); } + j3PropFree(cube); j3WorldFree(world); jlStaFree(font);