forked from valve/halflife-sdk
356 lines
No EOL
8.7 KiB
C
356 lines
No EOL
8.7 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.
|
|
*
|
|
***/
|
|
//
|
|
// build a .twm file from the read .smd 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"
|
|
|
|
/*
|
|
==============================
|
|
TWM_AddTriToMaterialLump
|
|
|
|
==============================
|
|
*/
|
|
void TWM_AddTriToMaterialLump(twm_info_t *pTwm,int matindex,int trisindex,smdtriangle_t pTri,char *pszTextureName)
|
|
{
|
|
if(strcmp(pTri.texturename,pszTextureName) == 0)
|
|
{
|
|
pTwm->materialgroup_lump[matindex].num_triangles++;
|
|
|
|
// add triangle index to lump
|
|
pTwm->materialgroup_lump[matindex].tris_indices = realloc(pTwm->materialgroup_lump[matindex].tris_indices,sizeof(int)*pTwm->materialgroup_lump[matindex].num_triangles);
|
|
pTwm->materialgroup_lump[matindex].tris_indices[pTwm->materialgroup_lump[matindex].num_triangles-1] = trisindex;
|
|
}
|
|
}
|
|
|
|
/*
|
|
==============================
|
|
TWM_AddMaterial
|
|
|
|
If this is a unique material
|
|
add it to the list
|
|
==============================
|
|
*/
|
|
void TWM_AddMaterial(twm_info_t *pTwm,char *pszTextureName)
|
|
{
|
|
if(pTwm->num_materialgroups)
|
|
{
|
|
int i;
|
|
|
|
// If we already have this material, dont add it
|
|
for(i = 0;i < pTwm->num_materialgroups;i++)
|
|
if(strcmp(pTwm->materialgroup_lump[i].texturename,pszTextureName) == 0)
|
|
return;
|
|
}
|
|
|
|
pTwm->num_materialgroups++;
|
|
pTwm->materialgroup_lump = realloc(pTwm->materialgroup_lump,sizeof(twm_materialgroup_t)*pTwm->num_materialgroups);
|
|
|
|
strcpy(pTwm->materialgroup_lump[pTwm->num_materialgroups-1].texturename,pszTextureName);
|
|
pTwm->materialgroup_lump[pTwm->num_materialgroups-1].num_triangles = 0;
|
|
pTwm->materialgroup_lump[pTwm->num_materialgroups-1].tris_indices = NULL;
|
|
}
|
|
|
|
/*
|
|
==============================
|
|
TWM_WriteMaterialgroups
|
|
|
|
create material group data
|
|
and write to disk
|
|
==============================
|
|
*/
|
|
int TWM_WriteMaterialgroups(FILE *pFile,twm_info_t *pTwm,smdref_t *pSmd)
|
|
{
|
|
char *szExt;
|
|
char szTemp[64];
|
|
int i;
|
|
|
|
// Pass 1: Load all texture names into mem
|
|
for(i = 0;i < pSmd->num_triangles;i++)
|
|
TWM_AddMaterial(pTwm,pSmd->triangles[i].texturename);
|
|
|
|
// Pass 2: Put proper textures in the right indices
|
|
for(i = 0;i < pTwm->num_materialgroups;i++)
|
|
{
|
|
int j;
|
|
|
|
// Go through SMD listing one more time
|
|
// and put all matching triangles into the lump
|
|
for(j = 0;j < pSmd->num_triangles;j++)
|
|
TWM_AddTriToMaterialLump(pTwm,i,j,pSmd->triangles[j],pTwm->materialgroup_lump[i].texturename);
|
|
}
|
|
|
|
// Write material info to disk
|
|
fwrite((char*)&pTwm->num_materialgroups,sizeof(pTwm->num_materialgroups),1,pFile);
|
|
|
|
for(i = 0;i < pTwm->num_materialgroups;i++)
|
|
{
|
|
// We add the texture path here as well as
|
|
// rename .bmp to .spr
|
|
strcpy(szTemp,g_szTexturePath);
|
|
strcat(szTemp,pTwm->materialgroup_lump[i].texturename);
|
|
|
|
szExt = strstr(szTemp,".bmp");
|
|
strcpy(szExt,".spr");
|
|
|
|
// Copy back into material texture
|
|
strcpy(pTwm->materialgroup_lump[i].texturename,szTemp);
|
|
|
|
fwrite(pTwm->materialgroup_lump[i].texturename,sizeof(char)*64,1,pFile);
|
|
fwrite((char*)&pTwm->materialgroup_lump[i].num_triangles,sizeof(short),1,pFile);
|
|
fwrite((char*)pTwm->materialgroup_lump[i].tris_indices,sizeof(short)*pTwm->materialgroup_lump[i].num_triangles,1,pFile);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
==============================
|
|
TWM_GetIndexForVert
|
|
|
|
Go through vert index
|
|
looking for a matching vertex
|
|
==============================
|
|
*/
|
|
int TWM_GetIndexForVert(twm_info_t *pTwm,twm_vert_t vertex)
|
|
{
|
|
int i;
|
|
|
|
// Go through vertex list looking for
|
|
// a matching index
|
|
for(i = 0;i < pTwm->num_vertices;i++)
|
|
// Compare verts
|
|
if(memcmp(pTwm->vertex_lump[i],vertex,sizeof(twm_vert_t)) == 0)
|
|
return i;
|
|
|
|
return SMD_Error(-1,"ERROR: Invalid Vert Index\n");
|
|
}
|
|
|
|
/*
|
|
==============================
|
|
TWM_WriteTriangles
|
|
|
|
write triangle listings
|
|
to file
|
|
==============================
|
|
*/
|
|
int TWM_WriteTriangles(FILE *pFile,twm_info_t *pTwm,smdref_t *pSmd)
|
|
{
|
|
int i;
|
|
smdtriangle_t *pTriangle;
|
|
|
|
for(i = 0;i < pSmd->num_triangles;i++)
|
|
{
|
|
twm_triangle_t twmTri;
|
|
|
|
pTriangle = &pSmd->triangles[i];
|
|
|
|
// increment counter
|
|
pTwm->num_tris++;
|
|
|
|
// fill UV data
|
|
twmTri.u[0] = pTriangle->verts[0].u;
|
|
twmTri.v[0] = pTriangle->verts[0].v;
|
|
twmTri.u[1] = pTriangle->verts[1].u;
|
|
twmTri.v[1] = pTriangle->verts[1].v;
|
|
twmTri.u[2] = pTriangle->verts[2].u;
|
|
twmTri.v[2] = pTriangle->verts[2].v;
|
|
|
|
// get vert indices
|
|
twmTri.vert_indices[0] = TWM_GetIndexForVert(pTwm,pTriangle->verts[0].origin);
|
|
twmTri.vert_indices[1] = TWM_GetIndexForVert(pTwm,pTriangle->verts[1].origin);
|
|
twmTri.vert_indices[2] = TWM_GetIndexForVert(pTwm,pTriangle->verts[2].origin);
|
|
|
|
// Store triangle in mem
|
|
pTwm->triangle_lump = realloc(pTwm->triangle_lump,sizeof(twm_triangle_t)*pTwm->num_tris);
|
|
memcpy((char*)&pTwm->triangle_lump[pTwm->num_tris-1],(char*)&twmTri,sizeof(twm_triangle_t));
|
|
}
|
|
|
|
// Write triangles to disk
|
|
fwrite((char*)&pTwm->num_tris,sizeof(short),1,pFile);
|
|
|
|
// Write element by element
|
|
for(i = 0;i < pTwm->num_tris;i++)
|
|
{
|
|
twm_triangle_t *cur_tri = &pTwm->triangle_lump[i];
|
|
|
|
fwrite((char*)cur_tri->vert_indices,sizeof(short)*3,1,pFile);
|
|
fwrite((char*)cur_tri->u,sizeof(float)*3,1,pFile);
|
|
fwrite((char*)cur_tri->v,sizeof(float)*3,1,pFile);
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
==============================
|
|
TWM_AddVertexToModel
|
|
|
|
go through vertex listing,
|
|
if this is a unique vert,
|
|
add it.
|
|
==============================
|
|
*/
|
|
void TWM_AddVertexToModel(twm_info_t *pTwm,smdvertex_t vertex)
|
|
{
|
|
if(pTwm->num_vertices)
|
|
{
|
|
int j;
|
|
|
|
// Look through current vertex listing.
|
|
// If this vertex exists, dont add it
|
|
// again.
|
|
for(j = 0;j < pTwm->num_vertices;j++)
|
|
if(memcmp(pTwm->vertex_lump[j],vertex.origin,sizeof(twm_vert_t)) == 0)
|
|
return;
|
|
}
|
|
|
|
// add it
|
|
pTwm->num_vertices++;
|
|
pTwm->vertex_lump = realloc(pTwm->vertex_lump,sizeof(twm_vert_t)*pTwm->num_vertices);
|
|
memcpy(pTwm->vertex_lump[pTwm->num_vertices-1],vertex.origin,sizeof(twm_vert_t));
|
|
}
|
|
|
|
/*
|
|
==============================
|
|
TWM_WriteVertices
|
|
|
|
write all unique vertices
|
|
to file
|
|
==============================
|
|
*/
|
|
int TWM_WriteVertices(FILE *pFile,twm_info_t *pTwm,smdref_t *pSmd)
|
|
{
|
|
int i,j;
|
|
smdtriangle_t *pTriangle;
|
|
|
|
// Go through triangle listing
|
|
for(i = 0;i < pSmd->num_triangles;i++)
|
|
{
|
|
pTriangle = &pSmd->triangles[i];
|
|
|
|
// Read vertex listing
|
|
for(j = 0;j < 3;j++)
|
|
TWM_AddVertexToModel(pTwm,pTriangle->verts[j]);
|
|
}
|
|
|
|
// Write remaining verts to file
|
|
fwrite((char*)&pTwm->num_vertices,sizeof(short),1,pFile);
|
|
fwrite((char*)pTwm->vertex_lump,sizeof(twm_vert_t)*pTwm->num_vertices,1,pFile);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
==============================
|
|
TWM_WriteHeader
|
|
|
|
Initial TWM information
|
|
==============================
|
|
*/
|
|
int TWM_WriteHeader(FILE *pFile,twm_info_t *pModel)
|
|
{
|
|
pModel->header_id = TWM_ID;
|
|
pModel->major_version = TWM_MAJOR_VERSION;
|
|
pModel->minor_version = TWM_MINOR_VERSION;
|
|
|
|
// Write to disk
|
|
fwrite((char*)&pModel->header_id,sizeof(int),1,pFile);
|
|
fwrite((char*)&pModel->major_version,sizeof(short),1,pFile);
|
|
fwrite((char*)&pModel->minor_version,sizeof(short),1,pFile);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
==============================
|
|
TWM_Initialize
|
|
|
|
Reset a twm struct
|
|
==============================
|
|
*/
|
|
void TWM_Initialize(twm_info_t *pTwm)
|
|
{
|
|
pTwm->num_vertices = 0;
|
|
pTwm->vertex_lump = NULL;
|
|
|
|
pTwm->num_tris = 0;
|
|
pTwm->triangle_lump = NULL;
|
|
|
|
pTwm->num_materialgroups = 0;
|
|
pTwm->materialgroup_lump = NULL;
|
|
}
|
|
|
|
/*
|
|
==============================
|
|
TWM_Destroy
|
|
|
|
Reset data inside a twm model
|
|
==============================
|
|
*/
|
|
void TWM_Destroy(twm_info_t *pTwm)
|
|
{
|
|
if(pTwm->num_vertices)
|
|
free(pTwm->vertex_lump);
|
|
|
|
if(pTwm->num_tris)
|
|
free(pTwm->triangle_lump);
|
|
|
|
if(pTwm->num_materialgroups);
|
|
{
|
|
int i;
|
|
|
|
for(i = 0;i < pTwm->num_materialgroups;i++)
|
|
free(pTwm->materialgroup_lump[i].tris_indices);
|
|
|
|
free(pTwm->materialgroup_lump);
|
|
}
|
|
}
|
|
|
|
/*
|
|
==============================
|
|
TWM_BuildFromSMD
|
|
|
|
Convert SMD data
|
|
into a usable .twm file
|
|
==============================
|
|
*/
|
|
int TWM_BuildFromSMD(char *filename,smdref_t *smdref)
|
|
{
|
|
twm_info_t twmmodel;
|
|
FILE *pFile = fopen(filename,"wb");
|
|
|
|
if(pFile == NULL)
|
|
return SMD_Error(0,"ERROR: Could not open %s\n",filename);
|
|
|
|
TWM_Initialize(&twmmodel);
|
|
|
|
TWM_WriteHeader(pFile,&twmmodel);
|
|
TWM_WriteVertices(pFile,&twmmodel,smdref);
|
|
TWM_WriteTriangles(pFile,&twmmodel,smdref);
|
|
TWM_WriteMaterialgroups(pFile,&twmmodel,smdref);
|
|
|
|
TWM_Destroy(&twmmodel);
|
|
|
|
fclose(pFile);
|
|
return 1;
|
|
} |