This section of the archives stores flipcode's complete Developer Toolbox collection, featuring a variety of mini-articles and source code contributions from our readers.


  Lightwave v6.0 Object Loader
  Submitted by

I wrote this class just for fun, and to check the new lightwave objects freatures, like UV Mapping and Weight Mapping. Try this code to load object and internal structures. See ya. Antonio Lattanzio

Currently browsing [] (3,827 bytes) - [lwoloader.cpp] - (9,660 bytes)

//Project:	LWO2 Loader Prototype
//Author:	Antonio Lattanzio	-	D3stY
//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; }

Currently browsing [] (3,827 bytes) - [3dtypes.h] - (2,687 bytes)

struct t_vert3
    float x,y,z;
	t_vert3& operator == (t_vert3 &v) {x=v.x;y=v.y;z=v.z;return *this;}
	t_vert3& operator = (float f) {x=y=z=f;return *this;}
	t_vert3& operator += (t_vert3 &v) {x+=v.x;y+=v.y;z+=v.z;return *this;}
	t_vert3& operator -= (t_vert3 &v) {x-=v.x;y-=v.y;z-=v.z;return *this;}
	t_vert3& operator *= (t_vert3 &v) {x*=v.x;y*=v.y;z*=v.z;return *this;}
	t_vert3& operator /= (t_vert3 &v) {x/=v.x;y/=v.y;z/=v.z;return *this;}

struct t_poly { int verts[3]; t_vert3 norm; };

struct t_uvmap { char *name; float *u,*v; UINT *index; t_uvmap *prev,*next; };

struct t_wmap { char *name; float *w; UINT *index; t_wmap *prev,*next; };

struct t_mesh { t_vert3* verts; t_vert3* norms; t_poly* polys; int numverts; int numpolys; t_mesh *next; t_mesh *prev; };

struct t_plist { UINT *list; t_plist *next; t_plist *prev; };

struct t_surf { char *name; float dr,dg,db,da; t_surf *next; t_surf *prev; };

struct t_object { t_mesh* meshes; t_uvmap* uvmap; t_wmap* wmap; t_plist* plist; t_surf* surf; int numverts; int numpolys; int nummeshes; int numuvmaps; int numwmaps; int numplists; int numsurfs;

void Delete() { int j=0;

//Delete Mesh Layers t_mesh *tm = meshes; if (tm) for (j=0; j<nummeshes; j++) { if (tm->norms) delete (tm->norms); delete (tm->polys); delete (tm->verts); if (!tm->next) break; tm = tm->next; delete (tm->prev); } delete (tm);

//Delete UVMAPs t_uvmap *tuv = uvmap; if (tuv) for (j=0; j<numuvmaps; j++) { delete (tuv->name); delete (tuv->u); delete (tuv->v); delete (tuv->index); if (!tuv->next) break; tuv = tuv->next; delete (tuv->prev); } delete (tuv);

//Delete WMAPs t_wmap *tw = wmap; if (tw) for (j=0; j<numwmaps; j++) { delete (tw->name); delete (tw->w); delete (tw->index); if (!tw->next) break; tw = tw->next; delete (tw->prev); } delete (tw); //delete (wmap); //Delete PLISTs t_plist *tpl = plist; if (tpl) for (j=0; j<numplists; j++) { delete (tpl->list); if (!tpl->next) break; tpl = tpl->next; delete (tpl->prev); } delete (tpl);

//Delete PLISTs t_surf *ts = surf; if (ts) for (j=0; j<numsurfs; j++) { delete (ts->name); if (!ts->next) break; ts = ts->next; delete (ts->prev); } delete (ts);

} };

//extern int Load3DS(char* filename, t_model *mod); //extern int LoadLWO2(char* filename, t_model *mod); extern BOOL LoadLWO2( char* filename, t_object *g_obj );

The zip file viewer built into the Developer Toolbox made use of the zlib library, as well as the zlibdll source additions.


Copyright 1999-2008 (C) FLIPCODE.COM and/or the original content author(s). All rights reserved.
Please read our Terms, Conditions, and Privacy information.