135 lines
4.2 KiB
C++
135 lines
4.2 KiB
C++
|
|
#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);
|
|
}
|
|
|