📄 3dsload.c
字号:
/* * 3D Studio object reader */#define FILELOAD#define MEMLOAD#include <stdlib.h>#include <string.h>#include <setjmp.h>#include "3dsload.h"static void (* dread) (void * dest, int len);static void (* dsetpos)(dword pos);static dword (* dgetpos)(void);static jmp_buf EnvState;#ifdef FILELOAD#include <stdio.h>static FILE * InFile=0;static void FileRead(void * dest, int len){ if(fread(dest, len, 1, InFile) != 1) { //printf("Error reading file\n"); longjmp(EnvState, 1); }}static void FileSetpos(dword pos){ if(fseek(InFile, (long)pos, SEEK_SET) != 0) { //printf("Error moving filepointer\n"); longjmp(EnvState, 1); }}static dword FileGetpos(void){ long pos; if((pos=ftell(InFile)) == -1L) { //printf("Error getting fileposition\n"); longjmp(EnvState, 1); } return (dword) pos;}#endif#ifdef MEMLOADstatic byte * MemBuffer=0;static dword MemBufferLen=0, MemBufferIndex=0;static void MemRead(void * dest, int len){ // Never allow any reads past the membuffer. if(MemBufferIndex+len > MemBufferLen) { //printf("Bad memread\n"); longjmp(EnvState, 1); } memcpy(dest, &MemBuffer[MemBufferIndex], len); MemBufferIndex+=len;}static void MemSetpos(dword pos){ // It should be legal to move the position one byte // past the membuffer. The mem must not be read though. if(pos > MemBufferLen) { //printf("Bad memsetpos\n"); longjmp(EnvState, 1); } MemBufferIndex=pos;}static dword MemGetpos(void){ return MemBufferIndex;}#endifstatic H3dsScene * Scene;H3dsMeshObj * GetMeshObj(void){ void * mem; if((mem=realloc(Scene->meshobjlist, sizeof(H3dsMeshObj)*(Scene->meshobjs+1))) == 0) { //printf("Error reallocating mem\n"); longjmp(EnvState, 1); } Scene->meshobjlist=(H3dsMeshObj *) mem; H3dsMeshObj * obj=&Scene->meshobjlist[Scene->meshobjs++]; memset(obj, 0, sizeof(H3dsMeshObj)); return obj;}static void * getmem(int size){ void * mem; if((mem=malloc(size))==0) { //printf("Error allocating mem\n"); longjmp(EnvState, 1); } return mem;}// Each 3DS data-chunk starts with a 6 byte header.// The first item in the header is a 2 byte (word) id-number.// After that follows a dword wich gives the size of// the data-chunk including the header. The size can be used// as an relative offset to the next chunk.// tab 4enum { CHUNK_RGBF = 0x0010, CHUNK_RGBB = 0x0011,// CHUNK_RBGB2 = 0x0012, // ?? NOT HLS. CHUNK_MAIN = 0x4D4D, CHUNK_OBJMESH = 0x3D3D, CHUNK_BKGCOLOR = 0x1200, CHUNK_AMBCOLOR = 0x2100, CHUNK_OBJBLOCK = 0x4000, CHUNK_TRIMESH = 0x4100, CHUNK_VERTLIST = 0x4110, CHUNK_FACELIST = 0x4120, CHUNK_FACEMAT = 0x4130, CHUNK_MAPLIST = 0x4140, CHUNK_SMOOLIST = 0x4150, CHUNK_TRMATRIX = 0x4160, CHUNK_LIGHT = 0x4600, CHUNK_SPOTLIGHT = 0x4610, CHUNK_CAMERA = 0x4700, CHUNK_MATERIAL = 0xAFFF, CHUNK_MATNAME = 0xA000, CHUNK_AMBIENT = 0xA010, CHUNK_DIFFUSE = 0xA020, CHUNK_SPECULAR = 0xA030, CHUNK_TEXTURE = 0xA200, CHUNK_BUMPMAP = 0xA230, CHUNK_MAPFILE = 0xA300, CHUNK_KEYFRAMER = 0xB000, CHUNK_FRAMES = 0xB008};static void ReadVertList(dword, H3dsMeshObj * meshobj){ word nv; dread(&nv, sizeof(nv)); meshobj->verts=nv; int k=nv; meshobj->vertlist=(H3dsVert *) getmem(sizeof(H3dsVert)*k); for(int n=0; n<k; n++) { dread(&meshobj->vertlist[n], sizeof(float32)*3); }}static void ReadFaceList(dword, H3dsMeshObj * meshobj){ word nv; dread(&nv, sizeof(nv)); meshobj->faces=nv; int k=nv; meshobj->facelist=(H3dsFace *) getmem(sizeof(H3dsFace)*k); for(int n=0; n<k; n++) { dread(&meshobj->facelist[n], sizeof(word)*4); }}static void ReadMapList(dword, H3dsMeshObj * meshobj){ word nv; dread(&nv, sizeof(nv)); meshobj->maps=nv; int k=nv; meshobj->maplist=(H3dsMap *) getmem(sizeof(H3dsMap)*k); for(int n=0; n<k; n++) { dread(&meshobj->maplist[n], sizeof(float32)*2); }}static void ReadTraMatrix(dword, H3dsMeshObj * meshobj){ dread(&meshobj->TraMatrix, sizeof(float32)*12); meshobj->matrix=1;}static void ReadTriMeshBlocks(dword p, char * name){ word id; dword len, pc; H3dsMeshObj * meshobj=GetMeshObj(); strcpy(meshobj->name, name); while((pc=dgetpos()) < p) { dread(&id, sizeof(id)); dread(&len, sizeof(len)); switch((int)id) { case CHUNK_VERTLIST: ReadVertList (pc+len, meshobj); break; case CHUNK_FACELIST: ReadFaceList (pc+len, meshobj); break; case CHUNK_MAPLIST: ReadMapList (pc+len, meshobj); break; case CHUNK_TRMATRIX: ReadTraMatrix(pc+len, meshobj); break; //case CHUNK_FACEMAT: //case CHUNK_SMOOLIST: default: dsetpos(pc+len); } }}static void ReadObjBlocks(dword p){ word id; dword len, pc; char name[16]; // The object name is the first item int n=0; do { dread(&name[n++], 1); } while ( ( name[n-1] != '\0' ) && ( n < (int)sizeof(name) ) ); name[n-1]='\0'; while((pc=dgetpos()) < p) { dread(&id, sizeof(id)); dread(&len, sizeof(len)); switch((int)id) { case CHUNK_TRIMESH: ReadTriMeshBlocks(pc+len, name); break; //case CHUNK_LIGHT: //case CHUNK_CAMERA: default: dsetpos(pc+len); } }}static void ReadObjMeshBlocks(dword p){ word id; dword len, pc; while((pc=dgetpos()) < p) { dread(&id, sizeof(id)); dread(&len, sizeof(len)); switch((int)id) { case CHUNK_OBJBLOCK: ReadObjBlocks(pc+len); break; //case CHUNK_AMBCOLOR: //case CHUNK_BKGCOLOR: default: dsetpos(pc+len); } }}static void ReadMainBlocks(dword p){ word id; dword len, pc; while((pc=dgetpos()) < p) { dread(&id, sizeof(id)); dread(&len, sizeof(len)); switch((int)id) { case CHUNK_OBJMESH: ReadObjMeshBlocks(pc+len); break; //case CHUNK_MATERIAL: //case CHUNK_KEYFRAMER: default: dsetpos(pc+len); } }}void HFree3dsScene(H3dsScene * scene){ if(scene) { if(scene->meshobjlist) { for(int n=scene->meshobjs-1; n>=0; n--) { H3dsMeshObj * mobj = &scene->meshobjlist[n]; if(mobj->maplist) free(mobj->maplist); if(mobj->facelist) free(mobj->facelist); if(mobj->vertlist) free(mobj->vertlist); } free(scene->meshobjlist); } free(scene); }}H3dsScene * HRead3dsScene(void * ptr, int what, dword size){ if(ptr==0) return 0; #ifdef FILELOAD if(what==0) { // Load from file InFile=(FILE *) ptr; dread=FileRead; dsetpos=FileSetpos; dgetpos=FileGetpos; } else #endif #ifdef MEMLOAD if(what==1) { // Read from mem MemBufferIndex=0; MemBufferLen=size; MemBuffer=(byte *) ptr; dread=MemRead; dsetpos=MemSetpos; dgetpos=MemGetpos; } else #endif { return 0; } if((Scene=(H3dsScene *) malloc(sizeof(H3dsScene)))==0) return 0; memset(Scene, 0, sizeof(H3dsScene)); int retval = setjmp(EnvState); if(retval==0) { // Return address set, start loading 3DS data. word id; dword len, pc; pc=dgetpos(); dread(&id, sizeof(id)); dread(&len, sizeof(len)); if((int)id!=CHUNK_MAIN) { HFree3dsScene(Scene); //printf("Not 3ds data\n"); return 0; } ReadMainBlocks(pc+len); } else { // There was an error, free the allocated mem and return NULL. HFree3dsScene(Scene); return 0; } return Scene;}H3dsScene * ThreeDS_ReadFromFile( const char * filename ){ FILE * inf; H3dsScene * scene; scene = NULL; inf = fopen( filename, "rb"); if ( inf == NULL ) { fprintf(stderr, "Failed to open %s\n", filename ); return NULL; } long size; if( fseek(inf, 0, SEEK_END)) { fprintf(stderr, "Error seeking %s\n", filename ); fclose( NULL ); return NULL; } size=ftell(inf); if ( size == -1L ) { fprintf(stderr, "Error seeking %s\n", filename ); fclose(inf); return NULL; } rewind(inf); scene = HRead3dsScene(inf, 0, size); if ( scene == NULL) { fprintf(stderr, "Failed to load %s\n", filename ); fclose(inf); return NULL; } fclose(inf); return scene;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -