--- /dev/null
+/*\r
+Copyright (C) 1999-2007 id Software, Inc. and contributors.\r
+For a list of contributors, see the accompanying CONTRIBUTORS file.\r
+\r
+This file is part of GtkRadiant.\r
+\r
+GtkRadiant is free software; you can redistribute it and/or modify\r
+it under the terms of the GNU General Public License as published by\r
+the Free Software Foundation; either version 2 of the License, or\r
+(at your option) any later version.\r
+\r
+GtkRadiant is distributed in the hope that it will be useful,\r
+but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+GNU General Public License for more details.\r
+\r
+You should have received a copy of the GNU General Public License\r
+along with GtkRadiant; if not, write to the Free Software\r
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA\r
+*/\r
+\r
+//\r
+// l3dslib.c: library for loading triangles from an Alias triangle file\r
+//\r
+\r
+#include <stdio.h>\r
+#include "cmdlib.h"\r
+#include "inout.h"\r
+#include "mathlib.h"\r
+#include "trilib.h"\r
+#include "l3dslib.h"\r
+#include "token.h"\r
+#include "fmodel.h"\r
+#include "bspfile.h"\r
+\r
+#define MAIN3DS 0x4D4D\r
+#define EDIT3DS 0x3D3D // this is the start of the editor config\r
+#define EDIT_OBJECT 0x4000\r
+#define OBJ_TRIMESH 0x4100\r
+#define TRI_VERTEXL 0x4110\r
+#define TRI_FACEL1 0x4120\r
+\r
+#define MAXVERTS 2000\r
+\r
+typedef struct {\r
+ int v[4];\r
+} tri;\r
+\r
+float fverts[MAXVERTS][3];\r
+tri tris[MAXTRIANGLES];\r
+\r
+int bytesread, level, numtris, totaltris;\r
+int vertsfound, trisfound;\r
+\r
+triangle_t *ptri;\r
+\r
+\r
+\r
+void DefaultNodesList(mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles)\r
+{\r
+ int pos, bit, i;\r
+\r
+ if (nodesList)\r
+ {\r
+ *num_mesh_nodes = 1;\r
+ memset(&(*nodesList)[0], 0, sizeof(mesh_node_t));\r
+ strcpy((*nodesList)[0].name, "default");\r
+\r
+ // set all of the tris to be used for the top node\r
+ for(i = 0; i < (*numtriangles); i++)\r
+ {\r
+ pos = (i) >> 3;\r
+ bit = 1 << ((i) & 7 );\r
+\r
+ (*nodesList)[0].tris[pos] |= bit;\r
+ }\r
+ }\r
+}\r
+\r
+\r
+// Alias stores triangles as 3 explicit vertices in .tri files, so even though we\r
+// start out with a vertex pool and vertex indices for triangles, we have to convert\r
+// to raw, explicit triangles\r
+void StoreAliasTriangles (void)\r
+{\r
+ int i, j, k;\r
+\r
+ if ((totaltris + numtris) > MAXTRIANGLES)\r
+ Error ("Error: Too many triangles");\r
+\r
+ for (i=0; i<numtris ; i++)\r
+ {\r
+ for (j=0 ; j<3 ; j++)\r
+ {\r
+ for (k=0 ; k<3 ; k++)\r
+ {\r
+ ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];\r
+ }\r
+ }\r
+ }\r
+ \r
+ totaltris += numtris;\r
+ numtris = 0;\r
+ vertsfound = 0;\r
+ trisfound = 0;\r
+}\r
+\r
+\r
+int ParseVertexL (FILE *input)\r
+{\r
+ int i, j, startbytesread, numverts;\r
+ unsigned short tshort;\r
+\r
+ if (vertsfound)\r
+ Error ("Error: Multiple vertex chunks");\r
+\r
+ vertsfound = 1;\r
+ startbytesread = bytesread;\r
+\r
+ if (feof(input))\r
+ Error ("Error: unexpected end of file");\r
+\r
+ fread(&tshort, sizeof(tshort), 1, input);\r
+ bytesread += sizeof(tshort);\r
+ numverts = (int)tshort;\r
+\r
+ if (numverts > MAXVERTS)\r
+ Error ("Error: Too many vertices");\r
+\r
+ for (i=0 ; i<numverts ; i++)\r
+ {\r
+ for (j=0 ; j<3 ; j++)\r
+ {\r
+ if (feof(input))\r
+ Error ("Error: unexpected end of file");\r
+\r
+ fread(&fverts[i][j], sizeof(float), 1, input);\r
+ bytesread += sizeof(float);\r
+ }\r
+ }\r
+\r
+ if (vertsfound && trisfound)\r
+ StoreAliasTriangles ();\r
+\r
+ return bytesread - startbytesread;\r
+}\r
+\r
+\r
+int ParseFaceL1 (FILE *input)\r
+{\r
+\r
+ int i, j, startbytesread;\r
+ unsigned short tshort;\r
+\r
+ if (trisfound)\r
+ Error ("Error: Multiple face chunks");\r
+\r
+ trisfound = 1;\r
+ startbytesread = bytesread;\r
+\r
+ if (feof(input))\r
+ Error ("Error: unexpected end of file");\r
+\r
+ fread(&tshort, sizeof(tshort), 1, input);\r
+ bytesread += sizeof(tshort);\r
+ numtris = (int)tshort;\r
+\r
+ if (numtris > MAXTRIANGLES)\r
+ Error ("Error: Too many triangles");\r
+\r
+ for (i=0 ; i<numtris ; i++)\r
+ {\r
+ for (j=0 ; j<4 ; j++)\r
+ {\r
+ if (feof(input))\r
+ Error ("Error: unexpected end of file");\r
+\r
+ fread(&tshort, sizeof(tshort), 1, input);\r
+ bytesread += sizeof(tshort);\r
+ tris[i].v[j] = (int)tshort;\r
+ }\r
+ }\r
+\r
+ if (vertsfound && trisfound)\r
+ StoreAliasTriangles ();\r
+\r
+ return bytesread - startbytesread;\r
+}\r
+\r
+\r
+int ParseChunk (FILE *input)\r
+{\r
+#define BLOCK_SIZE 4096\r
+ char temp[BLOCK_SIZE];\r
+ unsigned short type;\r
+ int i, length, w, t, retval;\r
+\r
+ level++;\r
+ retval = 0;\r
+\r
+// chunk type\r
+ if (feof(input))\r
+ Error ("Error: unexpected end of file");\r
+\r
+ fread(&type, sizeof(type), 1, input);\r
+ bytesread += sizeof(type);\r
+\r
+// chunk length\r
+ if (feof(input))\r
+ Error ("Error: unexpected end of file");\r
+\r
+ fread (&length, sizeof(length), 1, input);\r
+ bytesread += sizeof(length);\r
+ w = length - 6;\r
+\r
+// process chunk if we care about it, otherwise skip it\r
+ switch (type)\r
+ {\r
+ case TRI_VERTEXL:\r
+ w -= ParseVertexL (input);\r
+ goto ParseSubchunk;\r
+\r
+ case TRI_FACEL1:\r
+ w -= ParseFaceL1 (input);\r
+ goto ParseSubchunk;\r
+\r
+ case EDIT_OBJECT:\r
+ // read the name\r
+ i = 0;\r
+\r
+ do\r
+ {\r
+ if (feof(input))\r
+ Error ("Error: unexpected end of file");\r
+\r
+ fread (&temp[i], 1, 1, input);\r
+ i++;\r
+ w--;\r
+ bytesread++;\r
+ } while (temp[i-1]);\r
+\r
+ case MAIN3DS:\r
+ case OBJ_TRIMESH:\r
+ case EDIT3DS:\r
+ // parse through subchunks\r
+ParseSubchunk:\r
+ while (w > 0)\r
+ {\r
+ w -= ParseChunk (input);\r
+ }\r
+\r
+ retval = length;\r
+ goto Done;\r
+\r
+ default:\r
+ // skip other chunks\r
+ while (w > 0)\r
+ {\r
+ t = w;\r
+\r
+ if (t > BLOCK_SIZE)\r
+ t = BLOCK_SIZE;\r
+\r
+ if (feof(input))\r
+ Error ("Error: unexpected end of file");\r
+\r
+ fread (&temp, t, 1, input);\r
+ bytesread += t;\r
+\r
+ w -= t;\r
+ }\r
+\r
+ retval = length;\r
+ goto Done;\r
+ }\r
+\r
+Done:\r
+ level--;\r
+ return retval;\r
+}\r
+\r
+\r
+void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes)\r
+{\r
+ FILE *input;\r
+ short int tshort;\r
+\r
+ if (nodesList)\r
+ {\r
+ *num_mesh_nodes = 0;\r
+ *nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");\r
+ }\r
+\r
+ bytesread = 0;\r
+ level = 0;\r
+ numtris = 0;\r
+ totaltris = 0;\r
+ vertsfound = 0;\r
+ trisfound = 0;\r
+\r
+ if ((input = fopen(filename, "rb")) == 0) {\r
+ fprintf(stderr,"reader: could not open file '%s'\n", filename);\r
+ exit(0);\r
+ }\r
+\r
+ fread(&tshort, sizeof(tshort), 1, input);\r
+\r
+// should only be MAIN3DS, but some files seem to start with EDIT3DS, with\r
+// no MAIN3DS\r
+ if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {\r
+ fprintf(stderr,"File is not a 3DS file.\n");\r
+ exit(0);\r
+ }\r
+\r
+// back to top of file so we can parse the first chunk descriptor\r
+ fseek(input, 0, SEEK_SET);\r
+\r
+ ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));\r
+\r
+ *pptri = ptri;\r
+\r
+// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |\r
+// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks\r
+ ParseChunk (input);\r
+\r
+ if (vertsfound || trisfound)\r
+ Error ("Incomplete triangle set");\r
+\r
+ *numtriangles = totaltris;\r
+\r
+ fclose (input);\r
+\r
+ DefaultNodesList(nodesList,num_mesh_nodes,numtriangles);\r
+}\r
+\r
+//==========================================================================\r
+//\r
+// LoadASC\r
+//\r
+//==========================================================================\r
+\r
+void LoadASC(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)\r
+{\r
+ int i, j;\r
+ int vertexCount;\r
+ struct\r
+ {\r
+ float v[3];\r
+ } *vList;\r
+ int triCount;\r
+ triangle_t *tList;\r
+ float x, y, z;\r
+// float x2, y2, z2;\r
+// float rx, ry, rz;\r
+ qboolean goodObject;\r
+\r
+ if (nodesList)\r
+ {\r
+ *num_mesh_nodes = 0;\r
+ *nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");\r
+ }\r
+\r
+ TK_OpenSource(fileName);\r
+\r
+ goodObject = false;\r
+ while(goodObject == false)\r
+ {\r
+ TK_Beyond(TK_C_NAMED);\r
+ TK_Beyond(TK_OBJECT);\r
+ TK_Beyond(TK_C_TRI);\r
+ TK_Beyond(TK_MESH);\r
+ TK_BeyondRequire(TK_C_VERTICES, TK_COLON);\r
+ TK_FetchRequire(TK_INTNUMBER);\r
+ vertexCount = tk_IntNumber;\r
+ if(vertexCount > 0)\r
+ {\r
+ goodObject = true;\r
+ }\r
+ }\r
+ TK_BeyondRequire(TK_C_FACES, TK_COLON);\r
+ TK_FetchRequire(TK_INTNUMBER);\r
+ triCount = tk_IntNumber;\r
+ if(triCount >= MAXTRIANGLES)\r
+ {\r
+ Error("Too many triangles in file %s\n", fileName);\r
+ }\r
+ *triangleCount = triCount;\r
+ tList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");\r
+ *triList = tList;\r
+\r
+ memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));\r
+ TK_BeyondRequire(TK_C_VERTEX, TK_LIST);\r
+\r
+/* rx = ((rotation[0]+90.0)/360.0)*2.0*M_PI;\r
+ //rx = (rotation[0]/360.0)*2.0*M_PI;\r
+ ry = (rotation[1]/360.0)*2.0*M_PI;\r
+ rz = (rotation[2]/360.0)*2.0*M_PI;\r
+*/\r
+ vList = (void *) SafeMalloc(vertexCount*sizeof vList[0], "Vertex list");\r
+ for(i = 0; i < vertexCount; i++)\r
+ {\r
+ TK_BeyondRequire(TK_C_VERTEX, TK_INTNUMBER);\r
+ if(tk_IntNumber != i)\r
+ {\r
+ Error("File '%s', line %d:\nVertex index mismatch.\n",\r
+ tk_SourceName, tk_Line);\r
+ }\r
+ TK_FetchRequireFetch(TK_COLON);\r
+\r
+ TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);\r
+ x = tk_FloatNumber;\r
+ TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);\r
+ y = tk_FloatNumber;\r
+ TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);\r
+ z = tk_FloatNumber;\r
+\r
+/* x2 = x*cos(rz)+y*sin(rz);\r
+ y2 = -x*sin(rz)+y*cos(rz);\r
+ x = x2;\r
+ y = y2;\r
+ y2 = y*cos(rx)+z*sin(rx);\r
+ z2 = -y*sin(rx)+z*cos(rx);\r
+ y = y2;\r
+ z = z2;\r
+ x2 = x*cos(ry)-z*sin(ry);\r
+ z2 = x*sin(ry)+z*cos(ry);\r
+ x = x2;\r
+ z = z2;\r
+*/\r
+ vList[i].v[0] = x;\r
+ vList[i].v[1] = y;\r
+ vList[i].v[2] = z;\r
+ }\r
+ TK_BeyondRequire(TK_C_FACE, TK_LIST);\r
+ for(i = 0; i < triCount; i++)\r
+ {\r
+ TK_BeyondRequire(TK_C_FACE, TK_INTNUMBER);\r
+ if(tk_IntNumber != i)\r
+ {\r
+ Error("File '%s', line %d:\nTriangle index mismatch.\n",\r
+ tk_SourceName, tk_Line);\r
+ }\r
+ for(j = 0; j < 3; j++)\r
+ {\r
+ TK_BeyondRequire(TK_IDENTIFIER, TK_COLON);\r
+ TK_FetchRequire(TK_INTNUMBER);\r
+ if(tk_IntNumber >= vertexCount)\r
+ {\r
+ Error("File '%s', line %d:\nVertex number"\r
+ " > vertexCount: %d\n", tk_SourceName, tk_Line,\r
+ tk_IntNumber);\r
+ }\r
+ tList[i].verts[2-j][0] = vList[tk_IntNumber].v[0];\r
+ tList[i].verts[2-j][1] = vList[tk_IntNumber].v[1];\r
+ tList[i].verts[2-j][2] = vList[tk_IntNumber].v[2];\r
+#ifdef _QDATA\r
+ tList[i].indicies[2-j] = tk_IntNumber;\r
+#endif\r
+ }\r
+\r
+/* printf("Face %i:\n v0: %f, %f, %f\n v1: %f, %f, %f\n"\r
+ " v2: %f, %f, %f\n", i,\r
+ tList[i].verts[0][0],\r
+ tList[i].verts[0][1],\r
+ tList[i].verts[0][2],\r
+ tList[i].verts[1][0],\r
+ tList[i].verts[1][1],\r
+ tList[i].verts[1][2],\r
+ tList[i].verts[2][0],\r
+ tList[i].verts[2][1],\r
+ tList[i].verts[2][2]);\r
+*/\r
+ }\r
+\r
+ DefaultNodesList(nodesList,num_mesh_nodes,triangleCount);\r
+}\r