l3dslib.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1997-2006 Id Software, Inc.
  4. This file is part of Quake 2 Tools source code.
  5. Quake 2 Tools source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake 2 Tools source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Quake 2 Tools source code; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. //
  19. // l3dslib.c: library for loading triangles from an Alias triangle file
  20. //
  21. #include <stdio.h>
  22. #include "cmdlib.h"
  23. #include "mathlib.h"
  24. #include "trilib.h"
  25. #include "l3dslib.h"
  26. #define MAIN3DS 0x4D4D
  27. #define EDIT3DS 0x3D3D // this is the start of the editor config
  28. #define EDIT_OBJECT 0x4000
  29. #define OBJ_TRIMESH 0x4100
  30. #define TRI_VERTEXL 0x4110
  31. #define TRI_FACEL1 0x4120
  32. #define MAXVERTS 2000
  33. typedef struct {
  34. int v[4];
  35. } tri;
  36. float fverts[MAXVERTS][3];
  37. tri tris[MAXTRIANGLES];
  38. int bytesread, level, numtris, totaltris;
  39. int vertsfound, trisfound;
  40. triangle_t *ptri;
  41. // Alias stores triangles as 3 explicit vertices in .tri files, so even though we
  42. // start out with a vertex pool and vertex indices for triangles, we have to convert
  43. // to raw, explicit triangles
  44. void StoreAliasTriangles (void)
  45. {
  46. int i, j, k;
  47. if ((totaltris + numtris) > MAXTRIANGLES)
  48. Error ("Error: Too many triangles");
  49. for (i=0; i<numtris ; i++)
  50. {
  51. for (j=0 ; j<3 ; j++)
  52. {
  53. for (k=0 ; k<3 ; k++)
  54. {
  55. ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
  56. }
  57. }
  58. }
  59. totaltris += numtris;
  60. numtris = 0;
  61. vertsfound = 0;
  62. trisfound = 0;
  63. }
  64. int ParseVertexL (FILE *input)
  65. {
  66. int i, j, startbytesread, numverts;
  67. unsigned short tshort;
  68. if (vertsfound)
  69. Error ("Error: Multiple vertex chunks");
  70. vertsfound = 1;
  71. startbytesread = bytesread;
  72. if (feof(input))
  73. Error ("Error: unexpected end of file");
  74. fread(&tshort, sizeof(tshort), 1, input);
  75. bytesread += sizeof(tshort);
  76. numverts = (int)tshort;
  77. if (numverts > MAXVERTS)
  78. Error ("Error: Too many vertices");
  79. for (i=0 ; i<numverts ; i++)
  80. {
  81. for (j=0 ; j<3 ; j++)
  82. {
  83. if (feof(input))
  84. Error ("Error: unexpected end of file");
  85. fread(&fverts[i][j], sizeof(float), 1, input);
  86. bytesread += sizeof(float);
  87. }
  88. }
  89. if (vertsfound && trisfound)
  90. StoreAliasTriangles ();
  91. return bytesread - startbytesread;
  92. }
  93. int ParseFaceL1 (FILE *input)
  94. {
  95. int i, j, startbytesread;
  96. unsigned short tshort;
  97. if (trisfound)
  98. Error ("Error: Multiple face chunks");
  99. trisfound = 1;
  100. startbytesread = bytesread;
  101. if (feof(input))
  102. Error ("Error: unexpected end of file");
  103. fread(&tshort, sizeof(tshort), 1, input);
  104. bytesread += sizeof(tshort);
  105. numtris = (int)tshort;
  106. if (numtris > MAXTRIANGLES)
  107. Error ("Error: Too many triangles");
  108. for (i=0 ; i<numtris ; i++)
  109. {
  110. for (j=0 ; j<4 ; j++)
  111. {
  112. if (feof(input))
  113. Error ("Error: unexpected end of file");
  114. fread(&tshort, sizeof(tshort), 1, input);
  115. bytesread += sizeof(tshort);
  116. tris[i].v[j] = (int)tshort;
  117. }
  118. }
  119. if (vertsfound && trisfound)
  120. StoreAliasTriangles ();
  121. return bytesread - startbytesread;
  122. }
  123. int ParseChunk (FILE *input)
  124. {
  125. #define BLOCK_SIZE 4096
  126. char temp[BLOCK_SIZE];
  127. unsigned short type;
  128. int i, length, w, t, retval;
  129. level++;
  130. retval = 0;
  131. // chunk type
  132. if (feof(input))
  133. Error ("Error: unexpected end of file");
  134. fread(&type, sizeof(type), 1, input);
  135. bytesread += sizeof(type);
  136. // chunk length
  137. if (feof(input))
  138. Error ("Error: unexpected end of file");
  139. fread (&length, sizeof(length), 1, input);
  140. bytesread += sizeof(length);
  141. w = length - 6;
  142. // process chunk if we care about it, otherwise skip it
  143. switch (type)
  144. {
  145. case TRI_VERTEXL:
  146. w -= ParseVertexL (input);
  147. goto ParseSubchunk;
  148. case TRI_FACEL1:
  149. w -= ParseFaceL1 (input);
  150. goto ParseSubchunk;
  151. case EDIT_OBJECT:
  152. // read the name
  153. i = 0;
  154. do
  155. {
  156. if (feof(input))
  157. Error ("Error: unexpected end of file");
  158. fread (&temp[i], 1, 1, input);
  159. i++;
  160. w--;
  161. bytesread++;
  162. } while (temp[i-1]);
  163. case MAIN3DS:
  164. case OBJ_TRIMESH:
  165. case EDIT3DS:
  166. // parse through subchunks
  167. ParseSubchunk:
  168. while (w > 0)
  169. {
  170. w -= ParseChunk (input);
  171. }
  172. retval = length;
  173. goto Done;
  174. default:
  175. // skip other chunks
  176. while (w > 0)
  177. {
  178. t = w;
  179. if (t > BLOCK_SIZE)
  180. t = BLOCK_SIZE;
  181. if (feof(input))
  182. Error ("Error: unexpected end of file");
  183. fread (&temp, t, 1, input);
  184. bytesread += t;
  185. w -= t;
  186. }
  187. retval = length;
  188. goto Done;
  189. }
  190. Done:
  191. level--;
  192. return retval;
  193. }
  194. void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles)
  195. {
  196. FILE *input;
  197. short int tshort;
  198. bytesread = 0;
  199. level = 0;
  200. numtris = 0;
  201. totaltris = 0;
  202. vertsfound = 0;
  203. trisfound = 0;
  204. if ((input = fopen(filename, "rb")) == 0) {
  205. fprintf(stderr,"reader: could not open file '%s'\n", filename);
  206. exit(0);
  207. }
  208. fread(&tshort, sizeof(tshort), 1, input);
  209. // should only be MAIN3DS, but some files seem to start with EDIT3DS, with
  210. // no MAIN3DS
  211. if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
  212. fprintf(stderr,"File is not a 3DS file.\n");
  213. exit(0);
  214. }
  215. // back to top of file so we can parse the first chunk descriptor
  216. fseek(input, 0, SEEK_SET);
  217. ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
  218. *pptri = ptri;
  219. // parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
  220. // OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
  221. ParseChunk (input);
  222. if (vertsfound || trisfound)
  223. Error ("Incomplete triangle set");
  224. *numtriangles = totaltris;
  225. fclose (input);
  226. }