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 [lw6loader.zip] (3,827 bytes) - [lwoloader.cpp] - (9,660 bytes)

    /////////////////////////////////////////////////////////////////////////////////////
    //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;
    }

Currently browsing [lw6loader.zip] (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.