r716 - in trunk: . base/maps
lordhavoc at icculus.org
lordhavoc at icculus.org
Fri May 12 07:04:49 EDT 2006
Author: lordhavoc
Date: 2006-05-12 07:04:48 -0400 (Fri, 12 May 2006)
New Revision: 716
Modified:
trunk/base/maps/test.ent
trunk/model.c
trunk/model.h
trunk/nstring.c
trunk/nstring.h
trunk/util.c
Log:
reworked model system to use Import functions for loading each model
format and also Write now identifies file extension, this means that
util_convertobj has become util_convertmodel (able to convert any
supported format to any other supported format), and obj models now work
in the game without conversion.
Modified: trunk/base/maps/test.ent
===================================================================
--- trunk/base/maps/test.ent 2006-05-12 11:03:18 UTC (rev 715)
+++ trunk/base/maps/test.ent 2006-05-12 11:04:48 UTC (rev 716)
@@ -19,7 +19,7 @@
"classname" "vehicle_tank"
}
{
- "origin" "0 -23 8"
+ "origin" "0 -35 6"
"classname" "model"
"model" "models/players/generic/player_generic.md5mesh"
}
Modified: trunk/model.c
===================================================================
--- trunk/model.c 2006-05-12 11:03:18 UTC (rev 715)
+++ trunk/model.c 2006-05-12 11:04:48 UTC (rev 716)
@@ -188,11 +188,12 @@
Mem_Free(&hashtable);
}
-void Model_Build_Begin(Model *b, Mem_Zone *memzone, Nbool isskeletal)
+void Model_Build_Begin(Model *model, const char *filename, Mem_Zone *memzone, Nbool isskeletal)
{
- memset(b, 0, sizeof(*b));
- b->memzone = memzone;
- b->isskeletal = isskeletal;
+ memset(model, 0, sizeof(*model));
+ strncpy(model->filename, filename, sizeof(model->filename) - 1);
+ model->memzone = memzone;
+ model->isskeletal = isskeletal;
}
static void Model_Build_GenerateNeighbors(Model_Mesh *mesh)
@@ -227,69 +228,85 @@
// TODO: how do do this?
}
-void Model_Build_Compile(Model *b, Nbool generateneighbors, Nbool generateplanes, Nbool generatenormals, Nbool generatetangents, Nbool generatelightmaptexcoords, Nbool generatecollisionbrushes)
+void Model_Build_Compile(Model *model, Nbool generateneighbors, Nbool generateplanes, Nbool generatenormals, Nbool generatetangents, Nbool generatelightmaptexcoords, Nbool generatecollisionbrushes)
{
- NUint32 i, j;
+ NUint32 meshindex, vertexindex, weightindex, transformindex;
const float *v;
Model_Mesh *mesh;
Nbool initbox;
initbox = true;
- VectorClear(b->basecullmins);
- VectorClear(b->basecullmaxs);
- for (i = 0, mesh = b->data_meshes;i < b->num_meshes;i++, mesh++)
+ VectorClear(model->basecullmins);
+ VectorClear(model->basecullmaxs);
+ // clear the culling radius value in each transform as it will be regenerated
+ if (model->num_transforms)
+ for (transformindex = 0;transformindex < model->num_transforms;transformindex++)
+ model->data_transforminfo[transformindex].radius = 0;
+ // process each mesh
+ for (meshindex = 0, mesh = model->data_meshes;meshindex < model->num_meshes;meshindex++, mesh++)
{
+ // load the material
+ mesh->resource_material = Resource_IndexForName(mesh->materialname, RESOURCETYPE_MATERIAL, 0, 0);
+
+ // resize triangle arrays if there is some wasted space
if (mesh->max_triangles > mesh->num_triangles)
{
mesh->max_triangles = mesh->num_triangles;
- if (mesh->data_element3i) Mem_ReAlloc(b->memzone, &mesh->data_element3i, mesh->max_triangles * 3 * sizeof(*mesh->data_element3i));
- if (mesh->data_neighbor3i) Mem_ReAlloc(b->memzone, &mesh->data_neighbor3i, mesh->max_triangles * 3 * sizeof(*mesh->data_neighbor3i));
- if (mesh->data_plane4f) Mem_ReAlloc(b->memzone, &mesh->data_plane4f, mesh->max_triangles * 4 * sizeof(*mesh->data_plane4f));
+ if (mesh->data_element3i) Mem_ReAlloc(model->memzone, &mesh->data_element3i, mesh->max_triangles * 3 * sizeof(*mesh->data_element3i));
+ if (mesh->data_neighbor3i) Mem_ReAlloc(model->memzone, &mesh->data_neighbor3i, mesh->max_triangles * 3 * sizeof(*mesh->data_neighbor3i));
+ if (mesh->data_plane4f) Mem_ReAlloc(model->memzone, &mesh->data_plane4f, mesh->max_triangles * 4 * sizeof(*mesh->data_plane4f));
}
+ // resize vertex arrays if there is some wasted space
if (mesh->max_vertices > mesh->num_vertices)
{
mesh->max_vertices = mesh->num_vertices;
- if (mesh->data_vertex3f) Mem_ReAlloc(b->memzone, &mesh->data_vertex3f, mesh->max_vertices * 3 * sizeof(*mesh->data_vertex3f));
- if (mesh->data_svector3f) Mem_ReAlloc(b->memzone, &mesh->data_svector3f, mesh->max_vertices * 3 * sizeof(*mesh->data_svector3f));
- if (mesh->data_tvector3f) Mem_ReAlloc(b->memzone, &mesh->data_tvector3f, mesh->max_vertices * 3 * sizeof(*mesh->data_tvector3f));
- if (mesh->data_normal3f) Mem_ReAlloc(b->memzone, &mesh->data_normal3f, mesh->max_vertices * 3 * sizeof(*mesh->data_normal3f));
- if (mesh->data_texcoord2f) Mem_ReAlloc(b->memzone, &mesh->data_texcoord2f, mesh->max_vertices * 2 * sizeof(*mesh->data_texcoord2f));
- if (mesh->data_lightmaptexcoord2f) Mem_ReAlloc(b->memzone, &mesh->data_lightmaptexcoord2f, mesh->max_vertices * 2 * sizeof(*mesh->data_lightmaptexcoord2f));
- if (mesh->data_weightindex4b) Mem_ReAlloc(b->memzone, &mesh->data_weightindex4b, mesh->max_vertices * 4 * sizeof(*mesh->data_weightindex4b));
- if (mesh->data_weightvalue4b) Mem_ReAlloc(b->memzone, &mesh->data_weightvalue4b, mesh->max_vertices * 4 * sizeof(*mesh->data_weightvalue4b));
+ if (mesh->data_vertex3f) Mem_ReAlloc(model->memzone, &mesh->data_vertex3f, mesh->max_vertices * 3 * sizeof(*mesh->data_vertex3f));
+ if (mesh->data_svector3f) Mem_ReAlloc(model->memzone, &mesh->data_svector3f, mesh->max_vertices * 3 * sizeof(*mesh->data_svector3f));
+ if (mesh->data_tvector3f) Mem_ReAlloc(model->memzone, &mesh->data_tvector3f, mesh->max_vertices * 3 * sizeof(*mesh->data_tvector3f));
+ if (mesh->data_normal3f) Mem_ReAlloc(model->memzone, &mesh->data_normal3f, mesh->max_vertices * 3 * sizeof(*mesh->data_normal3f));
+ if (mesh->data_texcoord2f) Mem_ReAlloc(model->memzone, &mesh->data_texcoord2f, mesh->max_vertices * 2 * sizeof(*mesh->data_texcoord2f));
+ if (mesh->data_lightmaptexcoord2f) Mem_ReAlloc(model->memzone, &mesh->data_lightmaptexcoord2f, mesh->max_vertices * 2 * sizeof(*mesh->data_lightmaptexcoord2f));
+ if (mesh->data_weightindex4b) Mem_ReAlloc(model->memzone, &mesh->data_weightindex4b, mesh->max_vertices * 4 * sizeof(*mesh->data_weightindex4b));
+ if (mesh->data_weightvalue4b) Mem_ReAlloc(model->memzone, &mesh->data_weightvalue4b, mesh->max_vertices * 4 * sizeof(*mesh->data_weightvalue4b));
}
+ // generate triangle neighbors if requested
if (generateneighbors)
{
- if (!mesh->data_neighbor3i) Mem_ReAlloc(b->memzone, &mesh->data_neighbor3i, mesh->max_triangles * 3 * sizeof(*mesh->data_neighbor3i));
+ if (!mesh->data_neighbor3i) Mem_ReAlloc(model->memzone, &mesh->data_neighbor3i, mesh->max_triangles * 3 * sizeof(*mesh->data_neighbor3i));
Model_Build_GenerateNeighbors(mesh);
}
+ // generate triangle planes if requested
if (generateplanes)
{
- if (!mesh->data_plane4f) Mem_ReAlloc(b->memzone, &mesh->data_plane4f, mesh->max_triangles * 4 * sizeof(*mesh->data_plane4f));
+ if (!mesh->data_plane4f) Mem_ReAlloc(model->memzone, &mesh->data_plane4f, mesh->max_triangles * 4 * sizeof(*mesh->data_plane4f));
Model_Build_GeneratePlanes(mesh);
}
+ // generate vertex normals if requested
if (generatenormals)
{
- if (!mesh->data_normal3f) Mem_ReAlloc(b->memzone, &mesh->data_normal3f, mesh->max_vertices * 3 * sizeof(*mesh->data_normal3f));
+ if (!mesh->data_normal3f) Mem_ReAlloc(model->memzone, &mesh->data_normal3f, mesh->max_vertices * 3 * sizeof(*mesh->data_normal3f));
Model_Build_GenerateNormals(mesh);
}
+ // generate vertex tangent vectors if requested
if (generatetangents)
{
- if (!mesh->data_svector3f) Mem_ReAlloc(b->memzone, &mesh->data_svector3f, mesh->max_vertices * 3 * sizeof(*mesh->data_svector3f));
- if (!mesh->data_tvector3f) Mem_ReAlloc(b->memzone, &mesh->data_tvector3f, mesh->max_vertices * 3 * sizeof(*mesh->data_tvector3f));
+ if (!mesh->data_svector3f) Mem_ReAlloc(model->memzone, &mesh->data_svector3f, mesh->max_vertices * 3 * sizeof(*mesh->data_svector3f));
+ if (!mesh->data_tvector3f) Mem_ReAlloc(model->memzone, &mesh->data_tvector3f, mesh->max_vertices * 3 * sizeof(*mesh->data_tvector3f));
Model_Build_GenerateTangents(mesh);
}
+ // generate lightmap texcoords if requested
if (generatelightmaptexcoords)
{
- if (!mesh->data_lightmaptexcoord2f) Mem_ReAlloc(b->memzone, &mesh->data_lightmaptexcoord2f, mesh->max_vertices * 2 * sizeof(*mesh->data_lightmaptexcoord2f));
+ if (!mesh->data_lightmaptexcoord2f) Mem_ReAlloc(model->memzone, &mesh->data_lightmaptexcoord2f, mesh->max_vertices * 2 * sizeof(*mesh->data_lightmaptexcoord2f));
Model_Build_GenerateLightmapTexCoords(mesh);
}
+ // free old triangle collision brushes
if (mesh->data_collisionbrushes)
{
Collision_Brush_FreeBrushesForTriangleMesh(mesh->data_collisionbrushes, mesh->max_collisionbrushes);
@@ -297,40 +314,63 @@
mesh->max_collisionbrushes = 0;
mesh->data_collisionbrushes = NULL;
}
+ // generate triangle collision brushes if requested
if (generatecollisionbrushes)
{
mesh->num_collisionbrushes = mesh->num_triangles;
mesh->max_collisionbrushes = mesh->num_collisionbrushes;
- mesh->data_collisionbrushes = Collision_Brush_AllocBrushesForTriangleMesh(b->memzone, mesh->max_collisionbrushes);
+ mesh->data_collisionbrushes = Collision_Brush_AllocBrushesForTriangleMesh(model->memzone, mesh->max_collisionbrushes);
Collision_Brush_UpdateTriangleMeshBrushes(mesh->data_collisionbrushes, mesh->max_collisionbrushes, mesh->data_element3i, mesh->data_vertex3f);
}
- for (j = 0, v = mesh->data_vertex3f;j < mesh->num_vertices;j++, v += 3)
+ // compute culling box for this mesh and update model box
+ // also compute culling spheres for transforms
+ VectorCopy(mesh->data_vertex3f, mesh->basecullmins);
+ VectorCopy(mesh->data_vertex3f, mesh->basecullmaxs);
+ for (vertexindex = 0, v = mesh->data_vertex3f;vertexindex < mesh->num_vertices;vertexindex++, v += 3)
{
- if (initbox)
+ mesh->basecullmins[0] = Min(mesh->basecullmins[0], v[0]);
+ mesh->basecullmins[1] = Min(mesh->basecullmins[1], v[1]);
+ mesh->basecullmins[2] = Min(mesh->basecullmins[2], v[2]);
+ mesh->basecullmaxs[0] = Max(mesh->basecullmaxs[0], v[0]);
+ mesh->basecullmaxs[1] = Max(mesh->basecullmaxs[1], v[1]);
+ mesh->basecullmaxs[2] = Max(mesh->basecullmaxs[2], v[2]);
+ if (mesh->data_weightindex4b)
{
- initbox = false;
- VectorCopy(v, b->basecullmins);
- VectorCopy(v, b->basecullmaxs);
+ for (weightindex = 0;weightindex < 4 && mesh->data_weightvalue4b[vertexindex*4+weightindex] > 0;weightindex++)
+ {
+ NUint32 index = mesh->data_weightindex4b[vertexindex*4+weightindex];
+ Nvec3 v1, v;
+ Nvec r;
+ VectorCopy(mesh->data_vertex3f + vertexindex * 3, v1);
+ Matrix4x4_Transform(&model->data_transforminfo[index].baseinversematrix, v1, v);
+ r = VectorLength(v);
+ model->data_transforminfo[index].radius = Max(model->data_transforminfo[index].radius, r);
+ }
}
- else
- {
- b->basecullmins[0] = Min(b->basecullmins[0], v[0]);
- b->basecullmins[1] = Min(b->basecullmins[1], v[1]);
- b->basecullmins[2] = Min(b->basecullmins[2], v[2]);
- b->basecullmaxs[0] = Max(b->basecullmaxs[0], v[0]);
- b->basecullmaxs[1] = Max(b->basecullmaxs[1], v[1]);
- b->basecullmaxs[2] = Max(b->basecullmaxs[2], v[2]);
- }
}
+ if (!meshindex)
+ {
+ VectorCopy(mesh->basecullmins, model->basecullmins);
+ VectorCopy(mesh->basecullmaxs, model->basecullmaxs);
+ }
+ else
+ {
+ model->basecullmins[0] = Min(model->basecullmins[0], mesh->basecullmins[0]);
+ model->basecullmins[1] = Min(model->basecullmins[1], mesh->basecullmins[1]);
+ model->basecullmins[2] = Min(model->basecullmins[2], mesh->basecullmins[2]);
+ model->basecullmaxs[0] = Max(model->basecullmaxs[0], mesh->basecullmaxs[0]);
+ model->basecullmaxs[1] = Max(model->basecullmaxs[1], mesh->basecullmaxs[1]);
+ model->basecullmaxs[2] = Max(model->basecullmaxs[2], mesh->basecullmaxs[2]);
+ }
}
}
-void Model_Build_Free(Model *b)
+void Model_Build_Free(Model *model)
{
NUint32 i;
Model_Mesh *mesh;
- for (i = 0, mesh = b->data_meshes;i < b->num_meshes;i++, mesh++)
+ for (i = 0, mesh = model->data_meshes;i < model->num_meshes;i++, mesh++)
{
if (mesh->materialname) String_Free(&mesh->materialname);
if (mesh->data_element3i) Mem_Free(&mesh->data_element3i);
@@ -346,41 +386,41 @@
if (mesh->data_weightvalue4b) Mem_Free(&mesh->data_weightvalue4b);
if (mesh->data_collisionbrushes) Collision_Brush_FreeBrushesForTriangleMesh(mesh->data_collisionbrushes, mesh->max_collisionbrushes);
}
- if (b->data_meshes)
- Mem_Free(&b->data_meshes);
- memset(b, 0, sizeof(*b));
+ if (model->data_meshes)
+ Mem_Free(&model->data_meshes);
+ memset(model, 0, sizeof(*model));
}
-NUint32 Model_Build_AddSurface(Model *b, Mem_Zone *zone, const char *materialname, NUint32 initialtriangles, NUint32 initialvertices)
+NUint32 Model_Build_AddSurface(Model *model, const char *materialname, NUint32 initialtriangles, NUint32 initialvertices)
{
Model_Mesh *mesh;
- if (b->num_meshes >= b->max_meshes)
+ if (model->num_meshes >= model->max_meshes)
{
- b->max_meshes = Max(b->max_meshes * 2, 16);
- Mem_ReAlloc(Global_Zone, &b->data_meshes, b->max_meshes * sizeof(*b->data_meshes));
+ model->max_meshes = Max(model->max_meshes * 2, 16);
+ Mem_ReAlloc(model->memzone, &model->data_meshes, model->max_meshes * sizeof(*model->data_meshes));
}
- mesh = b->data_meshes + b->num_meshes;
- String_Set(&mesh->materialname, zone, materialname);
+ mesh = model->data_meshes + model->num_meshes;
+ String_Set(&mesh->materialname, model->memzone, materialname);
mesh->max_triangles = initialtriangles;
mesh->max_vertices = initialvertices;
- b->num_meshes++;
- return b->num_meshes - 1;
+ model->num_meshes++;
+ return model->num_meshes - 1;
}
-NUint32 Model_Build_AddVertex(Model *b, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t)
+NUint32 Model_Build_AddVertex(Model *model, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t)
{
float *v;
- Model_Mesh *mesh = b->data_meshes + meshindex;
+ Model_Mesh *mesh = model->data_meshes + meshindex;
if (mesh->num_vertices >= mesh->max_vertices)
{
mesh->max_vertices = Max(mesh->max_vertices * 2, 1024);
- Mem_ReAlloc(b->memzone, &mesh->data_vertex3f, mesh->max_vertices * 3 * sizeof(*mesh->data_vertex3f));
- Mem_ReAlloc(b->memzone, &mesh->data_normal3f, mesh->max_vertices * 3 * sizeof(*mesh->data_normal3f));
- Mem_ReAlloc(b->memzone, &mesh->data_texcoord2f, mesh->max_vertices * 2 * sizeof(*mesh->data_texcoord2f));
- if (b->isskeletal)
+ Mem_ReAlloc(model->memzone, &mesh->data_vertex3f, mesh->max_vertices * 3 * sizeof(*mesh->data_vertex3f));
+ Mem_ReAlloc(model->memzone, &mesh->data_normal3f, mesh->max_vertices * 3 * sizeof(*mesh->data_normal3f));
+ Mem_ReAlloc(model->memzone, &mesh->data_texcoord2f, mesh->max_vertices * 2 * sizeof(*mesh->data_texcoord2f));
+ if (model->isskeletal)
{
- Mem_ReAlloc(b->memzone, &mesh->data_weightindex4b, mesh->max_vertices * 4 * sizeof(*mesh->data_weightindex4b));
- Mem_ReAlloc(b->memzone, &mesh->data_weightvalue4b, mesh->max_vertices * 4 * sizeof(*mesh->data_weightvalue4b));
+ Mem_ReAlloc(model->memzone, &mesh->data_weightindex4b, mesh->max_vertices * 4 * sizeof(*mesh->data_weightindex4b));
+ Mem_ReAlloc(model->memzone, &mesh->data_weightvalue4b, mesh->max_vertices * 4 * sizeof(*mesh->data_weightvalue4b));
}
}
v = mesh->data_vertex3f + mesh->num_vertices * 3;
@@ -394,7 +434,7 @@
v = mesh->data_texcoord2f + mesh->num_vertices * 2;
v[0] = s;
v[1] = t;
- if (b->isskeletal)
+ if (model->isskeletal)
{
NUint8 *wi = mesh->data_weightindex4b + mesh->num_vertices * 4;
NUint8 *wf = mesh->data_weightvalue4b + mesh->num_vertices * 4;
@@ -411,20 +451,20 @@
return mesh->num_vertices - 1;
}
-NUint32 Model_Build_AddVertexSkeletal(Model *b, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t, NUint8 *wib, NUint8 *wfb)
+NUint32 Model_Build_AddVertexSkeletal(Model *model, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t, NUint8 *wib, NUint8 *wfb)
{
float *v;
- Model_Mesh *mesh = b->data_meshes + meshindex;
+ Model_Mesh *mesh = model->data_meshes + meshindex;
if (mesh->num_vertices >= mesh->max_vertices)
{
mesh->max_vertices = Max(mesh->max_vertices * 2, 1024);
- Mem_ReAlloc(b->memzone, &mesh->data_vertex3f, mesh->max_vertices * 3 * sizeof(*mesh->data_vertex3f));
- Mem_ReAlloc(b->memzone, &mesh->data_normal3f, mesh->max_vertices * 3 * sizeof(*mesh->data_normal3f));
- Mem_ReAlloc(b->memzone, &mesh->data_texcoord2f, mesh->max_vertices * 2 * sizeof(*mesh->data_texcoord2f));
- if (b->isskeletal)
+ Mem_ReAlloc(model->memzone, &mesh->data_vertex3f, mesh->max_vertices * 3 * sizeof(*mesh->data_vertex3f));
+ Mem_ReAlloc(model->memzone, &mesh->data_normal3f, mesh->max_vertices * 3 * sizeof(*mesh->data_normal3f));
+ Mem_ReAlloc(model->memzone, &mesh->data_texcoord2f, mesh->max_vertices * 2 * sizeof(*mesh->data_texcoord2f));
+ if (model->isskeletal)
{
- Mem_ReAlloc(b->memzone, &mesh->data_weightindex4b, mesh->max_vertices * 4 * sizeof(*mesh->data_weightindex4b));
- Mem_ReAlloc(b->memzone, &mesh->data_weightvalue4b, mesh->max_vertices * 4 * sizeof(*mesh->data_weightvalue4b));
+ Mem_ReAlloc(model->memzone, &mesh->data_weightindex4b, mesh->max_vertices * 4 * sizeof(*mesh->data_weightindex4b));
+ Mem_ReAlloc(model->memzone, &mesh->data_weightvalue4b, mesh->max_vertices * 4 * sizeof(*mesh->data_weightvalue4b));
}
}
v = mesh->data_vertex3f + mesh->num_vertices * 3;
@@ -438,7 +478,7 @@
v = mesh->data_texcoord2f + mesh->num_vertices * 2;
v[0] = s;
v[1] = t;
- if (b->isskeletal)
+ if (model->isskeletal)
{
NUint8 *wi = mesh->data_weightindex4b + mesh->num_vertices * 4;
NUint8 *wf = mesh->data_weightvalue4b + mesh->num_vertices * 4;
@@ -449,26 +489,26 @@
return mesh->num_vertices - 1;
}
-NUint32 Model_Build_FindOrAddVertex(Model *b, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t)
+NUint32 Model_Build_FindOrAddVertex(Model *model, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t)
{
NUint32 i;
float *v, *n, *tc;
NUint8 *wi, *wf;
- Model_Mesh *mesh = b->data_meshes + meshindex;
+ Model_Mesh *mesh = model->data_meshes + meshindex;
for (i = 0, v = mesh->data_vertex3f, n = mesh->data_normal3f, tc = mesh->data_texcoord2f, wi = mesh->data_weightindex4b, wf = mesh->data_weightvalue4b;i < mesh->num_vertices;i++, v += 3, n += 3, tc += 2, wi += 4, wf += 4)
if (fabs(v[0] - x) < 0.0001 && fabs(v[1] - y) < 0.0001 && fabs(v[2] - z) < 0.0001
&& fabs(n[0] - nx) < 0.0001 && fabs(n[1] - ny) < 0.0001 && fabs(n[2] - nz) < 0.0001
&& fabs(tc[0] - s) < 0.0001 && fabs(tc[1] - t) < 0.0001)
return i;
- return Model_Build_AddVertex(b, meshindex, x, y, z, nx, ny, nz, s, t);
+ return Model_Build_AddVertex(model, meshindex, x, y, z, nx, ny, nz, s, t);
}
-NUint32 Model_Build_FindOrAddVertexSkeletal(Model *b, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t, NUint8 *wib, NUint8 *wfb)
+NUint32 Model_Build_FindOrAddVertexSkeletal(Model *model, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t, NUint8 *wib, NUint8 *wfb)
{
NUint32 i;
float *v, *n, *tc;
NUint8 *wi, *wf;
- Model_Mesh *mesh = b->data_meshes + meshindex;
+ Model_Mesh *mesh = model->data_meshes + meshindex;
for (i = 0, v = mesh->data_vertex3f, n = mesh->data_normal3f, tc = mesh->data_texcoord2f, wi = mesh->data_weightindex4b, wf = mesh->data_weightvalue4b;i < mesh->num_vertices;i++, v += 3, n += 3, tc += 2, wi += 4, wf += 4)
if (fabs(v[0] - x) < 0.0001 && fabs(v[1] - y) < 0.0001 && fabs(v[2] - z) < 0.0001
&& fabs(n[0] - nx) < 0.0001 && fabs(n[1] - ny) < 0.0001 && fabs(n[2] - nz) < 0.0001
@@ -476,17 +516,17 @@
&& wi[0] == wib[0] && wi[1] == wib[1] && wi[2] == wib[2] && wi[3] == wib[3]
&& wf[0] == wfb[0] && wf[1] == wfb[1] && wf[2] == wfb[2] && wf[3] == wfb[3])
return i;
- return Model_Build_AddVertexSkeletal(b, meshindex, x, y, z, nx, ny, nz, s, t, wib, wfb);
+ return Model_Build_AddVertexSkeletal(model, meshindex, x, y, z, nx, ny, nz, s, t, wib, wfb);
}
-NUint32 Model_Build_AddTriangle(Model *b, NUint32 meshindex, int e0, int e1, int e2)
+NUint32 Model_Build_AddTriangle(Model *model, NUint32 meshindex, int e0, int e1, int e2)
{
- Model_Mesh *mesh = b->data_meshes + meshindex;
+ Model_Mesh *mesh = model->data_meshes + meshindex;
NUint32 *e;
if (mesh->num_triangles >= mesh->max_triangles)
{
mesh->max_triangles = Max(mesh->max_triangles * 2, 1024);
- Mem_ReAlloc(b->memzone, &mesh->data_element3i, mesh->max_triangles * 3 * sizeof(*mesh->data_element3i));
+ Mem_ReAlloc(model->memzone, &mesh->data_element3i, mesh->max_triangles * 3 * sizeof(*mesh->data_element3i));
}
e = mesh->data_element3i + mesh->num_triangles * 3;
e[0] = e0;
@@ -496,7 +536,7 @@
return mesh->num_triangles - 1;
}
-void Model_Build_Write(Model *b, const char *filename)
+static void Model_Build_WriteMD5(Model *model, const char *filename)
{
// FIXME: this is very unlikely to overflow but it should be made buffer size safe at some point
NUint32 i, num;
@@ -504,12 +544,12 @@
char *text;
Model_Mesh *mesh;
textmaxsize = 0x100000;
- for (i = 0, mesh = b->data_meshes;i < b->num_meshes;i++, mesh++)
+ for (i = 0, mesh = model->data_meshes;i < model->num_meshes;i++, mesh++)
textmaxsize += mesh->num_vertices * 60 + mesh->num_triangles * 40;
textsize = 0;
text = Mem_Alloc(Global_Zone, textmaxsize);
- textsize += snprintf(text + textsize, textmaxsize - textsize, "MD5Version 10\ncommandline \"\"\n\nnumJoints 1\nnumMeshes %u\n\njoints {\n\t\"ROOT\"\t-1 ( 0.000000 0.000000 0.000000 ) ( 0.000000 0.000000 0.000000 ) // \n}\n", b->num_meshes);
- for (i = 0, mesh = b->data_meshes;i < b->num_meshes;i++, mesh++)
+ textsize += snprintf(text + textsize, textmaxsize - textsize, "MD5Version 10\ncommandline \"\"\n\nnumJoints 1\nnumMeshes %u\n\njoints {\n\t\"ROOT\"\t-1 ( 0.000000 0.000000 0.000000 ) ( 0.000000 0.000000 0.000000 ) // \n}\n", model->num_meshes);
+ for (i = 0, mesh = model->data_meshes;i < model->num_meshes;i++, mesh++)
{
if (textmaxsize < textsize + mesh->num_vertices * 100 + mesh->num_triangles * 100 + mesh->num_vertices * 100 + 1000)
{
@@ -531,8 +571,16 @@
Mem_Free(&text);
}
-void Model_Build_ImportOBJ(Model *b, const char *inputname, const char *text, const char *textend)
+void Model_Build_Write(Model *model, const char *filename)
{
+ if (String_EndsWith(filename, ".md5mesh"))
+ Model_Build_WriteMD5(model, filename);
+ else
+ Console_Printf("Model_Build_Write: %s extension not recognized\n", filename);
+}
+
+static Nbool Model_Build_Import_OBJ(Model *model, Nsize filesize, const char *filedata)
+{
NUint32 linenumber = 0;
NSint32 meshindex = -1;
NUint32 num_vertices = 0, max_vertices = 0;
@@ -541,6 +589,8 @@
float *data_vertex3f = NULL;
float *data_normal3f = NULL;
float *data_texcoord2f = NULL;
+ const char *text = filedata;
+ const char *textend = filedata + filesize;
while (text < textend)
{
Nbool comment = false;
@@ -586,7 +636,7 @@
num_vertices++;
}
else
- Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 3);
+ Console_Printf("Model_Build_Import_OBJ: %s:%i: command %s takes %i parameters\n", model->filename, linenumber, argv[0], 3);
}
else if (!String_Compare(argv[0], "vn"))
{
@@ -604,7 +654,7 @@
num_normals++;
}
else
- Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 3);
+ Console_Printf("Model_Build_Import_OBJ: %s:%i: command %s takes %i parameters\n", model->filename, linenumber, argv[0], 3);
}
else if (!String_Compare(argv[0], "vt"))
{
@@ -621,15 +671,15 @@
num_texcoords++;
}
else
- Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 2);
+ Console_Printf("Model_Build_Import_OBJ: %s:%i: command %s takes %i parameters\n", model->filename, linenumber, argv[0], 2);
}
else if (!String_Compare(argv[0], "usemtl"))
{
// usemtl mtrl/chrome
if (argc == 2)
- meshindex = Model_Build_AddSurface(b, Global_Zone, argv[1], 0, 0);
+ meshindex = Model_Build_AddSurface(model, argv[1], 0, 0);
else
- Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 1);
+ Console_Printf("Model_Build_Import_OBJ: %s:%i: command %s takes %i parameters\n", model->filename, linenumber, argv[0], 1);
}
else if (!String_Compare(argv[0], "f"))
{
@@ -639,7 +689,7 @@
if (argc >= 4)
{
if (meshindex == -1)
- meshindex = Model_Build_AddSurface(b, Global_Zone, "default", 0, 0);
+ meshindex = Model_Build_AddSurface(model, "default", 0, 0);
for (i = 0;i < argc - 1;i++)
{
NUint32 j;
@@ -670,7 +720,7 @@
if (k >= 0 && k < num_vertices)
VectorCopy(data_vertex3f + k * 3, v);
else
- Console_Printf("Model_Build_ImportOBJ: %s:%i: invalid face vertex index (parameter #%i)\n", inputname, linenumber, i + 1);
+ Console_Printf("Model_Build_Import_OBJ: %s:%i: invalid face vertex index (parameter #%i)\n", model->filename, linenumber, i + 1);
break;
case 1:
if (k < 0)
@@ -680,7 +730,7 @@
if (k >= 0 && k < num_texcoords)
Vector2Copy(data_texcoord2f + k * 2, tc);
else
- Console_Printf("Model_Build_ImportOBJ: %s:%i: invalid face texcoord index (parameter #%i)\n", inputname, linenumber, i + 1);
+ Console_Printf("Model_Build_Import_OBJ: %s:%i: invalid face texcoord index (parameter #%i)\n", model->filename, linenumber, i + 1);
break;
case 2:
if (k < 0)
@@ -690,7 +740,7 @@
if (k >= 0 && k < num_normals)
VectorCopy(data_normal3f + k * 3, vn);
else
- Console_Printf("Model_Build_ImportOBJ: %s:%i: invalid face vertexnormal index (parameter #%i)\n", inputname, linenumber, i + 1);
+ Console_Printf("Model_Build_Import_OBJ: %s:%i: invalid face vertexnormal index (parameter #%i)\n", model->filename, linenumber, i + 1);
break;
}
}
@@ -707,35 +757,35 @@
s++;
}
}
- indices[i] = Model_Build_FindOrAddVertex(b, meshindex, v[0], v[1], v[2], vn[0], vn[1], vn[2], tc[0], tc[1]);
+ indices[i] = Model_Build_FindOrAddVertex(model, meshindex, v[0], v[1], v[2], vn[0], vn[1], vn[2], tc[0], tc[1]);
// make a triangle fan if we have enough vertices
if (i >= 2)
- Model_Build_AddTriangle(b, meshindex, indices[0], indices[i-1], indices[i]);
+ Model_Build_AddTriangle(model, meshindex, indices[0], indices[i], indices[i-1]);
}
}
else
- Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i or more parameters\n", inputname, linenumber, argv[0], 3);
+ Console_Printf("Model_Build_Import_OBJ: %s:%i: command %s takes %i or more parameters\n", model->filename, linenumber, argv[0], 3);
}
else if (!String_Compare(argv[0], "o"))
{
// o cylinder1
if (argc != 2)
- Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 1);
+ Console_Printf("Model_Build_Import_OBJ: %s:%i: command %s takes %i parameters\n", model->filename, linenumber, argv[0], 1);
}
else if (!String_Compare(argv[0], "mtllib"))
{
// mtllib zrail2.mtl
if (argc != 2)
- Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 1);
+ Console_Printf("Model_Build_Import_OBJ: %s:%i: command %s takes %i parameters\n", model->filename, linenumber, argv[0], 1);
}
else if (!String_Compare(argv[0], "g"))
{
// g cylinder1_mtrl/invisible
if (argc != 2)
- Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 1);
+ Console_Printf("Model_Build_Import_OBJ: %s:%i: command %s takes %i parameters\n", model->filename, linenumber, argv[0], 1);
}
else
- Console_Printf("Model_Build_ImportOBJ: %s:%i: unknown obj command %s\n", inputname, linenumber, argv[0]);
+ Console_Printf("Model_Build_Import_OBJ: %s:%i: unknown obj command %s\n", model->filename, linenumber, argv[0]);
}
if (data_vertex3f)
Mem_Free(&data_vertex3f);
@@ -743,6 +793,7 @@
Mem_Free(&data_normal3f);
if (data_texcoord2f)
Mem_Free(&data_texcoord2f);
+ return false;
}
/* example clips of an MD5 model
@@ -782,50 +833,41 @@
}
Model_MD5_Weight;
-void Model_Load(ResourceEntry *r)
+static Nbool Model_Build_Import_MD5(Model *model, Nsize filesize, const char *filedata)
{
Util_ParseC_Thread thread;
NUint32 meshnum, version, numjoints = 0;
Nbool error;
- Nsize filesize;
- Model *model;
- char *filedata;
Nbool isskeletal = false;
- model = Mem_Alloc(r->memzone, sizeof(Model));
-
- filedata = File_LoadFile(r->name, &filesize);
- if (!filedata)
- return;
-
Util_ParseC_SetUpThread(&thread, filedata, filesize);
#define Abort() { error = true; break; }
#define LoadValue(var, errstr) if (thread.type != UTIL_PARSEC_TOKENTYPE_VALUE) { \
- Console_Printf("Model_Load: Expected value " errstr "\n"); Abort(); \
+ Console_Printf("Model_Build_Import_MD5: Expected value " errstr "\n"); Abort(); \
} else \
(var) = thread.value, Util_ParseC_Lex(&thread)
#define LoadInt(var, errstr) if (thread.type != UTIL_PARSEC_TOKENTYPE_VALUE) { \
- Console_Printf("Model_Load: Expected integer " errstr "\n"); Abort(); \
+ Console_Printf("Model_Build_Import_MD5: Expected integer " errstr "\n"); Abort(); \
} else \
(var) = thread.value, Util_ParseC_Lex(&thread)
#define LoadString(var, errstr) if (thread.type != UTIL_PARSEC_TOKENTYPE_STRING) { \
- Console_Printf("Model_Load: Expected string " errstr "\n"); Abort(); \
+ Console_Printf("Model_Build_Import_MD5: Expected string " errstr "\n"); Abort(); \
} else \
- String_Set( &(var), r->memzone, thread.token), Util_ParseC_Lex(&thread)
+ String_Set( &(var), model->memzone, thread.token), Util_ParseC_Lex(&thread)
#define ExpectKeyword(str, errstr) if (!Util_ParseC_MatchName(&thread, (str))) { \
- Console_Printf("Model_Load: Expected '" str "' " errstr "\n"); Abort(); }
+ Console_Printf("Model_Build_Import_MD5: Expected '" str "' " errstr "\n"); Abort(); }
version = 0;
meshnum = 0;
error = false;
- VectorClear(model->basecullmins);
- VectorClear(model->basecullmaxs);
-
+ // FIXME: this code should probably use more of the Model_Build_ functions
+ // where possible, to allow importing additional geometry into an existing
+ // model structure
while (!error && thread.type != UTIL_PARSEC_TOKENTYPE_EOF)
{
//MD5Version 10
@@ -834,7 +876,7 @@
LoadInt(version, "after 'MD5Version'");
if (version != 10)
{
- Console_Printf("Model_Load: MD5Version %i not supported\n", version);
+ Console_Printf("Model_Build_Import_MD5: MD5Version %i not supported\n", version);
Abort();
}
}
@@ -849,7 +891,7 @@
LoadInt(numjoints, "after 'numJoints'");
if (numjoints < 1)
{
- Console_Printf("Model_Load: numJoints %i < 1\n", numjoints);
+ Console_Printf("Model_Build_Import_MD5: numJoints %i < 1\n", numjoints);
Abort();
}
if (numjoints > 1)
@@ -857,7 +899,7 @@
isskeletal = true;
model->num_transforms = numjoints;
model->max_transforms = model->num_transforms;
- model->data_transforminfo = Mem_Alloc(r->memzone, model->max_transforms * sizeof(*model->data_transforminfo));
+ model->data_transforminfo = Mem_Alloc(model->memzone, model->max_transforms * sizeof(*model->data_transforminfo));
}
}
//numMeshes 1
@@ -866,11 +908,11 @@
LoadInt(model->num_meshes, "after 'numMeshes'");
if (model->num_meshes < 1)
{
- Console_Printf("Model_Load: numMeshes %i < 1\n", model->num_meshes);
+ Console_Printf("Model_Build_Import_MD5: numMeshes %i < 1\n", model->num_meshes);
Abort();
}
model->max_meshes = model->num_meshes;
- model->data_meshes = Mem_Alloc(r->memzone, model->max_meshes * sizeof(Model_Mesh));
+ model->data_meshes = Mem_Alloc(model->memzone, model->max_meshes * sizeof(Model_Mesh));
}
//joints {
// "root" -1 ( 0.000000 0.000000 0.000000 ) ( -0.707107 -0.000000 -0.000000 ) //
@@ -902,7 +944,7 @@
if (parent >= (NSint32)jointnum)
{
String_Free(&name);
- Console_Printf("Model_Load: joint.parent (%i) >= joint (%i)\n", parent, jointnum);
+ Console_Printf("Model_Build_Import_MD5: joint.parent (%i) >= joint (%i)\n", parent, jointnum);
Abort();
}
if (isskeletal)
@@ -916,7 +958,7 @@
String_Free(&name);
if (jointnum != numjoints)
{
- Console_Printf("Model_Load: final jointnum (%i) != numJoints (%i)\n", jointnum, numjoints);
+ Console_Printf("Model_Build_Import_MD5: final jointnum (%i) != numJoints (%i)\n", jointnum, numjoints);
Abort();
}
}
@@ -933,7 +975,7 @@
ExpectKeyword("{", "after 'mesh'");
if (meshnum >= model->num_meshes)
{
- Console_Printf("Model_Load: meshnum (%i) >= nummeshes (%i)\n", meshnum, model->num_meshes);
+ Console_Printf("Model_Build_Import_MD5: meshnum (%i) >= nummeshes (%i)\n", meshnum, model->num_meshes);
Abort();
}
mesh = model->data_meshes + meshnum;
@@ -952,22 +994,22 @@
LoadInt(mesh->num_vertices, "after 'numverts'");
if (mesh->num_vertices < 3)
{
- Console_Printf("Model_Load: numverts (%i) < 3\n", mesh->num_vertices);
+ Console_Printf("Model_Build_Import_MD5: numverts (%i) < 3\n", mesh->num_vertices);
Abort();
}
mesh->max_vertices = mesh->num_vertices;
- mesh->data_vertex3f = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(float[3]));
- mesh->data_svector3f = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(float[3]));
- mesh->data_tvector3f = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(float[3]));
- mesh->data_normal3f = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(float[3]));
- mesh->data_texcoord2f = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(float[2]));
- mesh->data_lightmaptexcoord2f = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(float[2]));
+ mesh->data_vertex3f = Mem_Alloc(model->memzone, mesh->max_vertices * sizeof(float[3]));
+ mesh->data_svector3f = Mem_Alloc(model->memzone, mesh->max_vertices * sizeof(float[3]));
+ mesh->data_tvector3f = Mem_Alloc(model->memzone, mesh->max_vertices * sizeof(float[3]));
+ mesh->data_normal3f = Mem_Alloc(model->memzone, mesh->max_vertices * sizeof(float[3]));
+ mesh->data_texcoord2f = Mem_Alloc(model->memzone, mesh->max_vertices * sizeof(float[2]));
+ mesh->data_lightmaptexcoord2f = Mem_Alloc(model->memzone, mesh->max_vertices * sizeof(float[2]));
if (isskeletal)
{
- mesh->data_weightindex4b = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(NUint8[4]));
- mesh->data_weightvalue4b = Mem_Alloc(r->memzone, mesh->max_vertices * sizeof(NUint8[4]));
+ mesh->data_weightindex4b = Mem_Alloc(model->memzone, mesh->max_vertices * sizeof(NUint8[4]));
+ mesh->data_weightvalue4b = Mem_Alloc(model->memzone, mesh->max_vertices * sizeof(NUint8[4]));
}
- md5weightrange = Mem_Alloc(Global_Zone, mesh->max_vertices * sizeof(NUint32[2]));
+ md5weightrange = Mem_Alloc(model->memzone, mesh->max_vertices * sizeof(NUint32[2]));
}
// vert 0 ( 0.142532 0.983877 ) 0 1
// vert 1 ( 0.155314 0.987100 ) 1 1
@@ -979,7 +1021,7 @@
LoadInt(vertexnum, "after 'vert'");
if (vertexnum >= mesh->num_vertices)
{
- Console_Printf("Model_Load: vert (%i) >= numverts (%i)\n", vertexnum, mesh->num_vertices);
+ Console_Printf("Model_Build_Import_MD5: vert (%i) >= numverts (%i)\n", vertexnum, mesh->num_vertices);
Abort();
}
// (
@@ -1002,13 +1044,13 @@
LoadInt(mesh->num_triangles, "after 'numtris'");
if (mesh->num_triangles < 1)
{
- Console_Printf("Model_Load: numtris (%i) < 1\n", mesh->num_triangles);
+ Console_Printf("Model_Build_Import_MD5: numtris (%i) < 1\n", mesh->num_triangles);
Abort();
}
mesh->max_triangles = mesh->num_triangles;
- mesh->data_element3i = Mem_Alloc(r->memzone, mesh->max_triangles * sizeof(NUint32[3]));
- mesh->data_neighbor3i = Mem_Alloc(r->memzone, mesh->max_triangles * sizeof(NSint32[3]));
- mesh->data_plane4f = Mem_Alloc(r->memzone, mesh->max_triangles * sizeof(float[4]));
+ mesh->data_element3i = Mem_Alloc(model->memzone, mesh->max_triangles * sizeof(NUint32[3]));
+ mesh->data_neighbor3i = Mem_Alloc(model->memzone, mesh->max_triangles * sizeof(NSint32[3]));
+ mesh->data_plane4f = Mem_Alloc(model->memzone, mesh->max_triangles * sizeof(float[4]));
}
// tri 0 29 30 31
// tri 1 32 29 76
@@ -1019,7 +1061,7 @@
LoadInt(trianglenum, "after 'tri'");
if (trianglenum >= mesh->num_triangles)
{
- Console_Printf("Model_Load: tri (%i) >= numtris (%i)\n", trianglenum, mesh->num_triangles);
+ Console_Printf("Model_Build_Import_MD5: tri (%i) >= numtris (%i)\n", trianglenum, mesh->num_triangles);
Abort();
}
// TODO: boundscheck elements
@@ -1035,7 +1077,7 @@
LoadInt(md5numweights, "after 'numweights'");
if (md5numweights < 1)
{
- Console_Printf("Model_Load: numweights (%i) < 1\n", md5numweights);
+ Console_Printf("Model_Build_Import_MD5: numweights (%i) < 1\n", md5numweights);
Abort();
}
md5weights = Mem_Alloc(Global_Zone, md5numweights * sizeof(Model_MD5_Weight));
@@ -1051,7 +1093,7 @@
LoadInt(weightnum, "after 'weight'");
if (weightnum >= md5numweights)
{
- Console_Printf("Model_Load: weight (%i) >= numweights (%i)\n", weightnum, md5numweights);
+ Console_Printf("Model_Build_Import_MD5: weight (%i) >= numweights (%i)\n", weightnum, md5numweights);
Abort();
}
md5weight = md5weights + weightnum;
@@ -1059,7 +1101,7 @@
LoadInt(md5weight->jointnum, "(weight jointnum)");
if (md5weight->jointnum >= numjoints)
{
- Console_Printf("Model_Load: joint (%i) >= numjoints (%i)\n", md5weight->jointnum, numjoints);
+ Console_Printf("Model_Build_Import_MD5: joint (%i) >= numjoints (%i)\n", md5weight->jointnum, numjoints);
Abort();
}
// 1.000000
@@ -1147,63 +1189,6 @@
for (i = 0;i < mesh->num_vertices;i++)
VectorCopy(md5weights[md5weightrange[i*2+0]].vertex, mesh->data_vertex3f + i*3);
}
- // compile the base frame of the mesh for static uses
- Model_MeshNormals(mesh->num_triangles, mesh->data_element3i, mesh->num_vertices, mesh->data_vertex3f, mesh->data_texcoord2f, mesh->data_normal3f);
- Model_MeshTangents(mesh->num_triangles, mesh->data_element3i, mesh->num_vertices, mesh->data_vertex3f, mesh->data_texcoord2f, mesh->data_normal3f, mesh->data_svector3f, mesh->data_tvector3f);
- Model_MeshNeighbors(mesh->num_triangles, mesh->data_element3i, mesh->data_neighbor3i, mesh->num_vertices);
- Model_BuildTrianglePlanes(mesh->data_vertex3f, mesh->num_triangles, mesh->data_element3i, mesh->data_plane4f);
- // collision brushes are for the static frame
- // TODO: load separate collision brush file for faster collisions?
- mesh->num_collisionbrushes = mesh->num_triangles;
- mesh->max_collisionbrushes = mesh->num_collisionbrushes;
- mesh->data_collisionbrushes = Collision_Brush_AllocBrushesForTriangleMesh(r->memzone, mesh->max_triangles);
- Collision_Brush_UpdateTriangleMeshBrushes(mesh->data_collisionbrushes, mesh->num_triangles, mesh->data_element3i, mesh->data_vertex3f);
- // calculate culling shapes
- for (i = 0;i < mesh->num_vertices;i++)
- {
- NUint32 k;
- if (!i && !meshnum)
- {
- VectorCopy(mesh->data_vertex3f, model->basecullmins);
- VectorCopy(mesh->data_vertex3f, model->basecullmaxs);
- }
- else
- {
- model->basecullmins[0] = Min(model->basecullmins[0], mesh->data_vertex3f[i * 3 + 0]);
- model->basecullmins[1] = Min(model->basecullmins[1], mesh->data_vertex3f[i * 3 + 1]);
- model->basecullmins[2] = Min(model->basecullmins[2], mesh->data_vertex3f[i * 3 + 2]);
- model->basecullmaxs[0] = Max(model->basecullmaxs[0], mesh->data_vertex3f[i * 3 + 0]);
- model->basecullmaxs[1] = Max(model->basecullmaxs[1], mesh->data_vertex3f[i * 3 + 1]);
- model->basecullmaxs[2] = Max(model->basecullmaxs[2], mesh->data_vertex3f[i * 3 + 2]);
- }
- if (!i)
- {
- VectorCopy(mesh->data_vertex3f, mesh->basecullmins);
- VectorCopy(mesh->data_vertex3f, mesh->basecullmaxs);
- }
- else
- {
- mesh->basecullmins[0] = Min(mesh->basecullmins[0], mesh->data_vertex3f[i * 3 + 0]);
- mesh->basecullmins[1] = Min(mesh->basecullmins[1], mesh->data_vertex3f[i * 3 + 1]);
- mesh->basecullmins[2] = Min(mesh->basecullmins[2], mesh->data_vertex3f[i * 3 + 2]);
- mesh->basecullmaxs[0] = Max(mesh->basecullmaxs[0], mesh->data_vertex3f[i * 3 + 0]);
- mesh->basecullmaxs[1] = Max(mesh->basecullmaxs[1], mesh->data_vertex3f[i * 3 + 1]);
- mesh->basecullmaxs[2] = Max(mesh->basecullmaxs[2], mesh->data_vertex3f[i * 3 + 2]);
- }
- if (isskeletal)
- {
- for (k = 0;k < 4 && mesh->data_weightvalue4b[i*4+k] > 0;k++)
- {
- NUint32 index = mesh->data_weightindex4b[i*4+k];
- Nvec3 v1, v;
- Nvec r;
- VectorCopy(mesh->data_vertex3f + i * 3, v1);
- Matrix4x4_Transform(&model->data_transforminfo[index].baseinversematrix, v1, v);
- r = VectorLength(v);
- model->data_transforminfo[index].radius = Max(model->data_transforminfo[index].radius, r);
- }
- }
- }
Mem_Free(&md5weights);
Mem_Free(&md5weightrange);
meshnum++;
@@ -1212,17 +1197,55 @@
}
Util_ParseC_CleanUpThread(&thread);
Mem_Free(&filedata);
- // if there was a load error, don't point to the Model so nothing will try
- // to use the incomplete data
- if (!error)
- r->data = model;
#undef Abort
#undef LoadInt
#undef LoadValue
#undef LoadString
#undef ExpectKeyword
+ return error;
}
+Nbool Model_Build_Import(Model *model, Nsize filesize, const char *filedata)
+{
+ Nbool error = false;
+ if (String_EndsWith(model->filename, ".obj"))
+ error = Model_Build_Import_OBJ(model, filesize, filedata);
+ else if (String_EndsWith(model->filename, ".md5mesh"))
+ error = Model_Build_Import_MD5(model, filesize, filedata);
+ else
+ {
+ Console_Printf("Model_Build_Import_MD5: %s extension not recognized\n", model->filename);
+ error = true;
+ }
+ return error;
+}
+
+void Model_Load(ResourceEntry *r)
+{
+ Nsize filesize;
+ Model *model;
+ Nbool error;
+ char *filedata;
+
+ filedata = File_LoadFile(r->name, &filesize);
+ if (!filedata)
+ return;
+
+ model = Mem_Alloc(r->memzone, sizeof(Model));
+ Model_Build_Begin(model, r->name, r->memzone, false);
+
+ error = Model_Build_Import(model, filesize, filedata);
+
+ // if there was a load error, don't point to the Model so nothing will try
+ // to use the incomplete data
+ if (!error)
+ {
+ Model_Build_Compile(model, true, true, true, true, true, true);
+ r->data = model;
+ }
+}
+
+
void Model_Unload(UNUSED ResourceEntry *r)
{
// freeing of the memzone will get rid of the model
Modified: trunk/model.h
===================================================================
--- trunk/model.h 2006-05-12 11:03:18 UTC (rev 715)
+++ trunk/model.h 2006-05-12 11:04:48 UTC (rev 716)
@@ -81,6 +81,7 @@
typedef struct Model
{
// set at the creation of the Model
+ char filename[64];
Mem_Zone *memzone;
Nbool isskeletal;
@@ -99,20 +100,20 @@
}
Model;
+Nbool Model_Build_Import(Model *model, Nsize filesize, const char *filedata);
void Model_Load(ResourceEntry *r);
void Model_Unload(ResourceEntry *r);
-void Model_Build_Begin(Model *b, Mem_Zone *memzone, Nbool isskeletal);
-void Model_Build_Compile(Model *b, Nbool generateneighbors, Nbool generateplanes, Nbool generatenormals, Nbool generatetangents, Nbool generatelightmaptexcoords, Nbool generatecollisionbrushes);
-void Model_Build_Free(Model *b);
-NUint32 Model_Build_AddSurface(Model *b, Mem_Zone *zone, const char *materialname, NUint32 initialtriangles, NUint32 initialvertices);
-NUint32 Model_Build_AddVertex(Model *b, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t);
-NUint32 Model_Build_AddVertexSkeletal(Model *b, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t, NUint8 *wib, NUint8 *wfb);
-NUint32 Model_Build_FindOrAddVertex(Model *b, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t);
-NUint32 Model_Build_FindOrAddVertexSkeletal(Model *b, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t, NUint8 *wib, NUint8 *wfb);
-NUint32 Model_Build_AddTriangle(Model *b, NUint32 meshindex, int e0, int e1, int e2);
-void Model_Build_Write(Model *b, const char *filename);
-void Model_Build_ImportOBJ(Model *b, const char *inputname, const char *text, const char *textend);
+void Model_Build_Begin(Model *model, const char *filename, Mem_Zone *memzone, Nbool isskeletal);
+void Model_Build_Compile(Model *model, Nbool generateneighbors, Nbool generateplanes, Nbool generatenormals, Nbool generatetangents, Nbool generatelightmaptexcoords, Nbool generatecollisionbrushes);
+void Model_Build_Free(Model *model);
+NUint32 Model_Build_AddSurface(Model *model, const char *materialname, NUint32 initialtriangles, NUint32 initialvertices);
+NUint32 Model_Build_AddVertex(Model *model, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t);
+NUint32 Model_Build_AddVertexSkeletal(Model *model, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t, NUint8 *wib, NUint8 *wfb);
+NUint32 Model_Build_FindOrAddVertex(Model *model, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t);
+NUint32 Model_Build_FindOrAddVertexSkeletal(Model *model, NUint32 meshindex, float x, float y, float z, float nx, float ny, float nz, float s, float t, NUint8 *wib, NUint8 *wfb);
+NUint32 Model_Build_AddTriangle(Model *model, NUint32 meshindex, int e0, int e1, int e2);
+void Model_Build_Write(Model *model, const char *filename);
// this function decodes skeletal vertex information to your supplied arrays
// NOTE: outplane4f requires outvertex3f
Modified: trunk/nstring.c
===================================================================
--- trunk/nstring.c 2006-05-12 11:03:18 UTC (rev 715)
+++ trunk/nstring.c 2006-05-12 11:04:48 UTC (rev 716)
@@ -269,6 +269,18 @@
return strncasecmp(s ? s : "", t ? t : "", n);
}
+Nbool String_EndsWith(const char *s, const char *t)
+{
+ Nsize i;
+ Nsize slen = String_Length(s);
+ Nsize tlen = String_Length(t);
+ if (tlen && slen >= tlen)
+ for (i = 0;i <= slen - tlen;i++)
+ if (!String_Compare(s + i, t))
+ return true;
+ return false;
+}
+
void String_ToLower(char *s)
{
if( !s )
Modified: trunk/nstring.h
===================================================================
--- trunk/nstring.h 2006-05-12 11:03:18 UTC (rev 715)
+++ trunk/nstring.h 2006-05-12 11:04:48 UTC (rev 716)
@@ -29,6 +29,7 @@
NSint String_ICompare(const char *s, const char *t);
NSint String_NCompare(const char *s, const char *t, Nsize n);
NSint String_NICompare(const char *s, const char *t, Nsize n);
+Nbool String_EndsWith(const char *s, const char *t);
Nsize String_Length(const char *s);
Modified: trunk/util.c
===================================================================
--- trunk/util.c 2006-05-12 11:03:18 UTC (rev 715)
+++ trunk/util.c 2006-05-12 11:04:48 UTC (rev 716)
@@ -248,7 +248,7 @@
const char *basename, *imagename, *materialname;
char *tilename;
Nvec terrainsize[3], texturesize[2], terrainscale[3], terrainorigin[3], texturescale[2];
- Model b;
+ Model model;
basename = Shell_Callback_GetArg(1);
imagename = Shell_Callback_GetArg(2);
tilesize = (int) Shell_Callback_GetArgValue(3);
@@ -280,12 +280,14 @@
terrainorigin[2] = terrainsize[2] * -0.5;
tileswidth = width / tilesize;
tilesheight = height / tilesize;
- Model_Build_Begin(&b, Global_Zone, false);
+ tilename = String_APrintf(Global_Zone, "%s.md5mesh", basename);
+ Model_Build_Begin(&model, tilename, Global_Zone, false);
+ String_Free(&tilename);
for (by = 0;by < height;by += tilesize)
{
for (bx = 0;bx < width;bx += tilesize)
{
- NUint32 meshindex = Model_Build_AddSurface(&b, Global_Zone, materialname, 0, 0);
+ NUint32 meshindex = Model_Build_AddSurface(&model, materialname, 0, 0);
tilewidth = Bound(0, width - bx, tilesize+2);
tileheight = Bound(0, height - by, tilesize+2);
for (ty = 0, num = 0;ty < tileheight;ty++)
@@ -305,7 +307,7 @@
p = pixels + (pyi * width + pxi) * 4;
pz = ((p[0]+p[1]+p[2])*(1.0-pxf)+(p[4]+p[5]+p[6])*(pxf))*(1.0-pyf)+((p[w+0]+p[w+1]+p[w+2])*(1.0-pxf)+(p[w+4]+p[w+5]+p[w+6])*(pxf))*(pyf);
// FIXME: this SHOULD calculate a valid mesh normal!!
- Model_Build_AddVertex(&b, meshindex, px * terrainscale[0] + terrainorigin[0], py * terrainscale[1] + terrainorigin[1], pz * terrainscale[2] + terrainorigin[2], 0, 0, 1, (px * terrainscale[0] + terrainorigin[0]) * texturescale[0], (py * terrainscale[1] + terrainorigin[1]) * texturescale[1]);
+ Model_Build_AddVertex(&model, meshindex, px * terrainscale[0] + terrainorigin[0], py * terrainscale[1] + terrainorigin[1], pz * terrainscale[2] + terrainorigin[2], 0, 0, 1, (px * terrainscale[0] + terrainorigin[0]) * texturescale[0], (py * terrainscale[1] + terrainorigin[1]) * texturescale[1]);
}
}
for (ty = 0, num = 0;ty < tileheight-1;ty++)
@@ -313,17 +315,15 @@
for (tx = 0;tx < tilewidth-1;tx++, num += 6)
{
NUint32 i = ty*tilewidth+tx;
- Model_Build_AddTriangle(&b, meshindex, i, i+1, i+1+tilewidth);
- Model_Build_AddTriangle(&b, meshindex, i, i+1+tilewidth, i+tilewidth);
+ Model_Build_AddTriangle(&model, meshindex, i, i+1, i+1+tilewidth);
+ Model_Build_AddTriangle(&model, meshindex, i, i+1+tilewidth, i+tilewidth);
}
}
}
}
Mem_Free(&pixels);
- tilename = String_APrintf(Global_Zone, "%s.md5mesh", basename);
- Model_Build_Write(&b, tilename);
- String_Free(&tilename);
- Model_Build_Free(&b);
+ Model_Build_Write(&model, model.filename);
+ Model_Build_Free(&model);
}
static Shell_SymbolDecl Util_Shell_MakeTerrain_Decl = {
@@ -336,33 +336,33 @@
(Shell_Symbol_Callback) Util_Shell_MakeTerrain
};
-static void Util_Shell_ConvertOBJ(void)
+static void Util_Shell_ConvertModel(void)
{
- Nsize objtextsize;
- Model b;
+ Nsize filesize;
+ Model model;
const char *inputname = Shell_Callback_GetArg(1);
const char *outputname = Shell_Callback_GetArg(2);
- char *objtext = File_LoadFile(inputname, &objtextsize);
- if (!objtext)
+ char *filedata = File_LoadFile(inputname, &filesize);
+ if (!filedata)
{
- Shell_Callback_ThrowError("Could not open OBJ file\n");
+ Shell_Callback_ThrowError("Could not open model file\n");
// SHELLTODO
return;
}
- Model_Build_Begin(&b, Global_Zone, false);
- Model_Build_ImportOBJ(&b, inputname, objtext, objtext + objtextsize);
- Model_Build_Write(&b, outputname);
- Model_Build_Free(&b);
- Mem_Free(&objtext);
+ Model_Build_Begin(&model, inputname, Global_Zone, false);
+ if (!Model_Build_Import(&model, filesize, filedata))
+ Model_Build_Write(&model, outputname);
+ Model_Build_Free(&model);
+ Mem_Free(&filedata);
}
-static Shell_SymbolDecl Util_Shell_ConvertOBJ_Decl = {
- "util_convertobj",
- "Turn a .obj model into a .md5mesh model file.",
- "Usage: util_convertobj <inputname> <outputname>\n"
- "Example: util_convertobj maps/mymap/mymodel.obj maps/mymap/mymodel.md5mesh",
+static Shell_SymbolDecl Util_Shell_ConvertModel_Decl = {
+ "util_convertmodel",
+ "Convert a model from any supported format to any other.",
+ "Usage: util_convertmodel <inputname> <outputname>\n"
+ "Example: util_convertmodel maps/mymap/mymodel.obj maps/mymap/mymodel.md5mesh",
"ss",
- (Shell_Symbol_Callback) Util_Shell_ConvertOBJ
+ (Shell_Symbol_Callback) Util_Shell_ConvertModel
};
@@ -635,32 +635,32 @@
double boxsize;
const char *basefilename, *baseimagename;
char *filename;
- Model b;
+ Model model;
basefilename = Shell_Callback_GetArg(1);
baseimagename = Shell_Callback_GetArg(2);
boxsize = atof(Shell_Callback_GetArg(3));
- Model_Build_Begin(&b, 0, 0);
+ filename = String_APrintf(Global_Zone, "%s.md5mesh", basefilename);
+ Model_Build_Begin(&model, filename, Global_Zone, false);
+ String_Free(&filename);
for (i = 0;i < 6;i++)
{
NUint32 j;
NUint32 indices[4];
char *materialname = String_APrintf(Global_Zone, "%s_%s", baseimagename, skyboxsuffix[i]);
- NUint32 meshindex = Model_Build_AddSurface(&b, Global_Zone, materialname, 2, 4);
+ NUint32 meshindex = Model_Build_AddSurface(&model, materialname, 2, 4);
String_Free(&materialname);
for (j = 0;j < 4;j++)
- indices[j] = Model_Build_FindOrAddVertex(&b, meshindex, skyboxvertex[i][j][0], skyboxvertex[i][j][1], skyboxvertex[i][j][2], skyboxvertex[i][j][3], skyboxvertex[i][j][4], skyboxvertex[i][j][5], skyboxvertex[i][j][6], skyboxvertex[i][j][7]);
- Model_Build_AddTriangle(&b, meshindex, indices[0], indices[2], indices[1]);
- Model_Build_AddTriangle(&b, meshindex, indices[0], indices[3], indices[2]);
+ indices[j] = Model_Build_FindOrAddVertex(&model, meshindex, skyboxvertex[i][j][0], skyboxvertex[i][j][1], skyboxvertex[i][j][2], skyboxvertex[i][j][3], skyboxvertex[i][j][4], skyboxvertex[i][j][5], skyboxvertex[i][j][6], skyboxvertex[i][j][7]);
+ Model_Build_AddTriangle(&model, meshindex, indices[0], indices[2], indices[1]);
+ Model_Build_AddTriangle(&model, meshindex, indices[0], indices[3], indices[2]);
}
- filename = String_APrintf(Global_Zone, "%s.md5mesh", basefilename);
- Model_Build_Write(&b, filename);
- String_Free(&filename);
- Model_Build_Free(&b);
+ Model_Build_Write(&model, model.filename);
+ Model_Build_Free(&model);
}
static Shell_SymbolDecl Util_Shell_MakeSkyBox_Decl = {
"util_makeskybox",
- "Make an skybox md5mesh file.",
+ "Make a skybox md5mesh file.",
"Usage: util_makeskybox <maps/mymap/skybox> <imagebasename> <size>\n"
"Example: util_makeskybox maps/mymap/sunnyday maps/mymap/sunnyday 30000\n"
"would produce a file named maps/mymap/sunnyday.md5mesh containing 6 meshes for maps/mymap/sunnyday_px.tga and _nx, _py, _ny, _pz, _nz, forming a box +-100000m in each direction",
@@ -672,7 +672,7 @@
{
Shell_RegisterFunction(&Util_Shell_MakeTerrain_Decl);
Shell_RegisterFunction(&Util_Shell_MakeSkyBox_Decl);
- Shell_RegisterFunction(&Util_Shell_ConvertOBJ_Decl);
+ Shell_RegisterFunction(&Util_Shell_ConvertModel_Decl);
}
void Util_Quit(void)
More information about the neither-commits
mailing list