/////////////////////////////////////////////////////////////////////////////////////
//Project: LWO2 Loader Prototype
//Author: Antonio Lattanzio - D3stY
//e-mail: D3stY@softhome.net
//Date: 13/06/00
//Notes: This piece of code demonstrates how we can handle Lightwave 6 Objects (LWO2).
/////////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <stdio.h>
#include "3dtypes.h"
#include "useful.h"
//Some Inverted Tags x IFF format
#define LWO2_FORM 'MROF' //FROM
#define LWO2_LWO2 '2OWL' //LWO2
#define LWO2_TAGS 'SGAT' //TAGS
#define LWO2_LAYR 'RYAL' //LAYR
#define LWO2_PNTS 'STNP' //PNTS
#define LWO2_POLS 'SLOP' //POLS
#define LWO2_FACE 'ECAF' //FACE
#define LWO2_VMAP 'PAMV' //VMAP
#define LWO2_TXUV 'VUXT' //TXUV
#define LWO2_SURF 'FRUS' //SURF
#define LWO2_WGHT 'THGW' //WGHT
#define LWO2_PTAG 'GATP' //PTAG
long GetChunk(char* buffer,t_object *o);
//invert 4 bytes and returns a long
void invert4bytes( char *src , char *res )
{
BYTE x=3,y=0;
while (y!=4) res[y++] = src[x--];
}
// LoadLWO2
BOOL LoadLWO2( char* filename, t_object *g_obj )
{
char* memfile = NULL;
int flength = 0;
bool loaded = false;
if (filename==NULL) return false;
memset(g_obj,0,sizeof(g_obj));
FILE *file = fopen(filename,"rb");
if (!file) return FALSE;
fseek(file,0,SEEK_END);
flength = ftell(file);
memfile = new char[flength];
rewind(file);
fread(memfile, 1,flength,file);
fclose(file);
//MessageBox(NULL,filename,"",MB_OK);
GetChunk(memfile,g_obj);// start recursive parsing
delete memfile;
if (g_obj->numpolys==0||g_obj->numverts==0) return false;
return TRUE;
}
long GetChunk(char* buffer,t_object *g_obj)
{
long chunkid = *(long*)(buffer);
long chunklength;
static t_mesh *c_mesh=NULL;
static t_uvmap *c_uvmap=NULL;
static t_wmap *c_wmap=NULL;
static t_plist *c_plist=NULL;
static t_surf *c_surf=NULL;
invert4bytes( buffer+4, (char*)&chunklength );
int i = 8;
int j;
switch (chunkid)
{
case LWO2_FORM:
{
char str[255];
memset(str,0,255);
int x=0;
while (x<4) {str[x]=buffer[i++];x++;}
if (strcmp(str,"LWO2")!=0)
{
MessageBox(NULL,"Wrong File Format!","Whassuuup??",MB_OK);
i=chunklength;
}
break;
}
case LWO2_PNTS: //get all points
{
//First Mesh Entry
if (g_obj->meshes==NULL) {
c_mesh = g_obj->meshes = new t_mesh;
memset(c_mesh,0,sizeof(t_mesh));
g_obj->nummeshes++;
}else{
t_mesh *tm=g_obj->meshes;
while (tm->next) tm=tm->next;
c_mesh = new t_mesh;
memset(c_mesh,0,sizeof(t_mesh));
tm->next = c_mesh;
tm->next->prev = tm;
g_obj->nummeshes++;
}
if (c_mesh->numverts == NULL)
{
c_mesh->numverts = chunklength/12;
c_mesh->verts = new t_vert3[c_mesh->numverts];
for (j=0;j<c_mesh->numverts;j++)
{
invert4bytes( buffer+i, (char*)&c_mesh->verts[j].x );i+=4;
invert4bytes( buffer+i, (char*)&c_mesh->verts[j].y );i+=4;
invert4bytes( buffer+i, (char*)&c_mesh->verts[j].z );i+=4;
}
g_obj->numverts+=c_mesh->numverts;
//char str[255];
//sprintf(str,"Mesh: %u\tVerts:%u\n",g_obj->nummeshes,c_mesh->numverts);
//OutputDebugString(str);
} else i = chunklength;
break;
}
case LWO2_POLS: //get all polys
{
if (*(long*)(buffer+i)==LWO2_FACE)
if (c_mesh->polys == NULL)
{
c_mesh->numpolys = 0;
i+=4;
//chunklength+=8;
for (j=i;j<=chunklength;)
{
short vnum = *(char*)(buffer+j+1) + (*(char*)(buffer+j)<<8);
j+=2+vnum*2;
c_mesh->numpolys++;
if (vnum!=3) {
//delete (c_mesh->polys);
//c_mesh->polys=NULL;
//delete (c_mesh);
//delete (c_mesh->verts);
//g_obj->nummeshes--;
MessageBox(NULL,"Yo.. Check Geometry! [3verts x poly]","WASSSUUUPPP!!!",MB_OK);
i=chunklength;
break;
}
}
//if (j!=chunklength) break;
c_mesh->polys = new t_poly[c_mesh->numpolys];
int p=0;
for (j=i;j<=chunklength;)
{
short vnum = *(char*)(buffer+j+1) + (*(char*)(buffer+j)<<8);j+=2;
c_mesh->polys[p].verts[0] = (BYTE)buffer[j+1] + ((BYTE)buffer[j]<<8);j+=2;
c_mesh->polys[p].verts[1] = (BYTE)buffer[j+1] + ((BYTE)buffer[j]<<8);j+=2;
c_mesh->polys[p].verts[2] = (BYTE)buffer[j+1] + ((BYTE)buffer[j]<<8);j+=2;
p++;
}
i=chunklength;
g_obj->numpolys+=c_mesh->numpolys;
} else i = chunklength;
break;
}
case LWO2_VMAP:
{
int j=0;
UINT vmode = *(long*)(buffer+i);
if ( vmode==LWO2_TXUV||vmode==LWO2_WGHT )
{
j+=4;
short entries = *(char*)(buffer+i+j+1) + (*(char*)(buffer+i+j)<<8);
j+=2;
UINT strlen=0;
while (buffer[i+j]!=0) {j++;strlen++;}
if (strlen%2!=0) j++;else j+=2;
int tot = (chunklength-j)/(entries*4+2);
//char str[255];
//sprintf(str,"%u - %u - %f",entries,chunklength-j,(float)(chunklength-j)/(entries*4+2));
//MessageBox(NULL,str,"",MB_OK);
int vnum=0;
if (vmode==LWO2_TXUV)
{
if (g_obj->uvmap==NULL) {
c_uvmap = g_obj->uvmap = new t_uvmap;
memset(c_uvmap,0,sizeof(t_uvmap));
g_obj->numuvmaps++;
}else{
t_uvmap *tuv=g_obj->uvmap;
while (tuv->next) tuv=tuv->next;
c_uvmap = new t_uvmap;
memset(c_uvmap,0,sizeof(t_uvmap));
tuv->next = c_uvmap;
tuv->next->prev = tuv;
g_obj->numuvmaps++;
}
c_uvmap->name = new char[strlen+1];
strcpy(c_uvmap->name,buffer+i+6);
c_uvmap->u = new float[tot];
c_uvmap->v = new float[tot];
c_uvmap->index = new UINT[tot];
while (j<chunklength)
{
float u=0,v=0;
BYTE v1 = *(char*)(buffer+i+j+1);
BYTE v2 = *(char*)(buffer+i+j);
unsigned short vert = v1+v2*0xff;j+=2;//*(char*)(buffer+i+j+1) + (*(char*)(buffer+i+j)<<8);j+=2;
invert4bytes( buffer+i+j, (char*)&u );j+=4;
invert4bytes( buffer+i+j, (char*)&v );j+=4;
c_uvmap->u[vnum] = u;
c_uvmap->v[vnum] = v;
c_uvmap->index[vnum] = vert;
vnum++;
}
char str[255];
sprintf(str,"Mesh: %u\tUVs:%u/%u\n",g_obj->nummeshes,vnum,tot);
OutputDebugString(str);
}else
if (vmode==LWO2_WGHT)
{
if (g_obj->wmap==NULL) {
c_wmap = g_obj->wmap = new t_wmap;
memset(c_wmap,0,sizeof(t_wmap));
g_obj->numwmaps++;
}else{
t_wmap *tw=g_obj->wmap;
while (tw->next) tw=tw->next;
c_wmap = new t_wmap;
memset(c_wmap,0,sizeof(t_wmap));
tw->next = c_wmap;
tw->next->prev = tw;
g_obj->numwmaps++;
}
c_wmap->name = new char[strlen+1];
strcpy(c_wmap->name,buffer+i+6);
c_wmap->w = new float[tot];
c_wmap->index = new UINT[tot];
while (j<chunklength)
{
float power=0;
BYTE v1 = *(char*)(buffer+i+j+1);
BYTE v2 = *(char*)(buffer+i+j);
unsigned short vert = v1+v2*0xff;j+=2;
invert4bytes( buffer+i+j, (char*)&power );j+=4;
c_wmap->w[vnum] = power;
c_wmap->index[vnum] = vert;
vnum++;
//char str[255];
//sprintf(str,"Mesh: %u\tVert:%u\tW:%f\n",g_obj->nummeshes,vert,power);
//OutputDebugString(str);
}
char str[255];
sprintf(str,"Mesh: %u\tWs:%u/%u\n",g_obj->nummeshes,vnum,tot);
OutputDebugString(str);
}
}
i = chunklength;
break;
}
case LWO2_SURF:
{
UINT j=0;
UINT strlen=0;
while (buffer[i+j]!=0) {j++;strlen++;}
if (strlen%2!=0) j++;else j+=2;
//MessageBox(NULL,buffer+i,"",MB_OK);
if (g_obj->surf==NULL) {
c_surf = g_obj->surf = new t_surf;
memset(c_surf,0,sizeof(t_surf));
g_obj->numsurfs++;
}else{
t_surf *ts=g_obj->surf;
while (ts->next) ts=ts->next;
c_surf = new t_surf;
memset(c_surf,0,sizeof(t_surf));
ts->next = c_surf;
ts->next->prev = ts;
g_obj->numsurfs++;
}
c_surf->name = new char[strlen+1];
strcpy(c_surf->name,buffer+i);
//MessageBox(NULL,c_surf->name,"",MB_OK);
i = chunklength;
break;
}
case LWO2_PTAG:
{
int j=4;
UINT vmode = *(long*)(buffer+i);
if (vmode==LWO2_SURF)
{
UINT plnum = (chunklength-4)/4;
char str[255];
sprintf(str,"PTags: %u - %u\n",chunklength-4,(chunklength-4)/4);
OutputDebugString(str);
if (g_obj->plist==NULL) {
c_plist = g_obj->plist = new t_plist;
memset(c_plist,0,sizeof(t_plist));
g_obj->numplists++;
}else{
t_plist *tpl=g_obj->plist;
while (tpl->next) tpl=tpl->next;
c_plist = new t_plist;
memset(c_plist,0,sizeof(t_plist));
tpl->next = c_plist;
tpl->next->prev = tpl;
g_obj->numplists++;
}
c_plist->list = new UINT[plnum];
UINT vnum=0;
while (j<chunklength)
{
short val = (short)(((BYTE)buffer[i+j])+(BYTE)buffer[i+j+1]);j+=2;
short sur = (short)(((BYTE)buffer[i+j])+(BYTE)buffer[i+j+1]);j+=2;
//invert4bytes( buffer+i+j, (char*)&val );j+=4;
c_plist->list[vnum++] = val;
//char str[255];
//sprintf(str,"Pv: %u/%u\n",val,sur);
//OutputDebugString(str);
}
}
i = chunklength;
break;
}
default:
i = chunklength; // ignoring other chunks ... we can easly add more code here!
break;
}
while (i < chunklength) i += GetChunk(buffer+i,g_obj)+8;
return chunklength;
}
|