halflife-thewastes-sdk/utils/studiotwm/buildtwm.c
2023-09-06 03:27:45 +03:00

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;
}