halflife-thewastes-sdk/utils/studiotwm/parsesmd.c

248 lines
5.0 KiB
C

/***
*
* Copyright (C) 2002 The Wastes Project, All Rights Reserved.
*
* This product contains software technology from Valve Software, LLC,
* Copyright © 1996-2001, Valve LLC, All rights reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* The Wastes Project. All other use, distribution, or modification is prohibited
* without written permission from The Wastes Project.
*
***/
//
// Read a .smd reference file
//
#include <ctype.h>
#include <malloc.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "../../common/mathlib.h"
#include "../../common/const.h"
#include "../../common/twm.h"
#include "studiotwm.h"
/*
==============================
SMD_Error
Print an error message
and return an error code
==============================
*/
int SMD_Error(int errid,char *pszStream,...)
{
va_list argptr;
char szString[MAX_STRLEN];
va_start(argptr,pszStream);
vsprintf(szString,pszStream,argptr);
va_end(argptr);
fprintf(stderr,szString);
return errid;
}
/*
==============================
SMD_AddTriangle
Add triangle to current ref set
==============================
*/
void SMD_AddTriangle(smdref_t *smdref,smdvertex_t *verts,char *texturename)
{
int index = smdref->num_triangles;
smdref->num_triangles++;
// copy memory
smdref->triangles = (smdtriangle_t*)realloc(smdref->triangles,sizeof(smdtriangle_t)*smdref->num_triangles);
memcpy(smdref->triangles[index].verts,verts,sizeof(smdvertex_t)*3);
strcpy(smdref->triangles[index].texturename,texturename);
}
/*
==============================
SMD_ParseTriangles
Read a triangle data block
Largely read from studiomdl.c Grab_Triangles
==============================
*/
void SMD_ParseTriangles(FILE *pFile,char *pszLine,smdref_t *smdref)
{
int i,j;
while(fgets(pszLine,sizeof(char)*MAX_STRLEN,pFile) != NULL)
{
smdvertex_t p[3];
char texturename[64];
int itrash;
float fltrash[3];
char *c;
// TODO: Remove when neccesary
fltrash[0] = 1 * 4;
// check for end
if(strcmp("end\n",pszLine) == 0)
return;
// strip off trailing smag
strcpy(texturename,pszLine);
for(i = strlen(texturename) - 1;i >= 0 && !isgraph(texturename[i]); i--)
texturename[i + 1] = '\0';
// strip off newline
c = strchr(texturename,'\n');
if(c != NULL)
c[0] = '\0';
// Skip blank triangles
if(texturename[0] == '\0')
{
fgets(pszLine,sizeof(char)*MAX_STRLEN,pFile);
fgets(pszLine,sizeof(char)*MAX_STRLEN,pFile);
fgets(pszLine,sizeof(char)*MAX_STRLEN,pFile);
continue;
}
// Read the triangle data
for(j = 0;j < 3;j++)
{
//TODO: Flip vertex order?
if(fgets(pszLine,sizeof(char)*MAX_STRLEN,pFile) != NULL)
{
// Alot of this crap .TWM doesnt use, so
// just throw it into trash vars
if(!(sscanf(pszLine, "%d %f %f %f %f %f %f %f %f",
&itrash,
&p[j].origin[0],&p[j].origin[1],&p[j].origin[2],
&fltrash[0],&fltrash[1],&fltrash[2],
&p[j].u,&p[j].v) == 9))
{
SMD_Error(-1,"ERROR: Invalid triangle format\n");
return;
}
else
{
// if needed rescale the verts
if(g_flScale != 1.0f)
{
p[j].origin[0] *= g_flScale;
p[j].origin[1] *= g_flScale;
p[j].origin[2] *= g_flScale;
}
}
}
}
// Plug values into smdref
SMD_AddTriangle(smdref,p,texturename);
}
}
/*
==============================
SMD_ParseSMD
Read a SMD file and return a new one
returns 0 if parse was not successful
==============================
*/
int SMD_ParseSMD(char *filename,smdref_t *smdref)
{
char szLine[MAX_STRLEN];
char szToken[MAX_STRLEN];
int iOption;
FILE *pFile = fopen(filename,"r");
if(pFile == NULL)
return SMD_Error(0,"ERROR: Invalid file %s\n",filename);
// Start parsing
while(fgets(szLine,sizeof(szLine),pFile) != NULL)
{
sscanf(szLine,"%s %d",szToken,&iOption);
if(strcmp("version",szToken) == 0)
{
if(iOption != 1)
{
// Bad version
fprintf(stderr,"ERROR: Invalid version %i\n",iOption);
goto parsesmd_error;
}
}
else if(strcmp("triangles",szToken) == 0)
{
SMD_ParseTriangles(pFile,szLine,smdref);
}
}
fclose(pFile);
return 1;
parsesmd_error:
fclose(pFile);
return 0;
}
/*
==============================
SMD_Initialize
Reset a smdref
==============================
*/
void SMD_Initialize(smdref_t *smdref)
{
// Triangles
smdref->num_triangles = 0;
smdref->triangles = NULL;
}
/*
==============================
SMD_Destroy
Destroy a smdref
==============================
*/
void SMD_Destroy(smdref_t *smdref)
{
if(smdref->num_triangles)
free(smdref->triangles);
}
/*
==============================
SMD_ConvertToTWM
Parse an SMD then create
a TWM from it
==============================
*/
void SMD_ConvertToTWM(char *filein,char *fileout)
{
int err_count = 0;
smdref_t smdref;
printf("Parsing [%s]...",filein);
SMD_Initialize(&smdref);
if(SMD_ParseSMD(filein,&smdref))
{
printf("Building [%s]...",fileout);
if(TWM_BuildFromSMD(fileout,&smdref))
printf("Done\n",fileout);
}
SMD_Destroy(&smdref);
}