diff options
Diffstat (limited to 'Src/Winamp/plush/READ_3DS.C')
-rw-r--r-- | Src/Winamp/plush/READ_3DS.C | 244 |
1 files changed, 244 insertions, 0 deletions
diff --git a/Src/Winamp/plush/READ_3DS.C b/Src/Winamp/plush/READ_3DS.C new file mode 100644 index 00000000..90db94e9 --- /dev/null +++ b/Src/Winamp/plush/READ_3DS.C @@ -0,0 +1,244 @@ +/****************************************************************************** +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; + } +} + |