#include "model.hpp" #include "polygon.hpp" /******************************************************************************* ** ModelCreate *******************************************************************************/ Model ModelCreate(Picture* skin) { Model model; memset(&model, 0, sizeof(Model)); model.skin = *skin; return model; } /******************************************************************************* ** ModelAnimate *******************************************************************************/ void ModelAnimate(Model* model) { Vector* A; Vector* B; Vector* dst; Matrix matrix; Vector vector; float scale; int frame, i; MatrixRotateXYZ(matrix, model->rot.pos); frame = model->frame.pos[0]; A = model->keyframes[(frame + 0) % NumberOf(model->keyframes)]; B = model->keyframes[(frame + 1) % NumberOf(model->keyframes)]; dst = model->XYZ; scale = model->frame.pos[0] - frame; for (i = 0; i < NumberOf(model->XYZ); i++) { vector[0] = Interpolate(scale, A[i][0], B[i][0]) * model->scale.pos[0]; vector[1] = Interpolate(scale, A[i][1], B[i][1]) * model->scale.pos[1]; vector[2] = Interpolate(scale, A[i][2], B[i][2]) * model->scale.pos[2]; dst[i][0] = VectorDotProduct(vector, matrix[0]) + model->pos.pos[0]; dst[i][1] = VectorDotProduct(vector, matrix[1]) + model->pos.pos[1]; dst[i][2] = VectorDotProduct(vector, matrix[2]) + model->pos.pos[2]; } } /******************************************************************************* ** ModelRead *******************************************************************************/ Model ModelRead(Picture* skin) { Model model = ModelCreate(skin); model.keyframes = VectorArrayArrayRead(stdin); model.XYZ = (Vector*)MemoryAlloc(NumberOf(model.keyframes[0]), sizeof(Vector)); model.polys = MeshFaceArrayRead(); model.UVW = (Vector*)MemoryRead(stdin); ModelAnimate(&model); return model; } /******************************************************************************* ** ModelRender *******************************************************************************/ void ModelRender(Model* model, Camera* camera) { Vertex t1[POLYGON_MAX]; Vertex t2[POLYGON_MAX]; MeshFace* poly; int i, j, n, vid; assert(model && camera); ModelAnimate(model); PolygonTransform(model->XYZ, model->XYZ, NumberOf(model->XYZ), camera->matrix); for (i = 0; i < NumberOf(model->polys); i++) { poly = &model->polys[i]; n = NumberOf(poly->ids); for (j = 0; j < n; j++) { vid = poly->ids[j]; t1[j][0][0] = model->XYZ[vid][0]; t1[j][0][1] = model->XYZ[vid][1]; t1[j][0][2] = model->XYZ[vid][2]; t1[j][1][0] = model->UVW[vid][0]; t1[j][1][1] = model->UVW[vid][1]; } n = VertexArrayClipToFrustum2(t2, t1, n); if (n >= POLYGON_MIN) { for (j = 0; j < n; j++) { t2[j][1][0] *= model->skin.width; t2[j][1][1] *= model->skin.height; t2[j][1][2] = 2500000.0f / VectorDotProduct(t2[j][0], t2[j][0]); t2[j][1][2] = Min(t2[j][1][2], 255.0f); } VertexArrayProject(t2, n, camera->origin); /* ** Simple backface removal. Could be done better. Maybe? */ if ( (t2[2][0][0] - t2[1][0][0]) * (t2[0][0][1] - t2[1][0][1]) - (t2[2][0][1] - t2[1][0][1]) * (t2[0][0][0] - t2[1][0][0]) > 0) { VertexArrayScanXYZUVW(t2, n); DDATextureMap(camera->fb, &model->skin, camera->zb); } } } } /******************************************************************************* ** ModelTick *******************************************************************************/ void ModelTick(Model* model) { assert(model != NULL); MotionTick(&model->pos); MotionTick(&model->rot); MotionTick(&model->frame); }