diff --git a/main.c b/main.c index 58755ed..5853404 100644 --- a/main.c +++ b/main.c @@ -76,8 +76,8 @@ typedef struct ps1texture_t front, back; } ps1skin_t; -ps1mdl_t playerModel = { .position = { -200, 160, 400 }, .rotation = { 0 } }; -ps1mdl_t shamblerModel = { .position = { 200, 160, 400 }, .rotation = { 0 } }; +ps1mdl_t playerModel = { .position = { -200, 200, -160 }, .rotation = { 0 } }; +ps1mdl_t shamblerModel = { .position = { 100, 200, -160 }, .rotation = { 0 } }; ps1skin_t playerSkin, shamblerSkin; const MATRIX identity = { @@ -87,6 +87,13 @@ const MATRIX identity = { 0, 0, 0, }; +const MATRIX quake_swizzle = { + ONE, 0, 0, + 0, 0, -ONE, + 0, ONE, 0, + 0, 0, 0, +}; + MATRIX light_cols = { ONE, 0, 0, ONE, 0, 0, @@ -361,7 +368,7 @@ static int fakeLight(const int *norm) SVECTOR outPos; -void drawModel(ps1mdl_t *model, ps1skin_t *skin, int frameCounter) +void drawModel(MATRIX *view_matrix, ps1mdl_t *model, ps1skin_t *skin, int frameCounter) { ps1texture_t *tex; short u0, u1, u2, uoffs, voffs; @@ -375,52 +382,18 @@ void drawModel(ps1mdl_t *model, ps1skin_t *skin, int frameCounter) int *scale = model->header->scale; int *translate = model->header->translate; - // Expected order of things: - // - Initial scale matrix to correct aspect ratio - // - Coordinate system swizzle (scale) (can probably be combined with the above) - // - Camera inverse translation - // - Camera inverse rotation (apply on top of camera translation) - // - Multiply light matrix (lights will be in Quake coordinate system) - // - Push matrix - // - Entity local rotation - // - Entity local translation - // - Model internal scale - // - Model internal translate - // - Render - // - Pop matrix - - // TODO: this can all probably be done much more efficiently with the CompMatrixLV function. Doing it manually first though to better understand it. - MATRIX cam_mtx = identity; - //VECTOR cam_inv_pos = { -cam_pos.vx, -cam_pos.vy, -cam_pos.vz }; - ScaleMatrixL(&cam_mtx, &aspect_scale); // Aspect ratio correction - //TransMatrix(&cam_mtx, &cam_inv_pos); - //MATRIX cam_rot_mtx; - //SVECTOR cam_inv_rot = { -cam_rot.vx, -cam_rot.vy, -cam_rot.vz, 0 }; - //RotMatrix(&cam_inv_rot, &cam_rot_mtx); - //MulMatrix(&cam_mtx, &cam_rot_mtx); - - MATRIX light_mtx; - // MulMatrix0(&light_dirs, &cam_mtx, &light_mtx); - // gte_SetLightMatrix(&light_mtx); - MATRIX model_mtx; RotMatrix(&model->rotation, &model_mtx); TransMatrix(&model_mtx, &model->position); - - MulMatrix(&model_mtx, &cam_mtx); + MATRIX light_mtx; MulMatrix0(&light_dirs, &model_mtx, &light_mtx); gte_SetLightMatrix(&light_mtx); - // Model internal scale and translate, to transform vertices from [0..255] range to a larger dynamic range with appropriate world-relative size - // Swizzle the coordinates because Quake Z is up - // Finding the appropriate scale range here is tricky. Without the << 2 scale the vertex coordinates become so small that you lose depth precision. - MATRIX local_mtx = { .m = { ONE << 2, 0, 0, 0, 0, -ONE << 2, 0, ONE << 2, 0 }, .t = { 0 } }; - ScaleMatrixL(&local_mtx, (VECTOR*)scale); - TransMatrix(&local_mtx, (VECTOR*)translate); - MulMatrix(&model_mtx, &local_mtx); + CompMatrixLV(view_matrix, &model_mtx, &model_mtx); + + PushMatrix(); - // TODO: set these after setting up camera, then use PushMatrix + CompMatrixLV for entities? gte_SetRotMatrix(&model_mtx); gte_SetTransMatrix(&model_mtx); @@ -499,6 +472,8 @@ void drawModel(ps1mdl_t *model, ps1skin_t *skin, int frameCounter) addPrim(ot[db] + depth, poly); nextpri += sizeof(POLY_GT3); } + + PopMatrix(); } void drawStuff(int counter) @@ -515,8 +490,38 @@ void drawStuff(int counter) gte_SetBackColor(48, 48, 48); // Ambient light color gte_SetColorMatrix(&light_cols); // Light color (up to three different lights) - drawModel(&playerModel, &playerSkin, counter >> 2); - drawModel(&shamblerModel, &shamblerSkin, counter >> 2); + // Expected order of things: + // - Initial scale matrix to correct aspect ratio + // - Coordinate system swizzle (scale) (can probably be combined with the above) + // - Camera inverse translation + // - Camera inverse rotation (apply on top of camera translation) + // - Multiply light matrix (lights will be in Quake coordinate system) + // - Push matrix + // - Entity local rotation + // - Entity local translation + // - Model internal scale + // - Model internal translate + // - Render + // - Pop matrix + + MATRIX proj_matrix = quake_swizzle; // Swizzle coordinates so that everything is in Quake coordinate system (Z up) + ScaleMatrixL(&proj_matrix, &aspect_scale); // Apply aspect ratio correction for the current resolution + + MATRIX view_matrix; + SVECTOR trot = { 0, 0, 0, 0 }; // TODO: camera rotation (in Quake coordinates) + VECTOR tpos = { 0, 0, 0 }; // TODO: camera position (in Quake coordinates) + RotMatrix(&trot, &view_matrix); // Set camera rotation part of the view matrix + ApplyMatrixLV(&view_matrix, &tpos, &tpos); // Apply camera rotation to camera position + TransMatrix(&view_matrix, &tpos); // Apply transformed position to the translation part of the view matrix + + // Compose view and projection matrices to obtain a combined view-projection matrix + CompMatrixLV(&proj_matrix, &view_matrix, &view_matrix); + + gte_SetRotMatrix(&view_matrix); + gte_SetTransMatrix(&view_matrix); + + drawModel(&view_matrix, &playerModel, &playerSkin, counter >> 2); + drawModel(&view_matrix, &shamblerModel, &shamblerSkin, counter >> 2); } // Main function, program entrypoint @@ -531,8 +536,6 @@ int main(int argc, const char *argv[]) counter = 0; while(1) { - playerModel.rotation.vz = (counter << 2) % ONE; - drawStuff(counter); // Update display