/*** * * 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 #include #include #include #include #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; }