READ_3DS.C 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /******************************************************************************
  2. Plush Version 1.2
  3. read_3ds.c
  4. 3DS Object Reader
  5. Copyright (c) 1996-2000, Justin Frankel
  6. ******************************************************************************/
  7. #include "plush.h"
  8. typedef struct {
  9. pl_uInt16 id;
  10. void (*func)(FILE *f, pl_uInt32 p);
  11. } _pl_3DSChunk;
  12. static pl_Obj *obj;
  13. static pl_Obj *bobj;
  14. static pl_Obj *lobj;
  15. static pl_sInt16 currentobj;
  16. static pl_Mat *_m;
  17. static pl_Float _pl3DSReadFloat(FILE *f);
  18. static pl_uInt32 _pl3DSReadDWord(FILE *f);
  19. static pl_uInt16 _pl3DSReadWord(FILE *f);
  20. static void _pl3DSChunkReader(FILE *f, pl_uInt32 p);
  21. static void _pl3DSRGBFReader(FILE *f, pl_uInt32 p);
  22. static void _pl3DSRGBBReader(FILE *f, pl_uInt32 p);
  23. static void _pl3DSASCIIZReader(FILE *f, pl_uInt32 p, char *as);
  24. static void _pl3DSObjBlockReader(FILE *f, pl_uInt32 p);
  25. static void _pl3DSTriMeshReader(FILE *f, pl_uInt32 p);
  26. static void _pl3DSVertListReader(FILE *f, pl_uInt32 p);
  27. static void _pl3DSFaceListReader(FILE *f, pl_uInt32 p);
  28. static void _pl3DSFaceMatReader(FILE *f, pl_uInt32 p);
  29. static void MapListReader(FILE *f, pl_uInt32 p);
  30. static pl_sInt16 _pl3DSFindChunk(pl_uInt16 id);
  31. static _pl_3DSChunk _pl3DSChunkNames[] = {
  32. {0x4D4D,NULL}, /* Main */
  33. {0x3D3D,NULL}, /* Object Mesh */
  34. {0x4000,_pl3DSObjBlockReader},
  35. {0x4100,_pl3DSTriMeshReader},
  36. {0x4110,_pl3DSVertListReader},
  37. {0x4120,_pl3DSFaceListReader},
  38. {0x4130,_pl3DSFaceMatReader},
  39. {0x4140,MapListReader},
  40. {0xAFFF,NULL}, /* Material */
  41. {0xA010,NULL}, /* Ambient */
  42. {0xA020,NULL}, /* Diff */
  43. {0xA030,NULL}, /* Specular */
  44. {0xA200,NULL}, /* Texture */
  45. {0x0010,_pl3DSRGBFReader},
  46. {0x0011,_pl3DSRGBBReader},
  47. };
  48. pl_Obj *plRead3DSObj(char *fn, pl_Mat *m) {
  49. FILE *f;
  50. pl_uInt32 p;
  51. _m = m;
  52. obj = bobj = lobj = 0;
  53. currentobj = 0;
  54. f = fopen(fn, "rb");
  55. if (!f) return 0;
  56. fseek(f, 0, 2);
  57. p = ftell(f);
  58. rewind(f);
  59. _pl3DSChunkReader(f, p);
  60. fclose(f);
  61. return bobj;
  62. }
  63. static pl_Float _pl3DSReadFloat(FILE *f) {
  64. pl_uInt32 *i;
  65. pl_IEEEFloat32 c;
  66. i = (pl_uInt32 *) &c;
  67. *i = _pl3DSReadDWord(f);
  68. return ((pl_Float) c);
  69. }
  70. static pl_uInt32 _pl3DSReadDWord(FILE *f) {
  71. pl_uInt32 r;
  72. r = fgetc(f);
  73. r |= fgetc(f)<<8;
  74. r |= fgetc(f)<<16;
  75. r |= fgetc(f)<<24;
  76. return r;
  77. }
  78. static pl_uInt16 _pl3DSReadWord(FILE *f) {
  79. pl_uInt16 r;
  80. r = fgetc(f);
  81. r |= fgetc(f)<<8;
  82. return r;
  83. }
  84. static void _pl3DSRGBFReader(FILE *f, pl_uInt32 p) {
  85. pl_Float c[3];
  86. c[0] = _pl3DSReadFloat(f);
  87. c[1] = _pl3DSReadFloat(f);
  88. c[2] = _pl3DSReadFloat(f);
  89. }
  90. static void _pl3DSRGBBReader(FILE *f, pl_uInt32 p) {
  91. unsigned char c[3];
  92. if (fread(&c, sizeof(c), 1, f) != 1) return;
  93. }
  94. static void _pl3DSASCIIZReader(FILE *f, pl_uInt32 p, char *as) {
  95. char c;
  96. if (!as) while ((c = fgetc(f)) != EOF && c != '\0');
  97. else {
  98. while ((c = fgetc(f)) != EOF && c != '\0') *as++ = c;
  99. *as = 0;
  100. }
  101. }
  102. static void _pl3DSObjBlockReader(FILE *f, pl_uInt32 p) {
  103. _pl3DSASCIIZReader(f,p,0);
  104. _pl3DSChunkReader(f, p);
  105. }
  106. static void _pl3DSTriMeshReader(FILE *f, pl_uInt32 p) {
  107. pl_uInt32 i;
  108. pl_Face *face;
  109. obj = plObjCreate(0,0);
  110. _pl3DSChunkReader(f, p);
  111. i = obj->NumFaces;
  112. face = obj->Faces;
  113. while (i--) {
  114. face->Vertices[0] = obj->Vertices + (pl_uInt32) face->Vertices[0];
  115. face->Vertices[1] = obj->Vertices + (pl_uInt32) face->Vertices[1];
  116. face->Vertices[2] = obj->Vertices + (pl_uInt32) face->Vertices[2];
  117. face->MappingU[0] = face->Vertices[0]->xformedx;
  118. face->MappingV[0] = face->Vertices[0]->xformedy;
  119. face->MappingU[1] = face->Vertices[1]->xformedx;
  120. face->MappingV[1] = face->Vertices[1]->xformedy;
  121. face->MappingU[2] = face->Vertices[2]->xformedx;
  122. face->MappingV[2] = face->Vertices[2]->xformedy;
  123. face++;
  124. }
  125. plObjCalcNormals(obj);
  126. if (currentobj == 0) {
  127. currentobj = 1;
  128. lobj = bobj = obj;
  129. } else {
  130. lobj->Children[0] = obj;
  131. lobj = obj;
  132. }
  133. }
  134. static void _pl3DSVertListReader(FILE *f, pl_uInt32 p) {
  135. pl_uInt16 nv;
  136. pl_Vertex *v;
  137. nv = _pl3DSReadWord(f);
  138. obj->NumVertices = nv;
  139. v = obj->Vertices = (pl_Vertex *) calloc(sizeof(pl_Vertex)*nv,1);
  140. while (nv--) {
  141. v->x = _pl3DSReadFloat(f);
  142. v->y = _pl3DSReadFloat(f);
  143. v->z = _pl3DSReadFloat(f);
  144. if (feof(f)) return;
  145. v++;
  146. }
  147. }
  148. static void _pl3DSFaceListReader(FILE *f, pl_uInt32 p) {
  149. pl_uInt16 nv;
  150. pl_uInt16 c[3];
  151. pl_uInt16 flags;
  152. pl_Face *face;
  153. nv = _pl3DSReadWord(f);
  154. obj->NumFaces = nv;
  155. face = obj->Faces = (pl_Face *) calloc(sizeof(pl_Face)*nv,1);
  156. while (nv--) {
  157. c[0] = _pl3DSReadWord(f);
  158. c[1] = _pl3DSReadWord(f);
  159. c[2] = _pl3DSReadWord(f);
  160. flags = _pl3DSReadWord(f);
  161. if (feof(f)) return;
  162. face->Vertices[0] = (pl_Vertex *) (c[0]&0x0000FFFF);
  163. face->Vertices[1] = (pl_Vertex *) (c[1]&0x0000FFFF);
  164. face->Vertices[2] = (pl_Vertex *) (c[2]&0x0000FFFF);
  165. face->Material = _m;
  166. face++;
  167. }
  168. _pl3DSChunkReader(f, p);
  169. }
  170. static void _pl3DSFaceMatReader(FILE *f, pl_uInt32 p) {
  171. pl_uInt16 n, nf;
  172. _pl3DSASCIIZReader(f, p,0);
  173. n = _pl3DSReadWord(f);
  174. while (n--) {
  175. nf = _pl3DSReadWord(f);
  176. }
  177. }
  178. static void MapListReader(FILE *f, pl_uInt32 p) {
  179. pl_uInt16 nv;
  180. pl_Float c[2];
  181. pl_Vertex *v;
  182. nv = _pl3DSReadWord(f);
  183. v = obj->Vertices;
  184. if (nv == obj->NumVertices) while (nv--) {
  185. c[0] = _pl3DSReadFloat(f);
  186. c[1] = _pl3DSReadFloat(f);
  187. if (feof(f)) return;
  188. v->xformedx = (pl_sInt32) (c[0]*65536.0);
  189. v->xformedy = (pl_sInt32) (c[1]*65536.0);
  190. v++;
  191. }
  192. }
  193. static pl_sInt16 _pl3DSFindChunk(pl_uInt16 id) {
  194. pl_sInt16 i;
  195. for (i = 0; i < sizeof(_pl3DSChunkNames)/sizeof(_pl3DSChunkNames[0]); i++)
  196. if (id == _pl3DSChunkNames[i].id) return i;
  197. return -1;
  198. }
  199. static void _pl3DSChunkReader(FILE *f, pl_uInt32 p) {
  200. pl_uInt32 hlen;
  201. pl_uInt16 hid;
  202. pl_sInt16 n;
  203. pl_uInt32 pc;
  204. while (ftell(f) < (int)p) {
  205. pc = ftell(f);
  206. hid = _pl3DSReadWord(f); if (feof(f)) return;
  207. hlen = _pl3DSReadDWord(f); if (feof(f)) return;
  208. if (hlen == 0) return;
  209. n = _pl3DSFindChunk(hid);
  210. if (n < 0) fseek(f, pc + hlen, 0);
  211. else {
  212. pc += hlen;
  213. if (_pl3DSChunkNames[n].func != NULL) _pl3DSChunkNames[n].func(f, pc);
  214. else _pl3DSChunkReader(f, pc);
  215. fseek(f, pc, 0);
  216. }
  217. if (ferror(f)) break;
  218. }
  219. }