📄 3dsimport_load.cxx
字号:
/*
* 3D Studio object reader
*/
#define FILELOAD
#define MEMLOAD
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <ivu_types.hxx>
#include "3dsimport_load.hxx"
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 MEMLOAD
static 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;
}
#endif
static H3dsScene * Scene;
H3dsMeshObj * GetMeshObj(void)
{
void * mem;
if((mem=p_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=p_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 4
enum {
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) P_FREE(mobj->maplist);
if(mobj->facelist) P_FREE(mobj->facelist);
if(mobj->vertlist) P_FREE(mobj->vertlist);
}
P_FREE(scene->meshobjlist);
}
P_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 *) p_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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -