123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- /******************************************************************************
- Plush Version 1.2
- read_3ds.c
- 3DS Object Reader
- Copyright (c) 1996-2000, Justin Frankel
- ******************************************************************************/
- #include "plush.h"
- typedef struct {
- pl_uInt16 id;
- void (*func)(FILE *f, pl_uInt32 p);
- } _pl_3DSChunk;
- static pl_Obj *obj;
- static pl_Obj *bobj;
- static pl_Obj *lobj;
- static pl_sInt16 currentobj;
- static pl_Mat *_m;
- static pl_Float _pl3DSReadFloat(FILE *f);
- static pl_uInt32 _pl3DSReadDWord(FILE *f);
- static pl_uInt16 _pl3DSReadWord(FILE *f);
- static void _pl3DSChunkReader(FILE *f, pl_uInt32 p);
- static void _pl3DSRGBFReader(FILE *f, pl_uInt32 p);
- static void _pl3DSRGBBReader(FILE *f, pl_uInt32 p);
- static void _pl3DSASCIIZReader(FILE *f, pl_uInt32 p, char *as);
- static void _pl3DSObjBlockReader(FILE *f, pl_uInt32 p);
- static void _pl3DSTriMeshReader(FILE *f, pl_uInt32 p);
- static void _pl3DSVertListReader(FILE *f, pl_uInt32 p);
- static void _pl3DSFaceListReader(FILE *f, pl_uInt32 p);
- static void _pl3DSFaceMatReader(FILE *f, pl_uInt32 p);
- static void MapListReader(FILE *f, pl_uInt32 p);
- static pl_sInt16 _pl3DSFindChunk(pl_uInt16 id);
- static _pl_3DSChunk _pl3DSChunkNames[] = {
- {0x4D4D,NULL}, /* Main */
- {0x3D3D,NULL}, /* Object Mesh */
- {0x4000,_pl3DSObjBlockReader},
- {0x4100,_pl3DSTriMeshReader},
- {0x4110,_pl3DSVertListReader},
- {0x4120,_pl3DSFaceListReader},
- {0x4130,_pl3DSFaceMatReader},
- {0x4140,MapListReader},
- {0xAFFF,NULL}, /* Material */
- {0xA010,NULL}, /* Ambient */
- {0xA020,NULL}, /* Diff */
- {0xA030,NULL}, /* Specular */
- {0xA200,NULL}, /* Texture */
- {0x0010,_pl3DSRGBFReader},
- {0x0011,_pl3DSRGBBReader},
- };
- pl_Obj *plRead3DSObj(char *fn, pl_Mat *m) {
- FILE *f;
- pl_uInt32 p;
- _m = m;
- obj = bobj = lobj = 0;
- currentobj = 0;
- f = fopen(fn, "rb");
- if (!f) return 0;
- fseek(f, 0, 2);
- p = ftell(f);
- rewind(f);
- _pl3DSChunkReader(f, p);
- fclose(f);
- return bobj;
- }
- static pl_Float _pl3DSReadFloat(FILE *f) {
- pl_uInt32 *i;
- pl_IEEEFloat32 c;
- i = (pl_uInt32 *) &c;
- *i = _pl3DSReadDWord(f);
- return ((pl_Float) c);
- }
- static pl_uInt32 _pl3DSReadDWord(FILE *f) {
- pl_uInt32 r;
- r = fgetc(f);
- r |= fgetc(f)<<8;
- r |= fgetc(f)<<16;
- r |= fgetc(f)<<24;
- return r;
- }
- static pl_uInt16 _pl3DSReadWord(FILE *f) {
- pl_uInt16 r;
- r = fgetc(f);
- r |= fgetc(f)<<8;
- return r;
- }
- static void _pl3DSRGBFReader(FILE *f, pl_uInt32 p) {
- pl_Float c[3];
- c[0] = _pl3DSReadFloat(f);
- c[1] = _pl3DSReadFloat(f);
- c[2] = _pl3DSReadFloat(f);
- }
- static void _pl3DSRGBBReader(FILE *f, pl_uInt32 p) {
- unsigned char c[3];
- if (fread(&c, sizeof(c), 1, f) != 1) return;
- }
- static void _pl3DSASCIIZReader(FILE *f, pl_uInt32 p, char *as) {
- char c;
- if (!as) while ((c = fgetc(f)) != EOF && c != '\0');
- else {
- while ((c = fgetc(f)) != EOF && c != '\0') *as++ = c;
- *as = 0;
- }
- }
- static void _pl3DSObjBlockReader(FILE *f, pl_uInt32 p) {
- _pl3DSASCIIZReader(f,p,0);
- _pl3DSChunkReader(f, p);
- }
- static void _pl3DSTriMeshReader(FILE *f, pl_uInt32 p) {
- pl_uInt32 i;
- pl_Face *face;
- obj = plObjCreate(0,0);
- _pl3DSChunkReader(f, p);
- i = obj->NumFaces;
- face = obj->Faces;
- while (i--) {
- face->Vertices[0] = obj->Vertices + (pl_uInt32) face->Vertices[0];
- face->Vertices[1] = obj->Vertices + (pl_uInt32) face->Vertices[1];
- face->Vertices[2] = obj->Vertices + (pl_uInt32) face->Vertices[2];
- face->MappingU[0] = face->Vertices[0]->xformedx;
- face->MappingV[0] = face->Vertices[0]->xformedy;
- face->MappingU[1] = face->Vertices[1]->xformedx;
- face->MappingV[1] = face->Vertices[1]->xformedy;
- face->MappingU[2] = face->Vertices[2]->xformedx;
- face->MappingV[2] = face->Vertices[2]->xformedy;
- face++;
- }
- plObjCalcNormals(obj);
- if (currentobj == 0) {
- currentobj = 1;
- lobj = bobj = obj;
- } else {
- lobj->Children[0] = obj;
- lobj = obj;
- }
- }
- static void _pl3DSVertListReader(FILE *f, pl_uInt32 p) {
- pl_uInt16 nv;
- pl_Vertex *v;
- nv = _pl3DSReadWord(f);
- obj->NumVertices = nv;
- v = obj->Vertices = (pl_Vertex *) calloc(sizeof(pl_Vertex)*nv,1);
- while (nv--) {
- v->x = _pl3DSReadFloat(f);
- v->y = _pl3DSReadFloat(f);
- v->z = _pl3DSReadFloat(f);
- if (feof(f)) return;
- v++;
- }
- }
- static void _pl3DSFaceListReader(FILE *f, pl_uInt32 p) {
- pl_uInt16 nv;
- pl_uInt16 c[3];
- pl_uInt16 flags;
- pl_Face *face;
- nv = _pl3DSReadWord(f);
- obj->NumFaces = nv;
- face = obj->Faces = (pl_Face *) calloc(sizeof(pl_Face)*nv,1);
- while (nv--) {
- c[0] = _pl3DSReadWord(f);
- c[1] = _pl3DSReadWord(f);
- c[2] = _pl3DSReadWord(f);
- flags = _pl3DSReadWord(f);
- if (feof(f)) return;
- face->Vertices[0] = (pl_Vertex *) (c[0]&0x0000FFFF);
- face->Vertices[1] = (pl_Vertex *) (c[1]&0x0000FFFF);
- face->Vertices[2] = (pl_Vertex *) (c[2]&0x0000FFFF);
- face->Material = _m;
- face++;
- }
- _pl3DSChunkReader(f, p);
- }
- static void _pl3DSFaceMatReader(FILE *f, pl_uInt32 p) {
- pl_uInt16 n, nf;
- _pl3DSASCIIZReader(f, p,0);
- n = _pl3DSReadWord(f);
- while (n--) {
- nf = _pl3DSReadWord(f);
- }
- }
- static void MapListReader(FILE *f, pl_uInt32 p) {
- pl_uInt16 nv;
- pl_Float c[2];
- pl_Vertex *v;
- nv = _pl3DSReadWord(f);
- v = obj->Vertices;
- if (nv == obj->NumVertices) while (nv--) {
- c[0] = _pl3DSReadFloat(f);
- c[1] = _pl3DSReadFloat(f);
- if (feof(f)) return;
- v->xformedx = (pl_sInt32) (c[0]*65536.0);
- v->xformedy = (pl_sInt32) (c[1]*65536.0);
- v++;
- }
- }
- static pl_sInt16 _pl3DSFindChunk(pl_uInt16 id) {
- pl_sInt16 i;
- for (i = 0; i < sizeof(_pl3DSChunkNames)/sizeof(_pl3DSChunkNames[0]); i++)
- if (id == _pl3DSChunkNames[i].id) return i;
- return -1;
- }
- static void _pl3DSChunkReader(FILE *f, pl_uInt32 p) {
- pl_uInt32 hlen;
- pl_uInt16 hid;
- pl_sInt16 n;
- pl_uInt32 pc;
- while (ftell(f) < (int)p) {
- pc = ftell(f);
- hid = _pl3DSReadWord(f); if (feof(f)) return;
- hlen = _pl3DSReadDWord(f); if (feof(f)) return;
- if (hlen == 0) return;
- n = _pl3DSFindChunk(hid);
- if (n < 0) fseek(f, pc + hlen, 0);
- else {
- pc += hlen;
- if (_pl3DSChunkNames[n].func != NULL) _pl3DSChunkNames[n].func(f, pc);
- else _pl3DSChunkReader(f, pc);
- fseek(f, pc, 0);
- }
- if (ferror(f)) break;
- }
- }
|