Camera support.

This commit is contained in:
Scott Duensing 2019-08-29 21:06:10 -05:00
parent 18fab39c08
commit 7f0e1974ee
2 changed files with 214 additions and 119 deletions

274
j3d/j3d.c
View file

@ -28,6 +28,8 @@
//***TODO*** //***TODO***
// Allow multiple objects to be loaded into a world // Allow multiple objects to be loaded into a world
// Store original vertex data so we can do local rotations and save them // Store original vertex data so we can do local rotations and save them
// Rename verticies to vertices
// Remove _ from sin_table and cos_table
#include <math.h> #include <math.h>
@ -54,17 +56,20 @@ segment "j3d";
// Module global data // Module global data
static jint16 clipMinX = 0; jint16 _j3VarClipMinX = 0;
static jint16 clipMinY = 0; jint16 _j3VarClipMinY = 0;
static jint16 clipMinZ = 100; jint16 _j3VarClipMinZ = 100;
static jint16 clipMaxX = 319; jint16 _j3VarClipMaxX = 319;
static jint16 clipMaxY = 199; jint16 _j3VarClipMaxY = 199;
static jint16 clipMaxZ = 3000; jint16 _j3VarClipMaxZ = 3000;
static jint16 viewDistance = 250; jint16 _j3VarViewDistance = 250;
static float ambientLight = 6; float _j3VarAmbientLight = 6;
static j3VertexT cameraLocation; j3Matrix4x4T _j3VarCameraMatrix;
static j3FacingT cameraAngle; j3VertexT _j3VarCameraLocation;
static j3VertexT sunLocation; j3FacingT _j3VarCameraAngle;
bool _j3VarCameraLocationDirty = true;
bool _j3VarCameraAngleDirty = true;
j3VertexT _j3VarSunLocation;
#define ASPECT_RATIO (float)0.8 #define ASPECT_RATIO (float)0.8
@ -105,7 +110,7 @@ void _j3DrawSolid(j3ObjectT *o) {
z3 = o->verticies[vertex3].camera.z; z3 = o->verticies[vertex3].camera.z;
// Perform z clipping // Perform z clipping
if ((z1 < clipMinZ && z2 < clipMinZ && z3 < clipMinZ) || (z1 > clipMaxZ && z2 > clipMaxZ && z3 > clipMaxZ)) { if ((z1 < _j3VarClipMinZ && z2 < _j3VarClipMinZ && z3 < _j3VarClipMinZ) || (z1 > _j3VarClipMaxZ && z2 > _j3VarClipMaxZ && z3 > _j3VarClipMaxZ)) {
continue; continue;
} }
@ -118,12 +123,12 @@ void _j3DrawSolid(j3ObjectT *o) {
y3 = o->verticies[vertex3].camera.y; y3 = o->verticies[vertex3].camera.y;
// Screen position of points // Screen position of points
x1 = HALF_SCREEN_WIDTH + x1 * viewDistance / z1; x1 = HALF_SCREEN_WIDTH + x1 * _j3VarViewDistance / z1;
y1 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y1 * viewDistance / z1; y1 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y1 * _j3VarViewDistance / z1;
x2 = HALF_SCREEN_WIDTH + x2 * viewDistance / z2; x2 = HALF_SCREEN_WIDTH + x2 * _j3VarViewDistance / z2;
y2 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y2 * viewDistance / z2; y2 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y2 * _j3VarViewDistance / z2;
x3 = HALF_SCREEN_WIDTH + x3 * viewDistance / z3; x3 = HALF_SCREEN_WIDTH + x3 * _j3VarViewDistance / z3;
y3 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y3 * viewDistance / 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); j3DrawTriangle2D((jint16)x1, (jint16)y1, (jint16)x2, (jint16)y2, (jint16)x3, (jint16)y3, o->triangles[t].shade);
} }
@ -169,7 +174,7 @@ void j3DrawTriangle2D(jint16 x1, jint16 y1, jint16 x2,jint16 y2, jint16 x3, jint
} // end if } // end if
// Trivial rejection tests // Trivial rejection tests
if (y3 < clipMinY || y1 > clipMaxY || (x1 < clipMinX && x2 < clipMinX && x3 < clipMinX) || (x1 > clipMaxX && x2 > clipMaxX && x3 > clipMaxX)) { if (y3 < _j3VarClipMinY || y1 > _j3VarClipMaxY || (x1 < _j3VarClipMinX && x2 < _j3VarClipMinX && x3 < _j3VarClipMinX) || (x1 > _j3VarClipMaxX && x2 > _j3VarClipMaxX && x3 > _j3VarClipMaxX)) {
return; return;
} }
@ -220,19 +225,19 @@ void _j3DrawTriangleBottom(jint16 x1, jint16 y1, jint16 x2,jint16 y2, jint16 x3,
xe = (float)x1 + (float)0.5; xe = (float)x1 + (float)0.5;
// Perform y clipping // Perform y clipping
if (y1 < clipMinY) { if (y1 < _j3VarClipMinY) {
// Compute new xs and ys // Compute new xs and ys
xs = xs + dxLeft * (float)(-y1 + clipMinY); xs = xs + dxLeft * (float)(-y1 + _j3VarClipMinY);
xe = xe + dxRight * (float)(-y1 + clipMinY); xe = xe + dxRight * (float)(-y1 + _j3VarClipMinY);
// Reset y1 // Reset y1
y1 = clipMinY; y1 = _j3VarClipMinY;
} }
if (y3 > clipMaxY) { if (y3 > _j3VarClipMaxY) {
y3 = clipMaxY; y3 = _j3VarClipMaxY;
} }
// Test if x clipping is needed // Test if x clipping is needed
if (x1 >= clipMinX && x1 <= clipMaxX && x2 >= clipMinX && x2 <= clipMaxX && x3 >= clipMinX && x3 <= clipMaxX) { if (x1 >= _j3VarClipMinX && x1 <= _j3VarClipMaxX && x2 >= _j3VarClipMinX && x2 <= _j3VarClipMaxX && x3 >= _j3VarClipMinX && x3 <= _j3VarClipMaxX) {
// Draw the triangle // Draw the triangle
for (tempY=y1; tempY<=y3; tempY++) { for (tempY=y1; tempY<=y3; tempY++) {
jlDrawLine((jint16)xs, tempY, (jint16)xe, tempY); jlDrawLine((jint16)xs, tempY, (jint16)xe, tempY);
@ -250,15 +255,15 @@ void _j3DrawTriangleBottom(jint16 x1, jint16 y1, jint16 x2,jint16 y2, jint16 x3,
xs += dxLeft; xs += dxLeft;
xe += dxRight; xe += dxRight;
// Clip line // Clip line
if (left < clipMinX) { if (left < _j3VarClipMinX) {
left = clipMinX; left = _j3VarClipMinX;
if (right < clipMinX) { if (right < _j3VarClipMinX) {
continue; continue;
} }
} }
if (right > clipMaxX) { if (right > _j3VarClipMaxX) {
right = clipMaxX; right = _j3VarClipMaxX;
if (left > clipMaxX) { if (left > _j3VarClipMaxX) {
continue; continue;
} }
} }
@ -299,19 +304,19 @@ void _j3DrawTriangleTop(jint16 x1, jint16 y1, jint16 x2,jint16 y2, jint16 x3, ji
xe = (float)x2 + (float)0.5; xe = (float)x2 + (float)0.5;
// Perform y clipping // Perform y clipping
if (y1 < clipMinY) { if (y1 < _j3VarClipMinY) {
// Compute new xs and ys // Compute new xs and ys
xs = xs + dxLeft * (float)(-y1 + clipMinY); xs = xs + dxLeft * (float)(-y1 + _j3VarClipMinY);
xe = xe + dxRight * (float)(-y1 + clipMinY); xe = xe + dxRight * (float)(-y1 + _j3VarClipMinY);
// Reset y1 // Reset y1
y1 = clipMinY; y1 = _j3VarClipMinY;
} }
if (y3 > clipMaxY) { if (y3 > _j3VarClipMaxY) {
y3=clipMaxY; y3=_j3VarClipMaxY;
} }
// Test if x clipping is needed // Test if x clipping is needed
if (x1 >= clipMinX && x1 <= clipMaxX && x2 >= clipMinX && x2 <= clipMaxX && x3 >= clipMinX && x3 <= clipMaxX) { if (x1 >= _j3VarClipMinX && x1 <= _j3VarClipMaxX && x2 >= _j3VarClipMinX && x2 <= _j3VarClipMaxX && x3 >= _j3VarClipMinX && x3 <= _j3VarClipMaxX) {
// Draw the triangle // Draw the triangle
for (tempY=y1; tempY<=y3; tempY++) { for (tempY=y1; tempY<=y3; tempY++) {
jlDrawLine((jint16)xs, tempY, (jint16)xe, tempY); jlDrawLine((jint16)xs, tempY, (jint16)xe, tempY);
@ -329,15 +334,15 @@ void _j3DrawTriangleTop(jint16 x1, jint16 y1, jint16 x2,jint16 y2, jint16 x3, ji
xs += dxLeft; xs += dxLeft;
xe += dxRight; xe += dxRight;
// Clip line // Clip line
if (left < clipMinX) { if (left < _j3VarClipMinX) {
left = clipMinX; left = _j3VarClipMinX;
if (right < clipMinX) { if (right < _j3VarClipMinX) {
continue; continue;
} }
} }
if (right > clipMaxX) { if (right > _j3VarClipMaxX) {
right = clipMaxX; right = _j3VarClipMaxX;
if (left > clipMaxX) { if (left > _j3VarClipMaxX) {
continue; continue;
} }
} }
@ -371,11 +376,11 @@ void _j3DrawWireframePair(j3ObjectT *o, juint16 v1, juint16 v2) {
y2 = v.y; y2 = v.y;
z2 = v.z; z2 = v.z;
x1 = HALF_SCREEN_WIDTH + x1 * viewDistance / z1; x1 = HALF_SCREEN_WIDTH + x1 * _j3VarViewDistance / z1;
y1 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y1 * viewDistance / z1; y1 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y1 * _j3VarViewDistance / z1;
x2 = HALF_SCREEN_WIDTH + x2 * viewDistance / z2; x2 = HALF_SCREEN_WIDTH + x2 * _j3VarViewDistance / z2;
y2 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y2 * viewDistance / z2; y2 = HALF_SCREEN_HEIGHT - ASPECT_RATIO * y2 * _j3VarViewDistance / z2;
ix1 = (jint16)x1; ix1 = (jint16)x1;
iy1 = (jint16)y1; iy1 = (jint16)y1;
@ -497,6 +502,9 @@ void _j3ObjectUpdate(j3ObjectT *o) {
j3Matrix4x4T rotateZ; j3Matrix4x4T rotateZ;
j3Matrix4x4T final; j3Matrix4x4T final;
j3Matrix4x4T temp; j3Matrix4x4T temp;
j3Matrix4x4T result1;
j3Matrix4x4T result2;
j3Matrix4x4T translate;
// === ROTATION === // === ROTATION ===
@ -655,10 +663,60 @@ void _j3ObjectUpdate(j3ObjectT *o) {
} }
// === CAMERA SPACE === // === CAMERA SPACE ===
//***TODO*** Move this?
for (i=0; i<o->vertexCount; i++) { //***TODO*** Move this when we add multiple object stuff and re-do this function
o->verticies[i].camera = o->verticies[i].world; if (_j3VarCameraLocationDirty || _j3VarCameraAngleDirty) {
// 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;
// Z 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]);
// 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]);
// 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]);
j3MathMatrix4x4Mult(translate, rotateX, result1);
j3MathMatrix4x4Mult(result1, rotateY, result2);
j3MathMatrix4x4Mult(result2, rotateZ, _j3VarCameraMatrix);
_j3VarCameraLocationDirty = false;
_j3VarCameraAngleDirty = false;
}
if (o->positionDirty || o->rotationDirty) {
for (i=0; i<o->vertexCount; 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] + _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] + _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] + _j3VarCameraMatrix[3][2];
}
} }
// === REMOVE BACKFACES & LIGHT === // === REMOVE BACKFACES & LIGHT ===
@ -683,9 +741,9 @@ void _j3ObjectUpdate(j3ObjectT *o) {
j3MathCrossProduct3D((j3Vector3DT *)&v, (j3Vector3DT *)&u, (j3Vector3DT *)&normal); j3MathCrossProduct3D((j3Vector3DT *)&v, (j3Vector3DT *)&u, (j3Vector3DT *)&normal);
// Compute the line of sight vector, since all coordinates are world all // Compute the line of sight vector, since all coordinates are world all
// object vertices are already relative to (0,0,0), thus // object vertices are already relative to (0,0,0), thus
sight.x = cameraLocation.x - o->verticies[vertex0].world.x; sight.x = _j3VarCameraLocation.x - o->verticies[vertex0].world.x;
sight.y = cameraLocation.y - o->verticies[vertex0].world.y; sight.y = _j3VarCameraLocation.y - o->verticies[vertex0].world.y;
sight.z = cameraLocation.z - o->verticies[vertex0].world.z; sight.z = _j3VarCameraLocation.z - o->verticies[vertex0].world.z;
// Compute the dot product between line of sight vector and normal to surface // Compute the dot product between line of sight vector and normal to surface
dot = j3MathDotProduct3D((j3Vector3DT *)&normal, (j3Vector3DT *)&sight); dot = j3MathDotProduct3D((j3Vector3DT *)&normal, (j3Vector3DT *)&sight);
@ -697,10 +755,10 @@ void _j3ObjectUpdate(j3ObjectT *o) {
// Compute light intensity if needed // Compute light intensity if needed
if (o->triangles[i].lit) { if (o->triangles[i].lit) {
// Compute the dot product between the light source vector and normal vector to surface // Compute the dot product between the light source vector and normal vector to surface
dot = j3MathDotProduct3D((j3Vector3DT *)&normal, (j3Vector3DT *)&sunLocation); dot = j3MathDotProduct3D((j3Vector3DT *)&normal, (j3Vector3DT *)&_j3VarSunLocation);
// Test if light ray is reflecting off surface // Test if light ray is reflecting off surface
if (dot > 0) { if (dot > 0) {
intensity = ambientLight + (dot * (o->triangles[i].normalLength)); intensity = _j3VarAmbientLight + (dot * (o->triangles[i].normalLength));
// Test if intensity has overflowed // Test if intensity has overflowed
if (intensity > 15) { if (intensity > 15) {
intensity = 15; intensity = 15;
@ -709,7 +767,7 @@ void _j3ObjectUpdate(j3ObjectT *o) {
// totally illuminated. use the value to index into color table // totally illuminated. use the value to index into color table
o->triangles[i].shade = o->triangles[i].color - (jint16)intensity; o->triangles[i].shade = o->triangles[i].color - (jint16)intensity;
} else { } else {
o->triangles[i].shade = o->triangles[i].color - (jint16)ambientLight; o->triangles[i].shade = o->triangles[i].color - (jint16)_j3VarAmbientLight;
} }
} else { } else {
// Constant shading - simply assign color to shade // Constant shading - simply assign color to shade
@ -738,12 +796,12 @@ void _j3ObjectUpdate(j3ObjectT *o) {
// Normal v x u // Normal v x u
j3MathCrossProduct3D((j3Vector3DT *)&v, (j3Vector3DT *)&u, (j3Vector3DT *)&normal); j3MathCrossProduct3D((j3Vector3DT *)&v, (j3Vector3DT *)&u, (j3Vector3DT *)&normal);
// Compute the dot product between the light source vector and normal vector to surface // Compute the dot product between the light source vector and normal vector to surface
dot = j3MathDotProduct3D((j3Vector3DT *)&normal, (j3Vector3DT *)&sunLocation); dot = j3MathDotProduct3D((j3Vector3DT *)&normal, (j3Vector3DT *)&_j3VarSunLocation);
// Is light ray is reflecting off surface // Is light ray is reflecting off surface
if (dot > 0) { if (dot > 0) {
// cos 0 = (u.v)/|u||v| or // cos 0 = (u.v)/|u||v| or
intensity = ambientLight + (dot * (o->triangles[i].normalLength)); intensity = _j3VarAmbientLight + (dot * (o->triangles[i].normalLength));
// test if intensity has overflowed // test if intensity has overflowed
if (intensity > 15) { if (intensity > 15) {
intensity = 15; intensity = 15;
@ -752,7 +810,7 @@ void _j3ObjectUpdate(j3ObjectT *o) {
// totally illuminated. use the value to index into color table // totally illuminated. use the value to index into color table
o->triangles[i].shade = o->triangles[i].color - (jint16)intensity; o->triangles[i].shade = o->triangles[i].color - (jint16)intensity;
} else { } else {
o->triangles[i].shade = o->triangles[i].color - (jint16)ambientLight; o->triangles[i].shade = o->triangles[i].color - (jint16)_j3VarAmbientLight;
} }
} else { } else {
// Constant shading and simply assign color to shade // Constant shading and simply assign color to shade
@ -808,8 +866,8 @@ bool _j3UtilClipLine(jint16 *x1, jint16 *y1, jint16 *x2, jint16 *y2) {
bool success = false; // Did we successfully clip this line? bool success = false; // Did we successfully clip this line?
// Is the line completely visible? // Is the line completely visible?
point1 = ((*x1 >= clipMinX) && (*x1 <= clipMaxX) && (*y1 >= clipMinY) && (*y1 <= clipMaxY)); point1 = ((*x1 >= _j3VarClipMinX) && (*x1 <= _j3VarClipMaxX) && (*y1 >= _j3VarClipMinY) && (*y1 <= _j3VarClipMaxY));
point2 = ((*x2 >= clipMinX) && (*x2 <= clipMaxX) && (*y2 >= clipMinY) && (*y2 <= clipMaxY)); point2 = ((*x2 >= _j3VarClipMinX) && (*x2 <= _j3VarClipMaxX) && (*y2 >= _j3VarClipMinY) && (*y2 <= _j3VarClipMaxY));
if (point1 && point2) { if (point1 && point2) {
return(true); return(true);
} }
@ -818,10 +876,10 @@ bool _j3UtilClipLine(jint16 *x1, jint16 *y1, jint16 *x2, jint16 *y2) {
if (!point1 && !point2) { if (!point1 && !point2) {
// Test to see if each endpoint is on the same side of one of // Test to see if each endpoint is on the same side of one of
// the bounding planes created by each clipping region boundary // the bounding planes created by each clipping region boundary
if (((*x1<clipMinX) && (*x2<clipMinX)) || // left if (((*x1<_j3VarClipMinX) && (*x2<_j3VarClipMinX)) || // left
((*x1>clipMaxX) && (*x2>clipMaxX)) || // right ((*x1>_j3VarClipMaxX) && (*x2>_j3VarClipMaxX)) || // right
((*y1<clipMinY) && (*y2<clipMinY)) || // above ((*y1<_j3VarClipMinY) && (*y2<_j3VarClipMinY)) || // above
((*y1>clipMaxY) && (*y2>clipMaxY))) { // below ((*y1>_j3VarClipMaxY) && (*y2>_j3VarClipMaxY))) { // below
// No need to draw line // No need to draw line
return(false); return(false);
} }
@ -837,41 +895,41 @@ bool _j3UtilClipLine(jint16 *x1, jint16 *y1, jint16 *x2, jint16 *y2) {
dy = *y2 - *y1; dy = *y2 - *y1;
// Find which boundary line needs to be clipped against // Find which boundary line needs to be clipped against
if (*x2 > clipMaxX) { if (*x2 > _j3VarClipMaxX) {
// Flag right edge // Flag right edge
rightEdge = true; rightEdge = true;
// Find intersection with right edge // Find intersection with right edge
if (fabsf(dx) > FLT_EPSILON) { // dx != 0 if (fabsf(dx) > FLT_EPSILON) { // dx != 0
yi = (jint16)((float)0.5 + (dy / dx) * (clipMaxX - *x1) + *y1); yi = (jint16)((float)0.5 + (dy / dx) * (_j3VarClipMaxX - *x1) + *y1);
} else { } else {
yi = -1; // Invalidate intersection yi = -1; // Invalidate intersection
} }
} else if (*x2 < clipMinX) { } else if (*x2 < _j3VarClipMinX) {
// Flag left edge // Flag left edge
leftEdge = true; leftEdge = true;
// Find intersection with left edge // Find intersection with left edge
if (fabsf(dx) > FLT_EPSILON) { // dx != 0 if (fabsf(dx) > FLT_EPSILON) { // dx != 0
yi = (jint16)((float)0.5 + (dy / dx) * (clipMinX - *x1) + *y1); yi = (jint16)((float)0.5 + (dy / dx) * (_j3VarClipMinX - *x1) + *y1);
} else { } else {
yi = -1; // Invalidate intersection yi = -1; // Invalidate intersection
} }
} }
if (*y2 > clipMaxY) { if (*y2 > _j3VarClipMaxY) {
// Flag bottom edge // Flag bottom edge
bottomEdge = true; bottomEdge = true;
// Find intersection with right edge // Find intersection with right edge
if (fabsf(dy) > FLT_EPSILON) { // dy != 0 if (fabsf(dy) > FLT_EPSILON) { // dy != 0
xi = (jint16)((float)0.5 + (dx / dy) * (clipMaxY - *y1) + *x1); xi = (jint16)((float)0.5 + (dx / dy) * (_j3VarClipMaxY - *y1) + *x1);
} else { } else {
xi = -1; // Invalidate inntersection xi = -1; // Invalidate inntersection
} }
} else if (*y2 < clipMinY) { } else if (*y2 < _j3VarClipMinY) {
// Flag top edge // Flag top edge
topEdge = true; topEdge = true;
// Find intersection with top edge // Find intersection with top edge
if (fabsf(dy) > FLT_EPSILON) { // dy != 0 if (fabsf(dy) > FLT_EPSILON) { // dy != 0
xi = (jint16)((float)0.5 + (dx / dy) * (clipMinY - *y1) + *x1); xi = (jint16)((float)0.5 + (dx / dy) * (_j3VarClipMinY - *y1) + *x1);
} else { } else {
xi = -1; // Invalidate intersection xi = -1; // Invalidate intersection
} }
@ -880,23 +938,23 @@ bool _j3UtilClipLine(jint16 *x1, jint16 *y1, jint16 *x2, jint16 *y2) {
// We know where the line passed through // We know where the line passed through
// FInd which edge is the proper intersection // FInd which edge is the proper intersection
if (rightEdge && (yi >= clipMinY && yi <= clipMaxY)) { if (rightEdge && (yi >= _j3VarClipMinY && yi <= _j3VarClipMaxY)) {
*x2 = clipMaxX; *x2 = _j3VarClipMaxX;
*y2 = yi; *y2 = yi;
success = true; success = true;
} else if (leftEdge && (yi >= clipMinY && yi <= clipMaxY)) { } else if (leftEdge && (yi >= _j3VarClipMinY && yi <= _j3VarClipMaxY)) {
*x2 = clipMinX; *x2 = _j3VarClipMinX;
*y2 = yi; *y2 = yi;
success = true; success = true;
} }
if (bottomEdge && (xi >= clipMinX && xi <= clipMaxX)) { if (bottomEdge && (xi >= _j3VarClipMinX && xi <= _j3VarClipMaxX)) {
*x2 = xi; *x2 = xi;
*y2 = clipMaxY; *y2 = _j3VarClipMaxY;
success = true; success = true;
} else if (topEdge && (xi >= clipMinX && xi <= clipMaxX)) { } else if (topEdge && (xi >= _j3VarClipMinX && xi <= _j3VarClipMaxX)) {
*x2 = xi; *x2 = xi;
*y2 = clipMinY; *y2 = _j3VarClipMinY;
success = true; success = true;
} }
} }
@ -915,41 +973,41 @@ bool _j3UtilClipLine(jint16 *x1, jint16 *y1, jint16 *x2, jint16 *y2) {
dy = *y1 - *y2; dy = *y1 - *y2;
// Find which boundary line needs to be clipped against // Find which boundary line needs to be clipped against
if (*x1 > clipMaxX) { if (*x1 > _j3VarClipMaxX) {
// Flag right edge // Flag right edge
rightEdge = true; rightEdge = true;
// Find intersection with right edge // Find intersection with right edge
if (fabsf(dx) > FLT_EPSILON) { // dx != 0 if (fabsf(dx) > FLT_EPSILON) { // dx != 0
yi = (jint16)((float)0.5 + (dy / dx) * (clipMaxX - *x2) + *y2); yi = (jint16)((float)0.5 + (dy / dx) * (_j3VarClipMaxX - *x2) + *y2);
} else { } else {
yi = -1; // Invalidate inntersection yi = -1; // Invalidate inntersection
} }
} else if (*x1 < clipMinX) { } else if (*x1 < _j3VarClipMinX) {
// Flag left edge // Flag left edge
leftEdge = true; leftEdge = true;
// Find intersection with left edge // Find intersection with left edge
if (fabsf(dx) > FLT_EPSILON) { // dx != 0 if (fabsf(dx) > FLT_EPSILON) { // dx != 0
yi = (jint16)((float)0.5 + (dy / dx) * (clipMinX - *x2) + *y2); yi = (jint16)((float)0.5 + (dy / dx) * (_j3VarClipMinX - *x2) + *y2);
} else { } else {
yi = -1; // Invalidate intersection yi = -1; // Invalidate intersection
} }
} }
if (*y1 > clipMaxY) { if (*y1 > _j3VarClipMaxY) {
// Flag bottom edge // Flag bottom edge
bottomEdge = true; bottomEdge = true;
// Find intersection with right edge // Find intersection with right edge
if (fabsf(dy) > FLT_EPSILON) { // dy != 0 if (fabsf(dy) > FLT_EPSILON) { // dy != 0
xi = (jint16)((float)0.5 + (dx / dy) * (clipMaxY - *y2) + *x2); xi = (jint16)((float)0.5 + (dx / dy) * (_j3VarClipMaxY - *y2) + *x2);
} else { } else {
xi = -1; // invalidate inntersection xi = -1; // invalidate inntersection
} }
} else if (*y1 < clipMinY) { } else if (*y1 < _j3VarClipMinY) {
// Flag top edge // Flag top edge
topEdge = true; topEdge = true;
// Find intersection with top edge // Find intersection with top edge
if (fabsf(dy) > FLT_EPSILON) { // dy != 0 if (fabsf(dy) > FLT_EPSILON) { // dy != 0
xi = (jint16)((float)0.5 + (dx / dy) * (clipMinY - *y2) + *x2); xi = (jint16)((float)0.5 + (dx / dy) * (_j3VarClipMinY - *y2) + *x2);
} else { } else {
xi = -1; // invalidate inntersection xi = -1; // invalidate inntersection
} }
@ -958,23 +1016,23 @@ bool _j3UtilClipLine(jint16 *x1, jint16 *y1, jint16 *x2, jint16 *y2) {
// We know where the line passed through // We know where the line passed through
// Find which edge is the proper intersection // Find which edge is the proper intersection
if (rightEdge && (yi >= clipMinY && yi <= clipMaxY)) { if (rightEdge && (yi >= _j3VarClipMinY && yi <= _j3VarClipMaxY)) {
*x1 = clipMaxX; *x1 = _j3VarClipMaxX;
*y1 = yi; *y1 = yi;
success = true; success = true;
} else if (leftEdge && (yi >= clipMinY && yi <= clipMaxY)) { } else if (leftEdge && (yi >= _j3VarClipMinY && yi <= _j3VarClipMaxY)) {
*x1 = clipMinX; *x1 = _j3VarClipMinX;
*y1 = yi; *y1 = yi;
success = true; success = true;
} }
if (bottomEdge && (xi >= clipMinX && xi <= clipMaxX)) { if (bottomEdge && (xi >= _j3VarClipMinX && xi <= _j3VarClipMaxX)) {
*x1 = xi; *x1 = xi;
*y1 = clipMaxY; *y1 = _j3VarClipMaxY;
success = true; success = true;
} else if (topEdge && (xi >= clipMinX && xi <= clipMaxX)) { } else if (topEdge && (xi >= _j3VarClipMinX && xi <= _j3VarClipMaxX)) {
*x1 = xi; *x1 = xi;
*y1 = clipMinY; *y1 = _j3VarClipMinY;
success = true; success = true;
} }
} }
@ -989,17 +1047,17 @@ void j3UtilShutdown(void) {
void j3UtilStartup(void) { void j3UtilStartup(void) {
cameraLocation.x = 0; _j3VarCameraLocation.x = 0;
cameraLocation.y = 0; _j3VarCameraLocation.y = 0;
cameraLocation.z = 0; _j3VarCameraLocation.z = 0;
cameraAngle.x = 0; _j3VarCameraAngle.x = 0;
cameraAngle.y = 0; _j3VarCameraAngle.y = 0;
cameraAngle.z = 0; _j3VarCameraAngle.z = 0;
sunLocation.x = (float)-0.913913; _j3VarSunLocation.x = (float)-0.913913;
sunLocation.y = (float) 0.389759; _j3VarSunLocation.y = (float) 0.389759;
sunLocation.z = (float)-0.113369; _j3VarSunLocation.z = (float)-0.113369;
} }

View file

@ -27,9 +27,6 @@
#include "joey.h" #include "joey.h"
//***TODO*** verticies is vertices
typedef float j3Matrix4x4T[4][4]; typedef float j3Matrix4x4T[4][4];
typedef struct { typedef struct {
@ -79,11 +76,51 @@ typedef struct {
} j3WorldT; } j3WorldT;
#define jtCameraSetClippingBounds(x1, y1, x2, y2) \ extern jint16 _j3VarClipMinX;
clipMinX = (x1); j3MathCheckBounds(clipMinX, 0, 319); \ extern jint16 _j3VarClipMinY;
clipMinY = (y1); j3MathCheckBounds(clipMiny, 0, 199); \ extern jint16 _j3VarClipMinZ;
clipMaxX = (x2); j3MathCheckBounds(clipMaxX, 0, 319); \ extern jint16 _j3VarClipMaxX;
clipMaxY = (y2); j3MathCheckBounds(clipMaxy, 0, 199) 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;
#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)
#define j3MathCheckBounds(value, min, max) \ #define j3MathCheckBounds(value, min, max) \
if (value < (min)) value = (min); \ if (value < (min)) value = (min); \
@ -100,9 +137,9 @@ typedef struct {
ob.positionDirty = true ob.positionDirty = true
#define j3ObjectMoveTo(ob, px, py, pz) \ #define j3ObjectMoveTo(ob, px, py, pz) \
ob.position.x = (px); \ ob.position.x = (px); \
ob.position.y = (py); \ ob.position.y = (py); \
ob.position.z = (pz); \ ob.position.z = (pz); \
ob.positionDirty = true ob.positionDirty = true
#define j3ObjectRotate(ob, px, py, pz) \ #define j3ObjectRotate(ob, px, py, pz) \