l3dslib.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena 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 III Arena 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 Foobar; 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. }