r714 - in trunk: . base/shaders
lordhavoc at icculus.org
lordhavoc at icculus.org
Fri May 12 04:36:48 EDT 2006
Author: lordhavoc
Date: 2006-05-12 04:36:47 -0400 (Fri, 12 May 2006)
New Revision: 714
Modified:
trunk/base/shaders/light.vert
trunk/model.c
trunk/model.h
trunk/util.c
trunk/util.h
Log:
migrated Util_BuildModel code into Model_Build namespace and it now uses
the Model struct
Modified: trunk/base/shaders/light.vert
===================================================================
--- trunk/base/shaders/light.vert 2006-05-09 20:05:18 UTC (rev 713)
+++ trunk/base/shaders/light.vert 2006-05-12 08:36:47 UTC (rev 714)
@@ -30,14 +30,14 @@
vec3 lightminusvertex = LightPosition - gl_Vertex.xyz;
LightVector.x = dot(lightminusvertex, gl_MultiTexCoord1.xyz);
LightVector.y = dot(lightminusvertex, gl_MultiTexCoord2.xyz);
- LightVector.z = -dot(lightminusvertex, gl_MultiTexCoord3.xyz);
+ LightVector.z = dot(lightminusvertex, gl_MultiTexCoord3.xyz);
#if defined(USESPECULAR) || defined(USEFOG) || defined(USEOFFSETMAPPING)
// transform unnormalized eye direction into tangent space
vec3 eyeminusvertex = EyePosition - gl_Vertex.xyz;
EyeVector.x = dot(eyeminusvertex, gl_MultiTexCoord1.xyz);
EyeVector.y = dot(eyeminusvertex, gl_MultiTexCoord2.xyz);
- EyeVector.z = -dot(eyeminusvertex, gl_MultiTexCoord3.xyz);
+ EyeVector.z = dot(eyeminusvertex, gl_MultiTexCoord3.xyz);
#endif
// transform vertex to camera space, using ftransform to match non-VS
Modified: trunk/model.c
===================================================================
--- trunk/model.c 2006-05-09 20:05:18 UTC (rev 713)
+++ trunk/model.c 2006-05-12 08:36:47 UTC (rev 714)
@@ -22,21 +22,37 @@
}
}
-// build vectors (along S, T, and Normal) for a triangle
-static void Model_TriangleVectors(const float *v0, const float *v1, const float *v2, const float *tc0, const float *tc1, const float *tc2, float *svector3f, float *tvector3f, float *normal3f)
+// build smoothed normals for all vertices of a mesh
+static void Model_MeshNormals(NUint32 numtriangles, const NUint32 *element3i, NUint32 numvertices, const float *vertex3f, const float *texcoord2f, float *normal3f)
{
- float f, tangentcross[3], v10[3], v20[3], tc10[2], tc20[2];
- // 103 add/sub/negate/multiply (1 cycle), 3 divide (20 cycle), 3 sqrt (22 cycle), 4 compare (3 cycle?), total cycles not counting load/store/exchange roughly 241 cycles
- // 12 add, 28 subtract, 57 multiply, 3 divide, 3 sqrt, 4 compare, 50% chance of 6 negates
+ NUint32 i, j;
+ float normal[3];
+ // clear the output array
+ memset(normal3f, 0, numvertices * sizeof(float[3]));
+ // iterate the triangles
+ for (i = 0;i < numtriangles;i++)
+ {
+ TriangleNormal(vertex3f + element3i[i*3+0]*3, vertex3f + element3i[i*3+1]*3, vertex3f + element3i[i*3+2]*3, normal);
+ // accumulate normals
+ for (j = 0;j < 3;j++)
+ VectorAdd(normal3f + element3i[i*3+j]*3, normal, normal3f + element3i[i*3+j]*3);
+ }
+ // normalize the results
+ for (i = 0;i < numvertices;i++)
+ VectorNormalize(normal3f + i * 3);
+}
+// build tangent vectors (vectors along S, T texcoords) for a triangle
+static void Model_TangentVectors(const float *v0, const float *v1, const float *v2, const float *tc0, const float *tc1, const float *tc2, float *svector3f, float *tvector3f)
+{
+ float tangentcross[3], v10[3], v20[3], tc10[2], tc20[2], normal3f[3];
+
// 6 multiply, 9 subtract
VectorSubtract(v1, v0, v10);
VectorSubtract(v2, v0, v20);
normal3f[0] = v20[1] * v10[2] - v10[1] * v20[2];
normal3f[1] = v20[2] * v10[0] - v10[2] * v20[0];
normal3f[2] = v20[0] * v10[1] - v10[0] * v20[1];
- // 1 sqrt, 1 divide, 6 multiply, 2 add, 1 compare
- VectorNormalize(normal3f);
// 12 multiply, 10 subtract
tc10[1] = tc1[1] - tc0[1];
tc20[1] = tc2[1] - tc0[1];
@@ -48,18 +64,6 @@
tvector3f[0] = v20[0] * tc10[0] - v10[0] * tc20[0];
tvector3f[1] = v20[1] * tc10[0] - v10[1] * tc20[0];
tvector3f[2] = v20[2] * tc10[0] - v10[2] * tc20[0];
- // 12 multiply, 4 add, 6 subtract
- f = DotProduct(svector3f, normal3f);
- svector3f[0] -= f * normal3f[0];
- svector3f[1] -= f * normal3f[1];
- svector3f[2] -= f * normal3f[2];
- f = DotProduct(tvector3f, normal3f);
- tvector3f[0] -= f * normal3f[0];
- tvector3f[1] -= f * normal3f[1];
- tvector3f[2] -= f * normal3f[2];
- // 2 sqrt, 2 divide, 12 multiply, 4 add, 2 compare
- VectorNormalize(svector3f);
- VectorNormalize(tvector3f);
// if texture is mapped the wrong way (counterclockwise), the tangents
// have to be flipped, this is detected by calculating a normal from the
// two tangents, and seeing if it is opposite the surface normal
@@ -73,39 +77,48 @@
}
// build smoothed vectors (along S, T, and Normal) for all vertices of a mesh
-static void Model_MeshVectors(NUint32 numtriangles, const NUint32 *element3i, NUint32 numvertices, const float *vertex3f, const float *texcoord2f, float *svector3f, float *tvector3f, float *normal3f)
+static void Model_MeshTangents(NUint32 numtriangles, const NUint32 *element3i, NUint32 numvertices, const float *vertex3f, const float *texcoord2f, float *normal3f, float *svector3f, float *tvector3f)
{
NUint32 i, j;
- float svector[3], tvector[3], normal[3];
// this calculates a set of vectors per triangle and blends them onto the
// triangle's vertices, if triangle share vertices (continuous mesh) this
// smooths them, if they are not shared then this looks facetted.
//
- // a possibly more intelligent scheme would be to smooth vectors on all
- // vertices at the same position that share similar vectors, but that
- // takes longer and may still yield artifacts on texcoord seams
+ // a possibly more intelligent scheme would be to smooth normals on all
+ // vertices at the same position that share similar normals, but that
+ // takes longer and is difficult if they belong to different meshes
// clear the output arrays
memset(svector3f, 0, numvertices * sizeof(float[3]));
memset(tvector3f, 0, numvertices * sizeof(float[3]));
- memset(normal3f, 0, numvertices * sizeof(float[3]));
// iterate the triangles
for (i = 0;i < numtriangles;i++)
{
- Model_TriangleVectors(vertex3f + element3i[i*3+0] * 3, vertex3f + element3i[i*3+1] * 3, vertex3f + element3i[i*3+2] * 3, texcoord2f + element3i[i*3+0] * 2, texcoord2f + element3i[i*3+1] * 2, texcoord2f + element3i[i*3+2] * 2, svector, tvector, normal);
+ float svector[3], tvector[3];
+ Model_TangentVectors(vertex3f + element3i[i*3+0] * 3, vertex3f + element3i[i*3+1] * 3, vertex3f + element3i[i*3+2] * 3, texcoord2f + element3i[i*3+0] * 2, texcoord2f + element3i[i*3+1] * 2, texcoord2f + element3i[i*3+2] * 2, svector, tvector);
// accumulate vectors onto vertices
for (j = 0;j < 3;j++)
{
VectorAdd(svector3f + element3i[i*3+j]*3, svector, svector3f + element3i[i*3+j]*3);
VectorAdd(tvector3f + element3i[i*3+j]*3, tvector, tvector3f + element3i[i*3+j]*3);
- VectorAdd(normal3f + element3i[i*3+j]*3, normal, normal3f + element3i[i*3+j]*3);
}
}
- // normalize the results
- for (i = 0;i < numvertices;i++)
+ // project tangents onto planes and normalize the results
+ for (i = 0;i < numvertices;i++, svector3f += 3, tvector3f += 3, normal3f += 3)
{
- VectorNormalize(svector3f + i * 3);
- VectorNormalize(tvector3f + i * 3);
- VectorNormalize(normal3f + i * 3);
+ // project tangents onto plane defined by normal
+ // (makes sure they are perpendicular to the normal)
+ float f;
+ f = DotProduct(svector3f, normal3f);
+ svector3f[0] -= f * normal3f[0];
+ svector3f[1] -= f * normal3f[1];
+ svector3f[2] -= f * normal3f[2];
+ f = DotProduct(tvector3f, normal3f);
+ tvector3f[0] -= f * normal3f[0];
+ tvector3f[1] -= f * normal3f[1];
+ tvector3f[2] -= f * normal3f[2];
+ // normalize the tangents
+ VectorNormalize(svector3f);
+ VectorNormalize(tvector3f);
}
}
@@ -175,6 +188,563 @@
Mem_Free(&hashtable);
}
+void Model_Build_Begin(Model *b, Mem_Zone *memzone, Nbool isskeletal)
+{
+ memset(b, 0, sizeof(*b));
+ b->memzone = memzone;
+ b->isskeletal = isskeletal;
+}
+
+static void Model_Build_GenerateNeighbors(Model_Mesh *mesh)
+{
+ Model_MeshNeighbors(mesh->num_triangles, mesh->data_element3i, mesh->data_neighbor3i, mesh->num_vertices);
+}
+
+static void Model_Build_GeneratePlanes(Model_Mesh *mesh)
+{
+ Model_BuildTrianglePlanes(mesh->data_vertex3f, mesh->num_triangles, mesh->data_element3i, mesh->data_plane4f);
+}
+
+static void Model_Build_GenerateNormals(Model_Mesh *mesh)
+{
+ Model_MeshNormals(mesh->num_triangles, mesh->data_element3i, mesh->num_vertices, mesh->data_vertex3f, mesh->data_texcoord2f, mesh->data_normal3f);
+}
+
+static void Model_Build_GenerateTangents(Model_Mesh *mesh)
+{
+ 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);
+}
+
+static void Model_Build_GenerateLightmapTexCoords(Model_Mesh *mesh)
+{
+ // TODO
+ // this function should build non-overlapping triangle groups in a
+ // lightmap texture with some kind of assumed resolution based on the
+ // model bounding box (the resolution only matters when ensuring that
+ // some texture exists around each group to accomodate linear filtering,
+ // or perhaps a bit more if we decide to use mipmapped lightmaps)
+ //
+ // TODO: how do do this?
+}
+
+void Model_Build_Compile(Model *b, Nbool generateneighbors, Nbool generateplanes, Nbool generatenormals, Nbool generatetangents, Nbool generatelightmaptexcoords, Nbool generatecollisionbrushes)
+{
+ NUint32 i, j;
+ 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++)
+ {
+ 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->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 (generateneighbors)
+ {
+ if (!mesh->data_neighbor3i) Mem_ReAlloc(b->memzone, &mesh->data_neighbor3i, mesh->max_triangles * 3 * sizeof(*mesh->data_neighbor3i));
+ Model_Build_GenerateNeighbors(mesh);
+ }
+
+ if (generateplanes)
+ {
+ if (!mesh->data_plane4f) Mem_ReAlloc(b->memzone, &mesh->data_plane4f, mesh->max_triangles * 4 * sizeof(*mesh->data_plane4f));
+ Model_Build_GeneratePlanes(mesh);
+ }
+
+ if (generatenormals)
+ {
+ if (!mesh->data_normal3f) Mem_ReAlloc(b->memzone, &mesh->data_normal3f, mesh->max_vertices * 3 * sizeof(*mesh->data_normal3f));
+ Model_Build_GenerateNormals(mesh);
+ }
+
+ 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));
+ Model_Build_GenerateTangents(mesh);
+ }
+
+ if (generatelightmaptexcoords)
+ {
+ if (!mesh->data_lightmaptexcoord2f) Mem_ReAlloc(b->memzone, &mesh->data_lightmaptexcoord2f, mesh->max_vertices * 2 * sizeof(*mesh->data_lightmaptexcoord2f));
+ Model_Build_GenerateLightmapTexCoords(mesh);
+ }
+
+ if (mesh->data_collisionbrushes)
+ {
+ Collision_Brush_FreeBrushesForTriangleMesh(mesh->data_collisionbrushes, mesh->max_collisionbrushes);
+ mesh->num_collisionbrushes = 0;
+ mesh->max_collisionbrushes = 0;
+ mesh->data_collisionbrushes = NULL;
+ }
+ 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);
+ 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)
+ {
+ if (initbox)
+ {
+ initbox = false;
+ VectorCopy(v, b->basecullmins);
+ VectorCopy(v, b->basecullmaxs);
+ }
+ 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]);
+ }
+ }
+ }
+}
+
+void Model_Build_Free(Model *b)
+{
+ NUint32 i;
+ Model_Mesh *mesh;
+ for (i = 0, mesh = b->data_meshes;i < b->num_meshes;i++, mesh++)
+ {
+ if (mesh->materialname) String_Free(&mesh->materialname);
+ if (mesh->data_element3i) Mem_Free(&mesh->data_element3i);
+ if (mesh->data_neighbor3i) Mem_Free(&mesh->data_neighbor3i);
+ if (mesh->data_plane4f) Mem_Free(&mesh->data_plane4f);
+ if (mesh->data_vertex3f) Mem_Free(&mesh->data_vertex3f);
+ if (mesh->data_svector3f) Mem_Free(&mesh->data_svector3f);
+ if (mesh->data_tvector3f) Mem_Free(&mesh->data_tvector3f);
+ if (mesh->data_normal3f) Mem_Free(&mesh->data_normal3f);
+ if (mesh->data_texcoord2f) Mem_Free(&mesh->data_texcoord2f);
+ if (mesh->data_lightmaptexcoord2f) Mem_Free(&mesh->data_lightmaptexcoord2f);
+ if (mesh->data_weightindex4b) Mem_Free(&mesh->data_weightindex4b);
+ 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));
+}
+
+NUint32 Model_Build_AddSurface(Model *b, Mem_Zone *zone, const char *materialname, NUint32 initialtriangles, NUint32 initialvertices)
+{
+ Model_Mesh *mesh;
+ if (b->num_meshes >= b->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));
+ }
+ mesh = b->data_meshes + b->num_meshes;
+ String_Set(&mesh->materialname, zone, materialname);
+ mesh->max_triangles = initialtriangles;
+ mesh->max_vertices = initialvertices;
+ b->num_meshes++;
+ return b->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)
+{
+ float *v;
+ Model_Mesh *mesh = b->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(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));
+ }
+ }
+ v = mesh->data_vertex3f + mesh->num_vertices * 3;
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ v = mesh->data_normal3f + mesh->num_vertices * 3;
+ v[0] = nx;
+ v[1] = ny;
+ v[2] = nz;
+ v = mesh->data_texcoord2f + mesh->num_vertices * 2;
+ v[0] = s;
+ v[1] = t;
+ if (b->isskeletal)
+ {
+ NUint8 *wi = mesh->data_weightindex4b + mesh->num_vertices * 4;
+ NUint8 *wf = mesh->data_weightvalue4b + mesh->num_vertices * 4;
+ wi[0] = 0;
+ wi[1] = 0;
+ wi[2] = 0;
+ wi[3] = 0;
+ wf[0] = 255;
+ wf[1] = 0;
+ wf[2] = 0;
+ wf[3] = 0;
+ }
+ mesh->num_vertices++;
+ 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)
+{
+ float *v;
+ Model_Mesh *mesh = b->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(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));
+ }
+ }
+ v = mesh->data_vertex3f + mesh->num_vertices * 3;
+ v[0] = x;
+ v[1] = y;
+ v[2] = z;
+ v = mesh->data_normal3f + mesh->num_vertices * 3;
+ v[0] = nx;
+ v[1] = ny;
+ v[2] = nz;
+ v = mesh->data_texcoord2f + mesh->num_vertices * 2;
+ v[0] = s;
+ v[1] = t;
+ if (b->isskeletal)
+ {
+ NUint8 *wi = mesh->data_weightindex4b + mesh->num_vertices * 4;
+ NUint8 *wf = mesh->data_weightvalue4b + mesh->num_vertices * 4;
+ Vector4Copy(wib, wi);
+ Vector4Copy(wfb, wf);
+ }
+ mesh->num_vertices++;
+ 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 i;
+ float *v, *n, *tc;
+ NUint8 *wi, *wf;
+ Model_Mesh *mesh = b->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);
+}
+
+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 i;
+ float *v, *n, *tc;
+ NUint8 *wi, *wf;
+ Model_Mesh *mesh = b->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
+ && 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);
+}
+
+NUint32 Model_Build_AddTriangle(Model *b, NUint32 meshindex, int e0, int e1, int e2)
+{
+ Model_Mesh *mesh = b->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));
+ }
+ e = mesh->data_element3i + mesh->num_triangles * 3;
+ e[0] = e0;
+ e[1] = e1;
+ e[2] = e2;
+ mesh->num_triangles++;
+ return mesh->num_triangles - 1;
+}
+
+void Model_Build_Write(Model *b, const char *filename)
+{
+ // FIXME: this is very unlikely to overflow but it should be made buffer size safe at some point
+ NUint32 i, num;
+ Nsize textsize, textmaxsize;
+ char *text;
+ Model_Mesh *mesh;
+ textmaxsize = 0x100000;
+ for (i = 0, mesh = b->data_meshes;i < b->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++)
+ {
+ if (textmaxsize < textsize + mesh->num_vertices * 100 + mesh->num_triangles * 100 + mesh->num_vertices * 100 + 1000)
+ {
+ textmaxsize = textsize + mesh->num_vertices * 200 + mesh->num_triangles * 200 + mesh->num_vertices * 200 + 2000;
+ Mem_ReAlloc(Global_Zone, &text, textmaxsize);
+ }
+ textsize += snprintf(text + textsize, textmaxsize - textsize, "\nmesh {\n\tshader \"%s\"\n\n\tnumverts %u\n", mesh->materialname, mesh->num_vertices);
+ for (num = 0;num < mesh->num_vertices;num++)
+ textsize += snprintf(text + textsize, textmaxsize - textsize, "\tvert %u ( %.6f %.6f ) %u 1\n", num, mesh->data_texcoord2f[num*2+0], mesh->data_texcoord2f[num*2+1], num);
+ textsize += snprintf(text + textsize, textmaxsize - textsize, "\n\tnumtris %u\n", mesh->num_triangles);
+ for (num = 0;num < mesh->num_triangles;num++)
+ textsize += snprintf(text + textsize, textmaxsize - textsize, "\ttri %u %u %u %u\n", num, mesh->data_element3i[num*3+0], mesh->data_element3i[num*3+1], mesh->data_element3i[num*3+2]);
+ textsize += snprintf(text + textsize, textmaxsize - textsize, "\n\tnumweights %u\n", mesh->num_vertices);
+ for (num = 0;num < mesh->num_vertices;num++)
+ textsize += snprintf(text + textsize, textmaxsize - textsize, "\tweight %u 0 1.000000 ( %.6f %.6f %.6f )\n", num, mesh->data_vertex3f[num*3+0], mesh->data_vertex3f[num*3+1], mesh->data_vertex3f[num*3+2]);
+ textsize += snprintf(text + textsize, textmaxsize - textsize, "}\n");
+ }
+ File_WriteFile(filename, text, textsize);
+ Mem_Free(&text);
+}
+
+void Model_Build_ImportOBJ(Model *b, const char *inputname, const char *text, const char *textend)
+{
+ NUint32 linenumber = 0;
+ NSint32 meshindex = -1;
+ NUint32 num_vertices = 0, max_vertices = 0;
+ NUint32 num_normals = 0, max_normals = 0;
+ NUint32 num_texcoords = 0, max_texcoords = 0;
+ float *data_vertex3f = NULL;
+ float *data_normal3f = NULL;
+ float *data_texcoord2f = NULL;
+ while (text < textend)
+ {
+ Nbool comment = false;
+ NUint32 argc = 0;
+ char argv[64][256];
+ // parse the line
+ linenumber++;
+ while (text < textend && *text != '\r' && *text != '\n')
+ {
+ if (comment || *text <= ' ')
+ text++;
+ else if (*text == '#')
+ comment = true;
+ else
+ {
+ NUint32 charnum;
+ for (charnum = 0;text < textend && *text > ' ';text++)
+ if (charnum < sizeof(argv[0]) - 1)
+ argv[argc][charnum++] = *text;
+ argv[argc++][charnum] = 0;
+ }
+ }
+ if (*text == '\r' && text[1] == '\n')
+ text++;
+ if (*text == '\n')
+ text++;
+ // now we have a command
+ if (argc < 1)
+ continue;
+ if (!String_Compare(argv[0], "v"))
+ {
+ // v -4.99960e-2 0.250000 -1.00000
+ if (argc == 4)
+ {
+ if (num_vertices >= max_vertices)
+ {
+ max_vertices = Max(max_vertices * 2, 1024);
+ Mem_ReAlloc(Global_Zone, &data_vertex3f, max_vertices * sizeof(float[3]));
+ }
+ data_vertex3f[num_vertices*3+0] = atof(argv[1]);
+ data_vertex3f[num_vertices*3+2] = atof(argv[2]);
+ data_vertex3f[num_vertices*3+1] = atof(argv[3]);
+ num_vertices++;
+ }
+ else
+ Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 3);
+ }
+ else if (!String_Compare(argv[0], "vn"))
+ {
+ // vn 1.99019e-6 2.65359e-5 -1.000000
+ if (argc == 4)
+ {
+ if (num_normals >= max_normals)
+ {
+ max_normals = Max(max_normals * 2, 1024);
+ Mem_ReAlloc(Global_Zone, &data_normal3f, max_normals * sizeof(float[3]));
+ }
+ data_normal3f[num_normals*3+0] = atof(argv[1]);
+ data_normal3f[num_normals*3+2] = atof(argv[2]);
+ data_normal3f[num_normals*3+1] = atof(argv[3]);
+ num_normals++;
+ }
+ else
+ Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 3);
+ }
+ else if (!String_Compare(argv[0], "vt"))
+ {
+ // vt 0.00000e+0 1.99019e-6
+ if (argc == 3)
+ {
+ if (num_texcoords >= max_texcoords)
+ {
+ max_texcoords = Max(max_texcoords * 2, 1024);
+ Mem_ReAlloc(Global_Zone, &data_texcoord2f, max_texcoords * sizeof(float[2]));
+ }
+ data_texcoord2f[num_texcoords*2+0] = atof(argv[1]);
+ data_texcoord2f[num_texcoords*2+1] = -atof(argv[2]);
+ num_texcoords++;
+ }
+ else
+ Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i parameters\n", inputname, 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);
+ else
+ Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 1);
+ }
+ else if (!String_Compare(argv[0], "f"))
+ {
+ // f 1/11/5 18/56/71 17/58/67
+ NUint32 i;
+ NUint32 indices[64];
+ if (argc >= 4)
+ {
+ if (meshindex == -1)
+ meshindex = Model_Build_AddSurface(b, Global_Zone, "default", 0, 0);
+ for (i = 0;i < argc - 1;i++)
+ {
+ NUint32 j;
+ const char *s = argv[i+1];
+ float v[3];
+ float vn[3];
+ float tc[2];
+ // if there are 3 indices, they are vertex, texcoord, normal
+ // if there are 2 indices, they are vertex, texcoord
+ // if there is only one index, it is vertex
+ // so we just initialize the values to defaults,
+ // and update them as indices are read
+ VectorClear(v);
+ VectorClear(vn);
+ Vector2Clear(tc);
+ for (j = 0;j < 3;j++)
+ {
+ if (*s)
+ {
+ NSint32 k = atoi(s);
+ switch (j)
+ {
+ case 0:
+ if (k < 0)
+ k += num_vertices;
+ else
+ k--;
+ 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);
+ break;
+ case 1:
+ if (k < 0)
+ k += num_texcoords;
+ else
+ k--;
+ 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);
+ break;
+ case 2:
+ if (k < 0)
+ k += num_normals;
+ else
+ k--;
+ 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);
+ break;
+ }
+ }
+ // this weird code construct exits at NUL, or if the
+ // character is /, and then leaves s at the character
+ // after the NUL or /
+ while (*s)
+ {
+ if (*s == '/')
+ {
+ s++;
+ break;
+ }
+ s++;
+ }
+ }
+ indices[i] = Model_Build_FindOrAddVertex(b, 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]);
+ }
+ }
+ else
+ Console_Printf("Model_Build_ImportOBJ: %s:%i: command %s takes %i or more parameters\n", inputname, 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);
+ }
+ 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);
+ }
+ 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);
+ }
+ else
+ Console_Printf("Model_Build_ImportOBJ: %s:%i: unknown obj command %s\n", inputname, linenumber, argv[0]);
+ }
+ if (data_vertex3f)
+ Mem_Free(&data_vertex3f);
+ if (data_normal3f)
+ Mem_Free(&data_normal3f);
+ if (data_texcoord2f)
+ Mem_Free(&data_texcoord2f);
+}
+
/* example clips of an MD5 model
MD5Version 10
commandline ""
@@ -578,7 +1148,8 @@
VectorCopy(md5weights[md5weightrange[i*2+0]].vertex, mesh->data_vertex3f + i*3);
}
// compile the base frame of the mesh for static uses
- Model_MeshVectors(mesh->num_triangles, mesh->data_element3i, mesh->num_vertices, mesh->data_vertex3f, mesh->data_texcoord2f, mesh->data_svector3f, mesh->data_tvector3f, mesh->data_normal3f);
+ 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
Modified: trunk/model.h
===================================================================
--- trunk/model.h 2006-05-09 20:05:18 UTC (rev 713)
+++ trunk/model.h 2006-05-12 08:36:47 UTC (rev 714)
@@ -80,6 +80,11 @@
typedef struct Model
{
+ // set at the creation of the Model
+ Mem_Zone *memzone;
+
+ Nbool isskeletal;
+
NUint32 num_meshes;
NUint32 max_meshes;
Model_Mesh *data_meshes;
@@ -97,6 +102,18 @@
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);
+
// this function decodes skeletal vertex information to your supplied arrays
// NOTE: outplane4f requires outvertex3f
void Model_GetVertices(NUint32 resourceindex, NUint32 meshindex, const matrix4x4_t *transforms, float *outvertex3f, float *outsvector3f, float *outtvector3f, float *outnormal3f, float *outplane4f);
Modified: trunk/util.c
===================================================================
--- trunk/util.c 2006-05-09 20:05:18 UTC (rev 713)
+++ trunk/util.c 2006-05-12 08:36:47 UTC (rev 714)
@@ -2,6 +2,7 @@
#include "ncommon.h"
#include "util.h"
#include "texture.h"
+#include "model.h"
static Shell_SymbolDecl Util_Shell_MakeSkyBox_Decl;
static Shell_SymbolDecl Util_Shell_MakeTerrain_Decl;
@@ -240,337 +241,6 @@
#undef ReadNext
}
-void Util_BuildModel_Begin(Util_BuildModel *b)
-{
- memset(b, 0, sizeof(*b));
-}
-
-void Util_BuildModel_End(Util_BuildModel *b)
-{
- NUint32 i;
- Util_BuildModel_Surface *surface;
- for (i = 0, surface = b->data_surfaces;i < b->num_surfaces;i++, surface++)
- {
- Mem_Free(&surface->data_element3i);
- Mem_Free(&surface->data_vertex8f);
- }
- Mem_Free(&b->data_surfaces);
- memset(b, 0, sizeof(*b));
-}
-
-NUint32 Util_BuildModel_AddSurface(Util_BuildModel *b, const char *materialname)
-{
- Util_BuildModel_Surface *surface;
- if (b->num_surfaces >= b->max_surfaces)
- {
- b->max_surfaces = Max(b->max_surfaces * 2, 16);
- Mem_ReAlloc(Global_Zone, &b->data_surfaces, b->max_surfaces * sizeof(Util_BuildModel_Surface));
- }
- surface = b->data_surfaces + b->num_surfaces;
- strncpy(surface->materialname, materialname, sizeof(surface->materialname) - 1);
- b->num_surfaces++;
- return b->num_surfaces - 1;
-}
-
-NUint32 Util_BuildModel_AddVertex(Util_BuildModel *b, NUint32 surfaceindex, float x, float y, float z, float nx, float ny, float nz, float s, float t)
-{
- float *v;
- Util_BuildModel_Surface *surface = b->data_surfaces + surfaceindex;
- if (surface->num_vertices >= surface->max_vertices)
- {
- surface->max_vertices = Max(surface->max_vertices * 2, 1024);
- Mem_ReAlloc(Global_Zone, &surface->data_vertex8f, surface->max_vertices * sizeof(float[8]));
- }
- v = surface->data_vertex8f + surface->num_vertices * 8;
- v[0] = x;
- v[1] = y;
- v[2] = z;
- v[3] = nx;
- v[4] = ny;
- v[5] = nz;
- v[6] = s;
- v[7] = t;
- surface->num_vertices++;
- return surface->num_vertices - 1;
-}
-
-NUint32 Util_BuildModel_FindOrAddVertex(Util_BuildModel *b, NUint32 surfaceindex, float x, float y, float z, float nx, float ny, float nz, float s, float t)
-{
- NUint32 i;
- float *v;
- Util_BuildModel_Surface *surface = b->data_surfaces + surfaceindex;
- for (i = 0, v = surface->data_vertex8f;i < surface->num_vertices;i++, v += 8)
- if (fabs(v[0] - x) < 0.0001 && fabs(v[1] - y) < 0.0001 && fabs(v[2] - z) < 0.0001 && fabs(v[3] - nx) < 0.0001 && fabs(v[4] - ny) < 0.0001 && fabs(v[5] - nz) < 0.0001 && fabs(v[6] - s) < 0.0001 && fabs(v[7] - t) < 0.0001)
- return i;
- return Util_BuildModel_AddVertex(b, surfaceindex, x, y, z, nx, ny, nz, s, t);
-}
-
-NUint32 Util_BuildModel_AddTriangle(Util_BuildModel *b, NUint32 surfaceindex, int e0, int e1, int e2)
-{
- Util_BuildModel_Surface *surface = b->data_surfaces + surfaceindex;
- NUint32 *e;
- if (surface->num_triangles >= surface->max_triangles)
- {
- surface->max_triangles = Max(surface->max_triangles * 2, 1024);
- Mem_ReAlloc(Global_Zone, &surface->data_element3i, surface->max_triangles * sizeof(NUint32[3]));
- }
- e = surface->data_element3i + surface->num_triangles * 3;
- e[0] = e0;
- e[1] = e1;
- e[2] = e2;
- surface->num_triangles++;
- return surface->num_triangles - 1;
-}
-
-void Util_BuildModel_Write(Util_BuildModel *b, const char *filename)
-{
- // FIXME: this is very unlikely to overflow but it should be made buffer size safe at some point
- NUint32 i, num;
- Nsize textsize, textmaxsize;
- char *text;
- Util_BuildModel_Surface *surface;
- textmaxsize = 0x100000;
- for (i = 0, surface = b->data_surfaces;i < b->num_surfaces;i++, surface++)
- textmaxsize += surface->num_vertices * 60 + surface->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_surfaces);
- for (i = 0, surface = b->data_surfaces;i < b->num_surfaces;i++, surface++)
- {
- if (textmaxsize < textsize + surface->num_vertices * 100 + surface->num_triangles * 100 + surface->num_vertices * 100 + 1000)
- {
- textmaxsize = textsize + surface->num_vertices * 200 + surface->num_triangles * 200 + surface->num_vertices * 200 + 2000;
- Mem_ReAlloc(Global_Zone, &text, textmaxsize);
- }
- textsize += snprintf(text + textsize, textmaxsize - textsize, "\nmesh {\n\tshader \"%s\"\n\n\tnumverts %u\n", surface->materialname, surface->num_vertices);
- for (num = 0;num < surface->num_vertices;num++)
- textsize += snprintf(text + textsize, textmaxsize - textsize, "\tvert %u ( %.6f %.6f ) %u 1\n", num, surface->data_vertex8f[num*8+6], surface->data_vertex8f[num*8+7], num);
- textsize += snprintf(text + textsize, textmaxsize - textsize, "\n\tnumtris %u\n", surface->num_triangles);
- for (num = 0;num < surface->num_triangles;num++)
- textsize += snprintf(text + textsize, textmaxsize - textsize, "\ttri %u %u %u %u\n", num, surface->data_element3i[num*3+0], surface->data_element3i[num*3+1], surface->data_element3i[num*3+2]);
- textsize += snprintf(text + textsize, textmaxsize - textsize, "\n\tnumweights %u\n", surface->num_vertices);
- for (num = 0;num < surface->num_vertices;num++)
- textsize += snprintf(text + textsize, textmaxsize - textsize, "\tweight %u 0 1.000000 ( %.6f %.6f %.6f )\n", num, surface->data_vertex8f[num*8+0], surface->data_vertex8f[num*8+1], surface->data_vertex8f[num*8+2]);
- textsize += snprintf(text + textsize, textmaxsize - textsize, "}\n");
- }
- File_WriteFile(filename, text, textsize);
- Mem_Free(&text);
-}
-
-void Util_BuildModel_ImportOBJ(Util_BuildModel *b, const char *inputname, const char *text, const char *textend)
-{
- NUint32 linenumber = 0;
- NSint32 surfaceindex = -1;
- NUint32 num_vertices = 0, max_vertices = 0;
- NUint32 num_normals = 0, max_normals = 0;
- NUint32 num_texcoords = 0, max_texcoords = 0;
- float *data_vertex3f = NULL;
- float *data_normal3f = NULL;
- float *data_texcoord2f = NULL;
- while (text < textend)
- {
- Nbool comment = false;
- NUint32 argc = 0;
- char argv[64][256];
- // parse the line
- linenumber++;
- while (text < textend && *text != '\r' && *text != '\n')
- {
- if (comment || *text <= ' ')
- text++;
- else if (*text == '#')
- comment = true;
- else
- {
- NUint32 charnum;
- for (charnum = 0;text < textend && *text > ' ';text++)
- if (charnum < sizeof(argv[0]) - 1)
- argv[argc][charnum++] = *text;
- argv[argc++][charnum] = 0;
- }
- }
- if (*text == '\r' && text[1] == '\n')
- text++;
- if (*text == '\n')
- text++;
- // now we have a command
- if (argc < 1)
- continue;
- if (!String_Compare(argv[0], "v"))
- {
- // v -4.99960e-2 0.250000 -1.00000
- if (argc == 4)
- {
- if (num_vertices >= max_vertices)
- {
- max_vertices = Max(max_vertices * 2, 1024);
- Mem_ReAlloc(Global_Zone, &data_vertex3f, max_vertices * sizeof(float[3]));
- }
- data_vertex3f[num_vertices*3+0] = atof(argv[1]);
- data_vertex3f[num_vertices*3+2] = atof(argv[2]);
- data_vertex3f[num_vertices*3+1] = atof(argv[3]);
- num_vertices++;
- }
- else
- Console_Printf("util_convertobj: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 3);
- }
- else if (!String_Compare(argv[0], "vn"))
- {
- // vn 1.99019e-6 2.65359e-5 -1.000000
- if (argc == 4)
- {
- if (num_normals >= max_normals)
- {
- max_normals = Max(max_normals * 2, 1024);
- Mem_ReAlloc(Global_Zone, &data_normal3f, max_normals * sizeof(float[3]));
- }
- data_normal3f[num_normals*3+0] = atof(argv[1]);
- data_normal3f[num_normals*3+2] = atof(argv[2]);
- data_normal3f[num_normals*3+1] = atof(argv[3]);
- num_normals++;
- }
- else
- Console_Printf("util_convertobj: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 3);
- }
- else if (!String_Compare(argv[0], "vt"))
- {
- // vt 0.00000e+0 1.99019e-6
- if (argc == 3)
- {
- if (num_texcoords >= max_texcoords)
- {
- max_texcoords = Max(max_texcoords * 2, 1024);
- Mem_ReAlloc(Global_Zone, &data_texcoord2f, max_texcoords * sizeof(float[2]));
- }
- data_texcoord2f[num_texcoords*2+0] = atof(argv[1]);
- data_texcoord2f[num_texcoords*2+1] = -atof(argv[2]);
- num_texcoords++;
- }
- else
- Console_Printf("util_convertobj: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 2);
- }
- else if (!String_Compare(argv[0], "usemtl"))
- {
- // usemtl mtrl/chrome
- if (argc == 2)
- surfaceindex = Util_BuildModel_AddSurface(b, argv[1]);
- else
- Console_Printf("util_convertobj: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 1);
- }
- else if (!String_Compare(argv[0], "f"))
- {
- // f 1/11/5 18/56/71 17/58/67
- NUint32 i;
- NUint32 indices[64];
- if (argc >= 4)
- {
- if (surfaceindex == -1)
- surfaceindex = Util_BuildModel_AddSurface(b, "default");
- for (i = 0;i < argc - 1;i++)
- {
- NUint32 j;
- const char *s = argv[i+1];
- float v[3];
- float vn[3];
- float tc[2];
- // if there are 3 indices, they are vertex, texcoord, normal
- // if there are 2 indices, they are vertex, texcoord
- // if there is only one index, it is vertex
- // so we just initialize the values to defaults,
- // and update them as indices are read
- VectorClear(v);
- VectorClear(vn);
- Vector2Clear(tc);
- for (j = 0;j < 3;j++)
- {
- if (*s)
- {
- NSint32 k = atoi(s);
- switch (j)
- {
- case 0:
- if (k < 0)
- k += num_vertices;
- else
- k--;
- if (k >= 0 && k < num_vertices)
- VectorCopy(data_vertex3f + k * 3, v);
- else
- Console_Printf("util_convertobj: %s:%i: invalid face vertex index (parameter #%i)\n", inputname, linenumber, i + 1);
- break;
- case 1:
- if (k < 0)
- k += num_texcoords;
- else
- k--;
- if (k >= 0 && k < num_texcoords)
- Vector2Copy(data_texcoord2f + k * 2, tc);
- else
- Console_Printf("util_convertobj: %s:%i: invalid face texcoord index (parameter #%i)\n", inputname, linenumber, i + 1);
- break;
- case 2:
- if (k < 0)
- k += num_normals;
- else
- k--;
- if (k >= 0 && k < num_normals)
- VectorCopy(data_normal3f + k * 3, vn);
- else
- Console_Printf("util_convertobj: %s:%i: invalid face vertexnormal index (parameter #%i)\n", inputname, linenumber, i + 1);
- break;
- }
- }
- // this weird code construct exits at NUL, or if the
- // character is /, and then leaves s at the character
- // after the NUL or /
- while (*s)
- {
- if (*s == '/')
- {
- s++;
- break;
- }
- s++;
- }
- }
- indices[i] = Util_BuildModel_FindOrAddVertex(b, surfaceindex, 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)
- Util_BuildModel_AddTriangle(b, surfaceindex, indices[0], indices[i-1], indices[i]);
- }
- }
- else
- Console_Printf("util_convertobj: %s:%i: command %s takes %i or more parameters\n", inputname, linenumber, argv[0], 3);
- }
- else if (!String_Compare(argv[0], "o"))
- {
- // o cylinder1
- if (argc != 2)
- Console_Printf("util_convertobj: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 1);
- }
- else if (!String_Compare(argv[0], "mtllib"))
- {
- // mtllib zrail2.mtl
- if (argc != 2)
- Console_Printf("util_convertobj: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 1);
- }
- else if (!String_Compare(argv[0], "g"))
- {
- // g cylinder1_mtrl/invisible
- if (argc != 2)
- Console_Printf("util_convertobj: %s:%i: command %s takes %i parameters\n", inputname, linenumber, argv[0], 1);
- }
- else
- Console_Printf("util_convertobj: %s:%i: unknown obj command %s\n", inputname, linenumber, argv[0]);
- }
- if (data_vertex3f)
- Mem_Free(&data_vertex3f);
- if (data_normal3f)
- Mem_Free(&data_normal3f);
- if (data_texcoord2f)
- Mem_Free(&data_texcoord2f);
-}
-
static void Util_Shell_MakeTerrain(void)
{
NUint32 tilesize, width, height, bx, by, tx, ty, tilewidth, tileheight, num, tileswidth, tilesheight;
@@ -578,7 +248,7 @@
const char *basename, *imagename, *materialname;
char *tilename;
Nvec terrainsize[3], texturesize[2], terrainscale[3], terrainorigin[3], texturescale[2];
- Util_BuildModel b;
+ Model b;
basename = Shell_Callback_GetArg(1);
imagename = Shell_Callback_GetArg(2);
tilesize = (int) Shell_Callback_GetArgValue(3);
@@ -610,12 +280,12 @@
terrainorigin[2] = terrainsize[2] * -0.5;
tileswidth = width / tilesize;
tilesheight = height / tilesize;
- Util_BuildModel_Begin(&b);
+ Model_Build_Begin(&b, Global_Zone, false);
for (by = 0;by < height;by += tilesize)
{
for (bx = 0;bx < width;bx += tilesize)
{
- NUint32 surfaceindex = Util_BuildModel_AddSurface(&b, materialname);
+ NUint32 meshindex = Model_Build_AddSurface(&b, Global_Zone, 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++)
@@ -634,8 +304,8 @@
pyf = py - pyi;
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 surface normal!!
- Util_BuildModel_AddVertex(&b, surfaceindex, 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]);
+ // 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]);
}
}
for (ty = 0, num = 0;ty < tileheight-1;ty++)
@@ -643,17 +313,17 @@
for (tx = 0;tx < tilewidth-1;tx++, num += 6)
{
NUint32 i = ty*tilewidth+tx;
- Util_BuildModel_AddTriangle(&b, surfaceindex, i, i+1, i+1+tilewidth);
- Util_BuildModel_AddTriangle(&b, surfaceindex, i, i+1+tilewidth, i+tilewidth);
+ Model_Build_AddTriangle(&b, meshindex, i, i+1, i+1+tilewidth);
+ Model_Build_AddTriangle(&b, meshindex, i, i+1+tilewidth, i+tilewidth);
}
}
}
}
Mem_Free(&pixels);
tilename = String_APrintf(Global_Zone, "%s.md5mesh", basename);
- Util_BuildModel_Write(&b, tilename);
+ Model_Build_Write(&b, tilename);
String_Free(&tilename);
- Util_BuildModel_End(&b);
+ Model_Build_Free(&b);
}
static Shell_SymbolDecl Util_Shell_MakeTerrain_Decl = {
@@ -669,7 +339,7 @@
static void Util_Shell_ConvertOBJ(void)
{
Nsize objtextsize;
- Util_BuildModel b;
+ Model b;
const char *inputname = Shell_Callback_GetArg(1);
const char *outputname = Shell_Callback_GetArg(2);
char *objtext = File_LoadFile(inputname, &objtextsize);
@@ -679,10 +349,10 @@
// SHELLTODO
return;
}
- Util_BuildModel_Begin(&b);
- Util_BuildModel_ImportOBJ(&b, inputname, objtext, objtext + objtextsize);
- Util_BuildModel_Write(&b, outputname);
- Util_BuildModel_End(&b);
+ 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);
}
@@ -702,7 +372,7 @@
#define UTIL_SHELL_CONVERTLWO_FACE_MAXVERTS 4
typedef struct Util_Shell_ConvertLWO_Face
{
- NUint32 surfaceindex;
+ NUint32 meshindex;
NUint32 numpoints;
float point[UTIL_SHELL_CONVERTLWO_FACE_MAXVERTS][3];
}
@@ -823,7 +493,7 @@
// polygon attributes
if (!memcmp(chunk, "SURF", 4))
{
- // list of polygons and their corresponding surfaces
+ // list of polygons and their corresponding meshes
chunk_ptag_surf = chunk;
}
continue;
@@ -846,7 +516,7 @@
if (!memcmp(chunk, "SURF", 4))
{
materialindex++;
- // surface name, often Default
+ // mesh name, often Default
while (*content)
content++;
// skip to 4 byte boundary in file
@@ -965,27 +635,27 @@
double boxsize;
const char *basefilename, *baseimagename;
char *filename;
- Util_BuildModel b;
+ Model b;
basefilename = Shell_Callback_GetArg(1);
baseimagename = Shell_Callback_GetArg(2);
boxsize = atof(Shell_Callback_GetArg(3));
- Util_BuildModel_Begin(&b);
+ Model_Build_Begin(&b, 0, 0);
for (i = 0;i < 6;i++)
{
NUint32 j;
NUint32 indices[4];
char *materialname = String_APrintf(Global_Zone, "%s_%s", baseimagename, skyboxsuffix[i]);
- NUint32 surfaceindex = Util_BuildModel_AddSurface(&b, materialname);
+ NUint32 meshindex = Model_Build_AddSurface(&b, Global_Zone, materialname, 2, 4);
String_Free(&materialname);
for (j = 0;j < 4;j++)
- indices[j] = Util_BuildModel_FindOrAddVertex(&b, surfaceindex, 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]);
- Util_BuildModel_AddTriangle(&b, surfaceindex, indices[0], indices[2], indices[1]);
- Util_BuildModel_AddTriangle(&b, surfaceindex, indices[0], indices[3], indices[2]);
+ 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]);
}
filename = String_APrintf(Global_Zone, "%s.md5mesh", basefilename);
- Util_BuildModel_Write(&b, filename);
+ Model_Build_Write(&b, filename);
String_Free(&filename);
- Util_BuildModel_End(&b);
+ Model_Build_Free(&b);
}
static Shell_SymbolDecl Util_Shell_MakeSkyBox_Decl = {
Modified: trunk/util.h
===================================================================
--- trunk/util.h 2006-05-09 20:05:18 UTC (rev 713)
+++ trunk/util.h 2006-05-12 08:36:47 UTC (rev 714)
@@ -40,35 +40,6 @@
// lex the next token
void Util_ParseC_Lex(Util_ParseC_Thread *thread);
-typedef struct Util_BuildModel_Surface
-{
- // no support for skeletal weighting since this is only used by utilities building simple models
- char materialname[64];
- NUint32 num_triangles, max_triangles;
- NUint32 *data_element3i;
- NUint32 num_vertices, max_vertices;
- float *data_vertex8f;
-}
-Util_BuildModel_Surface;
-
-typedef struct Util_BuildModel
-{
- NUint32 num_surfaces, max_surfaces;
- Util_BuildModel_Surface *data_surfaces;
- // no support for skeleton since this is only used by utilities building simple models
-}
-Util_BuildModel;
-
-// a small system for easily building md5mesh files
-void Util_BuildModel_Begin(Util_BuildModel *b);
-void Util_BuildModel_End(Util_BuildModel *b);
-NUint32 Util_BuildModel_AddSurface(Util_BuildModel *b, const char *materialname);
-NUint32 Util_BuildModel_AddVertex(Util_BuildModel *b, NUint32 surfaceindex, float x, float y, float z, float nx, float ny, float nz, float s, float t);
-NUint32 Util_BuildModel_FindOrAddVertex(Util_BuildModel *b, NUint32 surfaceindex, float x, float y, float z, float nx, float ny, float nz, float s, float t);
-NUint32 Util_BuildModel_AddTriangle(Util_BuildModel *b, NUint32 surfaceindex, int e0, int e1, int e2);
-void Util_BuildModel_Write(Util_BuildModel *b, const char *filename);
-void Util_BuildModel_ImportOBJ(Util_BuildModel *b, const char *inputname, const char *text, const char *textend);
-
void Util_Init(void);
void Util_Quit(void);
More information about the neither-commits
mailing list