cos2000v2/lib/3d.c

281 lines
7.1 KiB
C

/*******************************************************************************/
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
#include "3d.h"
#include "types.h"
#include "video.h"
#include "string.h"
/*******************************************************************************/
/* Crée une projection simple pour test */
void proj(vector4 list[], vertex2d plane[], vector4 origin[], u16 number,
float factor)
{
for (u32 i = 0; i < number; i++)
{
plane[i].x =
(int) ((list[i].x * factor) /
(list[i].z + origin->z) + origin->x);
plane[i].y =
(int) ((list[i].y * factor) /
(list[i].z + origin->z) + origin->y);
}
}
/*******************************************************************************/
/* Crée une liste de vertex3D pour un cube */
void cube(model3d * model, vector4 * origin, u16 size)
{
strcpy("cube", model->name);
model->vertexnb = 8;
model->vertexlist = 0x00300000;
model->vertexlist[0].x = origin->x;
model->vertexlist[0].y = origin->y;
model->vertexlist[0].z = origin->z;
model->vertexlist[0].w = 1.0f;
model->vertexlist[1].x = origin->x + size;
model->vertexlist[1].y = origin->y;
model->vertexlist[1].z = origin->z;
model->vertexlist[1].w = 1.0f;
model->vertexlist[2].x = origin->x;
model->vertexlist[2].y = origin->y + size;
model->vertexlist[2].z = origin->z;
model->vertexlist[2].w = 1.0f;
model->vertexlist[3].x = origin->x + size;
model->vertexlist[3].y = origin->y + size;
model->vertexlist[3].z = origin->z;
model->vertexlist[3].w = 1.0f;
model->vertexlist[4].x = origin->x;
model->vertexlist[4].y = origin->y;
model->vertexlist[4].z = origin->z + size;
model->vertexlist[4].w = 1.0f;
model->vertexlist[5].x = origin->x + size;
model->vertexlist[5].y = origin->y;
model->vertexlist[5].z = origin->z + size;
model->vertexlist[5].w = 1.0f;
model->vertexlist[6].x = origin->x;
model->vertexlist[6].y = origin->y + size;
model->vertexlist[6].z = origin->z + size;
model->vertexlist[6].w = 1.0f;
model->vertexlist[7].x = origin->x + size;
model->vertexlist[7].y = origin->y + size;
model->vertexlist[7].z = origin->z + size;
model->vertexlist[7].w = 1.0f;
model->facelist = 0x00310000;
model->facelist[0].V1 = 0;
model->facelist[0].V2 = 1;
model->facelist[0].V3 = 3;
model->facelist[1].V1 = 0;
model->facelist[1].V2 = 2;
model->facelist[1].V3 = 3;
model->facelist[2].V1 = 4;
model->facelist[2].V2 = 5;
model->facelist[2].V3 = 7;
model->facelist[3].V1 = 4;
model->facelist[3].V2 = 6;
model->facelist[3].V3 = 7;
model->facelist[4].V1 = 0;
model->facelist[4].V2 = 1;
model->facelist[4].V3 = 5;
model->facelist[5].V1 = 0;
model->facelist[5].V2 = 1;
model->facelist[5].V3 = 4;
model->facelist[6].V1 = 0;
model->facelist[6].V2 = 0;
model->facelist[6].V3 = 0;
model->facelist[7].V1 = 0;
model->facelist[7].V2 = 0;
model->facelist[7].V3 = 0;
model->facelist[8].V1 = 0;
model->facelist[8].V2 = 0;
model->facelist[8].V3 = 0;
model->facelist[9].V1 = 0;
model->facelist[9].V2 = 0;
model->facelist[9].V3 = 0;
model->facelist[10].V1 = 0;
model->facelist[10].V2 = 0;
model->facelist[10].V3 = 0;
model->facelist[11].V1 = 0;
model->facelist[11].V2 = 0;
model->facelist[11].V3 = 0;
}
/*******************************************************************************/
/* Affiche un modèle 3D */
void show3dmodel(model3d * model, matrix44 * transformation,
vector4 origin[], float factor, type3D type)
{
u16 i;
vertex2d *plane = 0x00250000;
for (i = 0; i < model->vertexnb; i++)
{
matrix44_transform(transformation, &model->vertexlist[i]);
}
proj(model->vertexlist, plane, origin, model->vertexnb, factor);
switch (type)
{
case TYPE3D_POINTS:
for (i = 0; i < model->vertexnb; i++)
{
v_writepxl(&plane[i], egatorgb(4));
}
break;
case TYPE3D_LINES:
for (i = 0; i < model->facenb; i++)
{
v_line(&plane[model->facelist[i].V1],
&plane[model->facelist[i].V2],
egatorgb(4));
v_line(&plane[model->facelist[i].V1],
&plane[model->facelist[i].V3],
egatorgb(4));
v_line(&plane[model->facelist[i].V2],
&plane[model->facelist[i].V3],
egatorgb(4));
}
break;
case TYPE3D_FACES:
break;
case TYPE3D_FLAT:
break;
case TYPE3D_TEXTURE:
break;
}
}
/*******************************************************************************/
/* Charge un fichier 3DS */
int load3ds(u8 * pointer, u32 size, model3d * model)
{
u8 *ptr = pointer;
u16 chunk_id;
u32 chunk_size;
u16 i;
float *listfloat;
u16 *listunsigned;
dsState state = DS_READ_CHUNK_ID;
bool dsfile = false;
while (ptr - pointer < size)
{
switch (state)
{
case DS_READ_CHUNK_ID:
chunk_id = *((u16 *) ptr);
ptr += 2;
state = DS_READ_CHUNK_LENGTH;
break;
case DS_READ_CHUNK_LENGTH:
chunk_size = *((u32 *) ptr);
ptr += 4;
switch (chunk_id)
{
case MAIN3DS:
dsfile = true;
ptr += 10;
state = DS_READ_CHUNK_ID;
break;
case EDIT3DS:
state = DS_READ_CHUNK_ID;
break;
case OBJ_TRIMESH:
state = DS_READ_CHUNK_ID;
break;
case EDIT_OBJECT:
state = DS_READ_OBJECT_NAME;
break;
case TRI_VERTEXL:
state = DS_READ_POINT_COUNT;
break;
case TRI_FACEL1:
state = DS_READ_FACE_COUNT;
break;
case TRI_LOCAL:
state = DS_READ_MATRIX;
break;
default:
if (!dsfile)
return 1;
ptr += (chunk_size - 6);
state = DS_READ_CHUNK_ID;
break;
}
break;
case DS_READ_OBJECT_NAME:
strcpy(ptr, model->name);
ptr += (strlen(ptr) + 1);
state = DS_READ_CHUNK_ID;
break;
case DS_SKIP_CHUNK:
break;
case DS_READ_POINT_COUNT:
model->vertexnb = *((u16 *) ptr);
state = DS_READ_POINTS;
ptr += 2;
break;
case DS_READ_POINTS:
i = 0;
listfloat = ptr;
model->vertexlist = 0x00300000;
while (i < model->vertexnb)
{
model->vertexlist[i].x =
*(listfloat++);
model->vertexlist[i].y =
*(listfloat++);
model->vertexlist[i].z =
*(listfloat++);
model->vertexlist[i++].w = 1.0;
}
ptr = listfloat;
state = DS_READ_CHUNK_ID;
break;
case DS_READ_FACE_COUNT:
model->facenb = *((u16 *) ptr);
state = DS_READ_FACES;
ptr += 2;
break;
case DS_READ_FACES:
i = 0;
listunsigned = ptr;
model->facelist = 0x00400000;
while (i < model->facenb)
{
model->facelist[i].V1 =
*(listunsigned++);
model->facelist[i].V2 =
*(listunsigned++);
model->facelist[i++].V3 =
*(listunsigned++);
listunsigned++;
}
ptr = listunsigned;
state = DS_READ_CHUNK_ID;
break;
case DS_READ_MATRIX:
i = 0;
listfloat = ptr;
while (i < 4)
{
model->view.V[i].x =
*(listfloat++);
model->view.V[i].y =
*(listfloat++);
model->view.V[i].z =
*(listfloat++);
model->view.V[i++].w = 0.0f;
}
model->view.V[3].w = 1.0f;
ptr = listfloat;
state = DS_READ_CHUNK_ID;
break;
case DS_READ_DONE:
break;
}
}
}