summaryrefslogtreecommitdiff
path: root/utils/studiomdl/v1support.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/studiomdl/v1support.cpp')
-rw-r--r--utils/studiomdl/v1support.cpp393
1 files changed, 393 insertions, 0 deletions
diff --git a/utils/studiomdl/v1support.cpp b/utils/studiomdl/v1support.cpp
new file mode 100644
index 0000000..a6ac369
--- /dev/null
+++ b/utils/studiomdl/v1support.cpp
@@ -0,0 +1,393 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+//
+// studiomdl.c: generates a studio .mdl file from a .qc script
+// sources/<scriptname>.mdl.
+//
+
+
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4237 )
+#pragma warning( disable : 4305 )
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <math.h>
+
+#include "cmdlib.h"
+#include "scriplib.h"
+#include "mathlib/mathlib.h"
+#include "studio.h"
+#include "studiomdl.h"
+
+// The current version of the SMD file being parsed
+// Yes, I know this file is called 'v1support' and there's never actually
+// been a v > 1 but now there is
+// (actually, there was a while when we were using developing progressive mesh
+// stuff in the middle of HL2 development, but most all that code has long since
+// been deleted)
+int g_smdVersion = 1;
+
+int lookup_index( s_source_t *psource, int material, Vector& vertex, Vector& normal, Vector2D texcoord, int iCount, int bones[], float weights[] )
+{
+ int i, j;
+
+ for (i = 0; i < numvlist; i++)
+ {
+ if (v_listdata[i].m == material
+ && DotProduct( g_normal[i], normal ) > normal_blend
+ && VectorCompare( g_vertex[i], vertex )
+ && g_texcoord[i][0] == texcoord[0]
+ && g_texcoord[i][1] == texcoord[1])
+ {
+ if (g_bone[i].numbones == iCount)
+ {
+ for (j = 0; j < iCount; j++)
+ {
+ if (g_bone[i].bone[j] != bones[j] || g_bone[i].weight[j] != weights[j])
+ break;
+ }
+ if (j == iCount)
+ {
+ v_listdata[i].lastref = numvlist;
+ return i;
+ }
+ }
+ }
+ }
+ if (i >= MAXSTUDIOVERTS) {
+ MdlError( "too many indices in source: \"%s\"\n", psource->filename);
+ }
+
+ VectorCopy( vertex, g_vertex[i] );
+ VectorCopy( normal, g_normal[i] );
+ Vector2Copy( texcoord, g_texcoord[i] );
+
+ g_bone[i].numbones = iCount;
+ for ( j = 0; j < iCount; j++)
+ {
+ g_bone[i].bone[j] = bones[j];
+ g_bone[i].weight[j] = weights[j];
+ }
+
+ v_listdata[i].v = i;
+ v_listdata[i].m = material;
+ v_listdata[i].n = i;
+ v_listdata[i].t = i;
+
+ v_listdata[i].firstref = numvlist;
+ v_listdata[i].lastref = numvlist;
+
+ numvlist = i + 1;
+ return i;
+}
+
+
+void ParseFaceData( s_source_t *psource, int material, s_face_t *pFace )
+{
+ int index[3] = {};
+ int i, j;
+ Vector p;
+ Vector normal;
+ Vector2D t;
+ int iCount, bones[MAXSTUDIOSRCBONES];
+ float weights[MAXSTUDIOSRCBONES];
+ int bone;
+
+ for (j = 0; j < 3; j++)
+ {
+ memset( g_szLine, 0, sizeof( g_szLine ) );
+
+ if (!GetLineInput())
+ {
+ MdlError("%s: error on g_szLine %d: %s", g_szFilename, g_iLinecount, g_szLine );
+ }
+
+ iCount = 0;
+
+ i = sscanf( g_szLine, "%d %f %f %f %f %f %f %f %f %d %d %f %d %f %d %f %d %f",
+ &bone,
+ &p[0], &p[1], &p[2],
+ &normal[0], &normal[1], &normal[2],
+ &t[0], &t[1],
+ &iCount,
+ &bones[0], &weights[0], &bones[1], &weights[1], &bones[2], &weights[2], &bones[3], &weights[3] );
+
+ if (i < 9)
+ continue;
+
+ if (bone < 0 || bone >= psource->numbones)
+ {
+ MdlError("bogus bone index\n%d %s :\n%s", g_iLinecount, g_szFilename, g_szLine );
+ }
+
+ //Scale face pos
+ scale_vertex( p );
+
+ // continue parsing more bones.
+ // FIXME: don't we have a built in parser that'll do this?
+ if (iCount > 4)
+ {
+ int k;
+ int ctr = 0;
+ char *token;
+ for (k = 0; k < 18; k++)
+ {
+ while (g_szLine[ctr] == ' ')
+ {
+ ctr++;
+ }
+ token = strtok( &g_szLine[ctr], " " );
+ ctr += strlen( token ) + 1;
+ }
+ for (k = 4; k < iCount && k < MAXSTUDIOSRCBONES; k++)
+ {
+ while (g_szLine[ctr] == ' ')
+ {
+ ctr++;
+ }
+ token = strtok( &g_szLine[ctr], " " );
+ ctr += strlen( token ) + 1;
+
+ bones[k] = atoi(token);
+
+ token = strtok( &g_szLine[ctr], " " );
+ ctr += strlen( token ) + 1;
+
+ weights[k] = atof(token);
+ }
+ // printf("%d ", iCount );
+
+ //printf("\n");
+ //exit(1);
+ }
+
+ // adjust_vertex( p );
+ // scale_vertex( p );
+
+ // move vertex position to object space.
+ // VectorSubtract( p, psource->bonefixup[bone].worldorg, tmp );
+ // VectorTransform(tmp, psource->bonefixup[bone].im, p );
+
+ // move normal to object space.
+ // VectorCopy( normal, tmp );
+ // VectorTransform(tmp, psource->bonefixup[bone].im, normal );
+ // VectorNormalize( normal );
+
+ // invert v
+ t[1] = 1.0 - t[1];
+
+ if (i == 9 || iCount == 0)
+ {
+ iCount = 1;
+ bones[0] = bone;
+ weights[0] = 1.0;
+ }
+ else
+ {
+ iCount = SortAndBalanceBones( iCount, MAXSTUDIOBONEWEIGHTS, bones, weights );
+ }
+
+
+ index[j] = lookup_index( psource, material, p, normal, t, iCount, bones, weights );
+ }
+
+ // pFace->material = material; // BUG
+ pFace->a = index[0];
+ pFace->b = index[2];
+ pFace->c = index[1];
+ Assert( ((pFace->a & 0xF0000000) == 0) && ((pFace->b & 0xF0000000) == 0) &&
+ ((pFace->c & 0xF0000000) == 0) );
+}
+
+void Grab_Triangles( s_source_t *psource )
+{
+ int i;
+ Vector vmin, vmax;
+
+ vmin[0] = vmin[1] = vmin[2] = 99999;
+ vmax[0] = vmax[1] = vmax[2] = -99999;
+
+ g_numfaces = 0;
+ numvlist = 0;
+
+ //
+ // load the base triangles
+ //
+ int texture;
+ int material;
+ char texturename[MAX_PATH];
+
+ while (1)
+ {
+ if (!GetLineInput())
+ break;
+
+ // check for end
+ if (IsEnd( g_szLine ))
+ break;
+
+ // Look for extra junk that we may want to avoid...
+ int nLineLength = strlen( g_szLine );
+ if (nLineLength >= sizeof( texturename ))
+ {
+ MdlWarning("Unexpected data at line %d, (need a texture name) ignoring...\n", g_iLinecount );
+ continue;
+ }
+
+ // strip off trailing smag
+ V_strcpy_safe( texturename, g_szLine );
+ for (i = strlen( texturename ) - 1; i >= 0 && ! V_isgraph( texturename[i] ); i--)
+ {
+ }
+ texturename[i + 1] = '\0';
+
+ // funky texture overrides
+ for (i = 0; i < numrep; i++)
+ {
+ if (sourcetexture[i][0] == '\0')
+ {
+ V_strcpy_safe( texturename, defaulttexture[i] );
+ break;
+ }
+ if (stricmp( texturename, sourcetexture[i]) == 0)
+ {
+ V_strcpy_safe( texturename, defaulttexture[i] );
+ break;
+ }
+ }
+
+ if (texturename[0] == '\0')
+ {
+ // weird source problem, skip them
+ GetLineInput();
+ GetLineInput();
+ GetLineInput();
+ continue;
+ }
+
+ if (stricmp( texturename, "null.bmp") == 0 || stricmp( texturename, "null.tga") == 0 || stricmp( texturename, "debug/debugempty" ) == 0)
+ {
+ // skip all faces with the null texture on them.
+ GetLineInput();
+ GetLineInput();
+ GetLineInput();
+ continue;
+ }
+
+ texture = LookupTexture( texturename, ( g_smdVersion > 1 ) );
+ psource->texmap[texture] = texture; // hack, make it 1:1
+ material = UseTextureAsMaterial( texture );
+
+ s_face_t f;
+ ParseFaceData( psource, material, &f );
+
+ // remove degenerate triangles
+ if (f.a == f.b || f.b == f.c || f.a == f.c)
+ {
+ // printf("Degenerate triangle %d %d %d\n", f.a, f.b, f.c );
+ continue;
+ }
+
+ g_src_uface[g_numfaces] = f;
+ g_face[g_numfaces].material = material;
+ g_numfaces++;
+ }
+
+ BuildIndividualMeshes( psource );
+}
+
+
+int Load_SMD ( s_source_t *psource )
+{
+ char cmd[1024];
+ int option;
+
+ // Reset smdVersion
+ g_smdVersion = 1;
+
+ if (!OpenGlobalFile( psource->filename ))
+ return 0;
+
+ if( !g_quiet )
+ {
+ printf ("SMD MODEL %s\n", psource->filename);
+ }
+
+ g_iLinecount = 0;
+
+ while (GetLineInput())
+ {
+ int numRead = sscanf( g_szLine, "%s %d", cmd, &option );
+
+ // Blank line
+ if ((numRead == EOF) || (numRead == 0))
+ continue;
+
+ if (stricmp( cmd, "version" ) == 0)
+ {
+ if (option < 1 || option > 2)
+ {
+ MdlError("bad version\n");
+ }
+ g_smdVersion = option;
+ }
+ else if (stricmp( cmd, "nodes" ) == 0)
+ {
+ psource->numbones = Grab_Nodes( psource->localBone );
+ }
+ else if (stricmp( cmd, "skeleton" ) == 0)
+ {
+ Grab_Animation( psource, "BindPose" );
+ }
+ else if (stricmp( cmd, "triangles" ) == 0)
+ {
+ Grab_Triangles( psource );
+ }
+ else if (stricmp( cmd, "vertexanimation" ) == 0)
+ {
+ Grab_Vertexanimation( psource, "BindPose" );
+ }
+ else if ((strncmp( cmd, "//", 2 ) == 0) || (strncmp( cmd, ";", 1 ) == 0) || (strncmp( cmd, "#", 1 ) == 0))
+ {
+ ProcessSourceComment( psource, cmd );
+ continue;
+ }
+ else
+ {
+ MdlWarning("unknown studio command \"%s\"\n", cmd );
+ }
+ }
+ fclose( g_fpInput );
+
+ return 1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+