
#include <cstdio>
#include <cmath>

#define USING_DESTINY3D
#define DESTINY3D_STATIC_LINK

#include "deString.hpp"
#include "deMath.hpp"
#include "deList.hpp"
#include "deHash.hpp"

#include "tinyxml/tinyxml.h"

// 3ds handling
#include <lib3ds/file.h>                        
#include <lib3ds/camera.h>
#include <lib3ds/mesh.h>
#include <lib3ds/node.h>
#include <lib3ds/material.h>
#include <lib3ds/matrix.h>
#include <lib3ds/vector.h>
#include <lib3ds/light.h>
#ifdef _DEBUG
#pragma comment(lib, "lib3ds-d")
#else
#pragma comment(lib, "lib3ds")
#endif

Lib3dsFile*			m_3dsFile = NULL;

void help();
void init();
void cleanup();

void ConvertFile(Lib3dsFile *f, deString2 sPath, TiXmlDocument* xmlDoc);

void help()
{
	printf("\n3ds2dexi.exe\nCopyright(c) 2002, 2003 Novus Delta, LLC\n\nConverts 3DS format files to DWORLD format Destiny3D files\n\nUseage:\n3ds2dworld <filename>\n\n<filename> is a 3DS filename including extension.  \n\nNote: The output DWORLD will have the same name with a .dworld extension.\n");
	exit(1);
}

int main(int argc, char* argv[])
{
	deString2		fname;

#ifdef _DEBUG 
	int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); // Get current flag 
	flag |= _CRTDBG_LEAK_CHECK_DF; // Turn on leak-checking bit 
//	flag |= _CRTDBG_CHECK_ALWAYS_DF;
//	flag |= _CRTDBG_CHECK_CRT_DF;
	_CrtSetDbgFlag(flag); // Set flag to the new value 
#endif

	if (argc == 1)
	{
		help();
	}
	else if (argc > 2)
	{
		help();
	}

	if (strcmp(argv[1], "-?") == 0)
	{
		help();
	}
	else if (strcmp(argv[1], "-h") == 0)
	{
		help();
	}
	else if (strcmp(argv[1], "?") == 0)
	{
		help();
	}
	else if (strcmp(argv[1], "-help") == 0)
	{
		help();
	}
	else if (strcmp(argv[1], "--?") == 0)
	{
		help();
	}
	else if (strcmp(argv[1], "--help") == 0)
	{
		help();
	}
	else
	{
		// assume arg is the filename for now
		fname = argv[1];
		
		// calc path if there is one
		deString2 sPath = fname;

		sPath = sPath.SubString(0, sPath.Find('\\', 0, deString2::search_backwards));
		printf("Using path: %s\n", sPath.const_str());
		/*
		pdest = strrchr(sPath.const_str(), ch);
		if (pdest)
		{
			result = pdest - sPath.Reserve(sPath.Length()) + 1;
			sPath.Trim();
//			fname = sPath.SubString(result, sPath.Length()-1);
			sPath = sPath.SubString(0, result-1);
			printf("Using path: %s\n", sPath.const_str());
		}
		else
		{
			sPath = "";
		}
		*/


		// split off filename from path

		// calc output filename
		//deTArray<deString2> splits;
		//fname.Split('.', splits);
		deString2 split = fname.SubString(0, fname.Find('.', 0, deString2::search_backwards));

		// feedback to user
		printf("Reading %s ", fname.const_str());

		// load 3ds file
		m_3dsFile = lib3ds_file_load(fname.const_str());
		if (!m_3dsFile)
		{
			printf("...Failed to open input file '%s'!\n", fname.const_str());
			exit(1);
		}
	
		// init destiny3d
		init();

		// Convert the meshes in the 3ds file to brushes
		//splits[0] = splits[0] + ".dexi";
		split = split + ".dexi";
		TiXmlDocument* xmlDoc = new TiXmlDocument(split.const_str());
		printf("...Done.\n");
		printf("Converting Data ");
		ConvertFile(m_3dsFile, sPath, xmlDoc);
		printf("...Done.\n");

		// feedback to user
		printf("Writing %s ", split.const_str());
		xmlDoc->SaveFile();
		delete xmlDoc;

		printf("...Done.\n");
		cleanup();
	}

	return 0;
}

void init()
{
	// init destiny3d
#if 0
	IdeBitmap_Initialize();
	IdeRenderState_Initialize();
	IdeBrush_Initialize();
	IdeScene_Initialize();

	m_pWorldManager = IdeWorld_GetManager();
	if (!m_pWorldManager)
	{
		printf("\nFATAL ERROR: Failed to initialize Destiny3d World Manager!");
		exit(1);
	}
	m_iWorld = m_pWorldManager->CreateWorld();
	m_pWorld = m_pWorldManager->GetWorld(m_iWorld);
	if (!m_pWorld)
	{
		printf("\nFATAL ERROR: Failed to create a Destiny3d World!");
		exit(1);
	}
#endif
}

void cleanup()
{
/*
	// cleanup destiny3d
	if (m_pWorld)
		m_pWorld->Release();
	
	IdeResourceManager_GetManager()->RemoveAllResources();
*/
	if (m_3dsFile)
		lib3ds_file_free(m_3dsFile);
}

TiXmlElement* addEndChild(TiXmlElement* addTo, const char* addNamed)
{
	TiXmlElement* new_elem = new TiXmlElement(addNamed);
	addTo->LinkEndChild(new_elem);
	return new_elem;
}

TiXmlElement* addAfterChild(TiXmlElement* addTo, TiXmlElement* afterThis, const char* addNamed)
{
	TiXmlElement* new_elem = new TiXmlElement(addNamed);
	addTo->LinkAfterChild(afterThis, new_elem);
	return new_elem;
}

void instanceDump(TiXmlElement* scenedef, Lib3dsNode* n, const deMatrix44& parentFrame)
{
	static deString2 dummyName = "$$$DUMMY";
	deMatrix44 concatFrame, thisFrame(n->matrix, deFALSE);
	parentFrame.Multiply(thisFrame, concatFrame);
	if (n->type == LIB3DS_OBJECT_NODE && dummyName!= n->name)
	{
		TiXmlElement* instance_elem = scenedef->InsertEndChild(TiXmlElement("trimeshinstance"))->ToElement();
		if (n->data.object.instance[0])
		{
			instance_elem->SetAttribute("meshdef", n->data.object.instance);
			instance_elem->SetAttribute("instanced", 1);
		}
		else
		{
			instance_elem->SetAttribute("meshdef", n->name);
			instance_elem->SetAttribute("instanced", 0);
		}
	}
	Lib3dsNode* child;
	for(child=n->childs; child; child=child->next)
	{
		instanceDump(scenedef, child, concatFrame);
	}
}

void ConvertFile(Lib3dsFile *f, deString2 sPath, TiXmlDocument* xmlDoc)
{
	// create the destiny3d root element
	TiXmlElement* destiny3d_root = xmlDoc->InsertEndChild(TiXmlElement("destiny3d_content"))->ToElement();
	destiny3d_root->SetAttribute("version", "0.1");
	destiny3d_root->SetAttribute("target", "dworld");

	// children of destiny3d_content root (in order):
	// bitmaps, surfaces, vertices, skeletons, animations, meshes, scenedef, actordef
	// we only handle bitmaps, surfaces, vertices, meshes, scenedef
	
	TiXmlElement* bitmaps_elem = destiny3d_root->InsertEndChild(TiXmlElement("bitmaps"))->ToElement();
	TiXmlElement* surfaces_elem = destiny3d_root->InsertEndChild(TiXmlElement("surfaces"))->ToElement();
	TiXmlElement* vertices_elem = destiny3d_root->InsertEndChild(TiXmlElement("vertices"))->ToElement();
	TiXmlElement* meshes_elem = destiny3d_root->InsertEndChild(TiXmlElement("meshes"))->ToElement();
	TiXmlElement* scenedef_elem = destiny3d_root->InsertEndChild(TiXmlElement("scenedef"))->ToElement();

	// bitmaps & surfaces
	Lib3dsMaterial* mat3ds;
	int i;
	for (mat3ds = f->materials, i = 0; mat3ds; mat3ds = mat3ds->next, ++i)
	{
		deString attribString;
		attribString.Format("sfc_%s", mat3ds->name);
		TiXmlElement* sfc_elem = surfaces_elem->InsertEndChild(TiXmlElement("surface"))->ToElement();
		sfc_elem->SetAttribute("name", attribString.const_str());
		const char* texname = mat3ds->texture1_map.name;
		if (texname[0])
		{
			// create the bitmap element
			TiXmlElement* bmp_elem = bitmaps_elem->InsertEndChild(TiXmlElement("bitmap"))->ToElement();
			TiXmlElement* file_elem = bmp_elem->InsertEndChild(TiXmlElement("file"))->ToElement();
			file_elem->SetAttribute("name", texname);
			bmp_elem->SetAttribute("name", texname);

			// create the textures element
			/*
			<textures>
				<texture stage="0" textype="2D">
					<bitmap_name>bitmap1</bitmap_name>
				</texture>
			</textures>
			*/
			TiXmlElement* texs_elem = sfc_elem->InsertEndChild(TiXmlElement("textures"))->ToElement();
			TiXmlElement* tex_elem = texs_elem->InsertEndChild(TiXmlElement("texture"))->ToElement();
			tex_elem->SetAttribute("stage", 0);
			tex_elem->SetAttribute("textype", "2D");
			TiXmlElement* bmpname_elem = tex_elem->InsertEndChild(TiXmlElement("bitmap_name"))->ToElement();
			bmpname_elem->InsertEndChild(TiXmlText(texname));
		}
	}

	{ // scope enclosure
	// vertices & meshes
	Lib3dsMesh *mesh;
	for (mesh=f->meshes, i=0; mesh; mesh=mesh->next, ++i) 
	{
		Lib3dsDword k;
		deString attribString;
		attribString.Format("vpool%.4i", i);
		TiXmlElement* vpool_elem = vertices_elem->InsertEndChild(TiXmlElement("vertexpool"))->ToElement();
		vpool_elem->SetAttribute("name", attribString.const_str());
		TiXmlElement* mesh_elem = meshes_elem->InsertEndChild(TiXmlElement("trimeshdef"))->ToElement();
		mesh_elem->SetAttribute("name", mesh->name);
		mesh_elem->SetAttribute("vertexpool", attribString.const_str());
		TiXmlElement* lastposition = NULL;

		int numpos = 0;
		int numpoints = 0;
		int firstvert = numpoints;
		DE_ASSERT(mesh->points == mesh->texels);
		for (k = 0; k < mesh->points; ++k)
		{
			char buffer[30];
			// vertex position
			TiXmlElement* vpos_elem;
			if (lastposition)
				vpos_elem = addAfterChild(vpool_elem, lastposition, "vert_pos");
			else
				vpos_elem = addEndChild(vpool_elem, "vert_pos");
			lastposition = vpos_elem;
			//TiXmlElement* pos_elem = vpos_elem->InsertEndChild(TiXmlElement("position"))->ToElement();
			TiXmlElement* pos_elem = vpos_elem;
			pos_elem->SetValue("position");
			float* pos = mesh->pointL[k].pos;
			_snprintf(buffer, 20, "%g", pos[0]);
			pos_elem->SetAttribute("x", buffer);
			_snprintf(buffer, 20, "%g", pos[1]);
			pos_elem->SetAttribute("y", buffer);
			_snprintf(buffer, 20, "%g", pos[2]);
			pos_elem->SetAttribute("z", buffer);
			
			// vertex entry
			TiXmlElement* vert_elem = addEndChild(vpool_elem, "vertex");
			vert_elem->SetAttribute("posidx", numpos);
/*			// normal
			TiXmlElement* norm_elem = vert_elem->InsertEndChild(TiXmlElement("normal"))->ToElement();
			deVec3d norm = face->Normal;
			_snprintf(buffer, 20, "%g", norm.x);
			norm_elem->SetAttribute("nx", buffer);
			_snprintf(buffer, 20, "%g", norm.y);
			norm_elem->SetAttribute("ny", buffer);
			_snprintf(buffer, 20, "%g", norm.z);
			norm_elem->SetAttribute("nz", buffer);
*/			// texture coordinate
			TiXmlElement* uv_elem = addEndChild(vert_elem, "texcoord");
			float* uv = mesh->texelL[k];
			_snprintf(buffer, 20, "%g", uv[0]);
			uv_elem->SetAttribute("u", buffer);
			_snprintf(buffer, 20, "%g", 1.0 - uv[1]);
			uv_elem->SetAttribute("v", buffer);
			uv_elem->SetAttribute("w", 0);
			
			++numpos;
			++numpoints;
		}
		vpool_elem->SetAttribute("num_pos", numpos);
		vpool_elem->SetAttribute("num_vert", numpoints);

		//	<trimeshsub name="mesh1sub1" winding="clockwise" surface="surface1" facecount="4">
		//		<triface v0="0" v1="1" v2="2"/>
		deTHashString<deTList<Lib3dsFace*> > FaceListHash(97);
		for (k = 0; k < mesh->faces; ++k)
		{
			Lib3dsFace* face = &(mesh->faceL[k]);
			deTList<Lib3dsFace*>* FaceList = FaceListHash.FindElement(face->material, NULL);
			if (!FaceList)
				FaceList = FaceListHash.AddElement(deTList<Lib3dsFace*>(), face->material);
			FaceList->AddElement(face);
		}
		deTArray<deTList<Lib3dsFace*>*> FaceListArray;
		FaceListHash.GetAllElements(FaceListArray);
		for (k = 0; k < FaceListArray.size(); ++k)
		{
			deTList<Lib3dsFace*>* FaceList = FaceListArray[k];
			deTList<Lib3dsFace*>::iterator
				it = FaceList->begin(),
				end = FaceList->end();

			TiXmlElement* submesh_elem = mesh_elem->InsertEndChild(TiXmlElement("trimeshsub"))->ToElement();
			attribString.Format("%s_sub%i", mesh->name, k);
			submesh_elem->SetAttribute("name", attribString.const_str());
			submesh_elem->SetAttribute("winding", "counter");
			mat3ds = lib3ds_file_material_by_name(f, (*it)->material);
			if (!mat3ds)
				printf("...Error finding material '%s' ", (*it)->material);
			attribString.Format("sfc_%s", mat3ds ? mat3ds->name : "<null>");
			submesh_elem->SetAttribute("surface", attribString.const_str());
			submesh_elem->SetAttribute("facecount", FaceList->size());
			
			for (; it != end; ++it)
			{
				TiXmlElement* triface = addEndChild(submesh_elem, "triface");
				triface->SetAttribute("v0", (*it)->points[0]);
				triface->SetAttribute("v1", (*it)->points[2]);
				triface->SetAttribute("v2", (*it)->points[1]);
			}
		}
	}
	Lib3dsNode* n;
	for(n=f->nodes; n; n=n->next)
	{
		// scenedef
		/*
		<trimeshinstance meshdef="mesh1" instanced="0">
			<transform>
				<position x="0" y="0" z="0"/>
				<rotation qx="0" qy="0" qz="1" qw="0"/>
			</transform>
		</trimeshinstance>
		*/
		deMatrix44 I;
		I.Identity();
		instanceDump(scenedef_elem, n, I);
	}
	} // scope enclosure


#if 0
	Lib3dsMesh *m;
	for (m=f->meshes; m; m=m->next) 
	{
    
		IdeSceneNode* scenenode = IdeSceneNode_CreateBrushNode();
		

		deVertex	*verts;
		verts = new deVertex[m->points];
		deTArray<unsigned short*> indexArray;
		unsigned short	*indices;
		indices = new unsigned short[m->faces*3];
		indexArray.PushBack(indices);
		deTexCoord *uvcoords;
		Lib3dsMaterial *mat = NULL;
		IdeRenderTexture * TextureState;
		deTArray<IdeRenderTexture*> textureArray;
		deString2 sTexture;
		deARGB color;
		int iStages = 0;

		//
		// Determine how many different materials we have in the object
		// as well as how many indices between each.
		// Basically start goign through the face data and sending it through
		// until we find a change in material names.
		BIndexList blah;
		IdeBrush * b = IdeBrush_CreateBrush(IdeBrush::Brush_Static);
		IdeStaticBrush * s = (IdeStaticBrush*)(b->GetBrushInterface(IdeBrush::Brush_Static));
		int iNumMaterials = 1;
		int iNumIndices = 0;
		IdeResourceBase* rsc;
		IdeBitmap *BMP, *BMP2;
		char* matName = new char[64];
		strcpy(matName, m->faceL[0].material);
		int j = 0;

/*		if (m->faceL[0].material[0])
		{
			iStages = 1;
			for (i=0; i<m->faces; i = i++) 
			{
				if (strcmp(matName, m->faceL[i].material) != 0)
				{
					// material name has changed
					strcpy(matName, m->faceL[i].material);
					iStages++;
				}
			}
		}*/

		for (i=0; i<m->points; ++i) 
		{
//			Lib3dsNode* node = lib3ds_file_node_by_name(f, m->name, LIB3DS_OBJECT_NODE);
			verts[i].x = m->pointL[i].pos[0];
			verts[i].y = m->pointL[i].pos[1];
			verts[i].z = m->pointL[i].pos[2];
		}

		uvcoords = new deTexCoord[m->points];
		for (i=0; i < m->texels; i++)
		{
			uvcoords[i].u = m->texelL[i][0];
			uvcoords[i].v = -m->texelL[i][1];
		}

		i = 0;
		bAlpha = false;
		strcpy(matName, m->faceL[0].material);
		if (m->faceL[0].material[0])
		{
			j = 0;
			iNumIndices = 0;
			// build texture state for first material
			mat = lib3ds_file_material_by_name(f, m->faceL[i].material);
			if (mat)
			{
				TextureState = IdeRenderState_CreateRenderTexture();
				textureArray.PushBack(TextureState);
				if (mat->texture1_map.name[0])
				{
	//				rsc = IdeResourceManager_GetManager()->GetResource(mat->texture1_map.name, NULL);
					// modified to use given pathname from command line
					sTexture = mat->texture1_map.name;
					sTexture = sPath + sTexture;
					rsc = IdeResourceManager_GetManager()->GetResource(sTexture.Alloc(sTexture.Length()) , NULL);
					sTexture.Trim();
					if (rsc)
					{
						BMP = (IdeBitmap*)rsc->GetRscInterface(IdeBitmap_GetRscInterfaceID());
						TextureState->Lock();
						TextureState->SetColorArg(0,1,IdeRenderTexture::TEXTUREARG_TEXTURE);
						TextureState->SetColorArg(0,2,IdeRenderTexture::TEXTUREARG_DIFFUSE);
						TextureState->SetColorOperation(0, IdeRenderTexture::TEXTUREOP_SELECTARG1);
						// check for an alpha map
						if (mat->opacity_map.name[0])
						{
							rsc = IdeResourceManager_GetManager()->GetResource(mat->opacity_map.name, NULL);
							if (rsc)
							{
								BMP2 = (IdeBitmap*)rsc->GetRscInterface(IdeBitmap_GetRscInterfaceID());
								BMP->BindGrayScaleAsAlphaMap(BMP2);
								BMP2->Release();
								bAlpha = true;
								TextureState->SetAlphaArg(0,1,IdeRenderTexture::TEXTUREARG_TEXTURE);
			 					TextureState->SetAlphaOperation(0, IdeRenderTexture::TEXTUREOP_SELECTARG1);
							}
						}
						else
						{
							// check if main texture has an alpha built in
							if (BMP->GetFormat() == IdeDriver::BPP_A8R8G8B8)
							{
								bAlpha = true;
								TextureState->SetAlphaArg(0,1,IdeRenderTexture::TEXTUREARG_TEXTURE);
			 					TextureState->SetAlphaOperation(0, IdeRenderTexture::TEXTUREOP_SELECTARG1);
							}
						}
						TextureState->SetBitmap(0,BMP);
						TextureState->Unlock();
						TextureState->SetWorldID(m_iWorld);
						BMP->Release();
						iStages = 1;
					}
					else
						iStages = 0;
				}
				int r, g, b, a;
				r = (mat->diffuse[0] + 0.5) * 255.0;
				g = (mat->diffuse[1] + 0.5) * 255.0;
				b = (mat->diffuse[2] + 0.5) * 255.0;
				a = (mat->diffuse[3] + 0.5) * 255.0;
				if (r > 255)
					r = 255;
				if (g > 255)
					g = 255;
				if (b > 255)
					b = 255;
				if (a > 255)
					a = 255;
				color = ARGB(a,r,g,b);
			}
			else
				iStages = 0;

			for (i=0; i<m->faces; i = i++) 
			{
				if (strcmp(matName, m->faceL[i].material) != 0)
				{
					// material name has changed
					strcpy(matName, m->faceL[i].material);
					// build index list for what we have so far
					blah.positions = verts;
					blah.normals = verts;
					blah.uvcoords = uvcoords;
					blah.numpoints = m->points;
					blah.numtexstages = iStages;
					blah.indices = indices;
					blah.numindices = iNumIndices;
					s->SetTextureState(TextureState);
					s->SetDiffuseColor(color);
					s->AddIndexedBuffer(blah);
					iNumIndices = 0;
					j = 0;
					indices = new unsigned short[m->faces*3];
					indexArray.PushBack(indices);
					// build texture state for the next texture
					mat = lib3ds_file_material_by_name(f, m->faceL[i].material);
					if (mat)
					{
						TextureState = IdeRenderState_CreateRenderTexture();
						textureArray.PushBack(TextureState);
						if (mat->texture1_map.name[0])
						{
	//						rsc = IdeResourceManager_GetManager()->GetResource(mat->texture1_map.name, NULL);
							// modified to use given pathname from command line
					      sTexture = mat->texture1_map.name;
					      sTexture = sPath + sTexture;
							rsc = IdeResourceManager_GetManager()->GetResource(sTexture.Alloc(sTexture.Length()) , NULL);
							sTexture.Trim();
							if (rsc)
							{
								BMP = (IdeBitmap*)rsc->GetRscInterface(IdeBitmap_GetRscInterfaceID());
								TextureState->Lock();
								TextureState->SetColorArg(0,1,IdeRenderTexture::TEXTUREARG_TEXTURE);
								TextureState->SetColorArg(0,2,IdeRenderTexture::TEXTUREARG_DIFFUSE);
								TextureState->SetColorOperation(0, IdeRenderTexture::TEXTUREOP_SELECTARG1);
								// check for an alpha map
								if (mat->opacity_map.name[0])
								{
									rsc = IdeResourceManager_GetManager()->GetResource(mat->opacity_map.name, NULL);
									if (rsc)
									{
										BMP2 = (IdeBitmap*)rsc->GetRscInterface(IdeBitmap_GetRscInterfaceID());
										BMP->BindGrayScaleAsAlphaMap(BMP2);
										BMP2->Release();
										TextureState->SetAlphaArg(0,1,IdeRenderTexture::TEXTUREARG_TEXTURE);
					 					TextureState->SetAlphaOperation(0, IdeRenderTexture::TEXTUREOP_SELECTARG1);
									}
								}
								else
								{
									// check if main texture has an alpha built in
									if (BMP->GetFormat() == IdeDriver::BPP_A8R8G8B8)
									{
										bAlpha = true;
										TextureState->SetAlphaArg(0,1,IdeRenderTexture::TEXTUREARG_TEXTURE);
			 							TextureState->SetAlphaOperation(0, IdeRenderTexture::TEXTUREOP_SELECTARG1);
									}
								}
								TextureState->SetBitmap(0,BMP);
								TextureState->Unlock();
								TextureState->SetWorldID(m_iWorld);
								BMP->Release();
								iStages = 1;
							}
							else
								iStages = 0;
						}
	//					lib3ds_material_free(mat);
						int r, g, b, a;
						r = (mat->diffuse[0] + 0.5) * 255.0;
						g = (mat->diffuse[1] + 0.5) * 255.0;
						b = (mat->diffuse[2] + 0.5) * 255.0;
						a = (mat->diffuse[3] + 0.5) * 255.0;
						if (r > 255)
							r = 255;
						if (g > 255)
							g = 255;
						if (b > 255)
							b = 255;
						if (a > 255)
							a = 255;
						color = ARGB(a,r,g,b);
					}
					else
						iStages = 0;
				}
				indices[j] = m->faceL[i].points[0];
				indices[j+1] = m->faceL[i].points[1];
				indices[j+2] = m->faceL[i].points[2];
				j = j + 3;
				iNumIndices += 3;
			}
			// build index list for last set
			blah.positions = verts;
			blah.normals = verts;
			blah.uvcoords = uvcoords;
			blah.numpoints = m->points;
			blah.numtexstages = 1;
			blah.indices = indices;
			blah.numindices = iNumIndices;
			s->SetTextureState(TextureState);
			s->SetDiffuseColor(color);
			s->AddIndexedBuffer(blah);
		}
		else
		{
			iStages = 0;
			j = 0;
			s->SetTextureState(NULL);
			for (i=0; i<m->faces; i = i++) 
			{
				indices[j] = m->faceL[i].points[0];
				indices[j+1] = m->faceL[i].points[1];
				indices[j+2] = m->faceL[i].points[2];
				j = j + 3;
			}
		}
		delete[] matName;

/*	    for (i=0; i<m->faces; i = i++) 
		{
			// check for a change in material data
			if (m->faceL[i].material[0])
			{
				if (strcmp(matName, m->faceL[i].material) != 0)
				{
					// material name has changed
					strcpy(matName, m->faceL[i].material);
				}
			}
		}*/

/*		blah.positions = verts;
		blah.normals = verts;
		blah.uvcoords = uvcoords;
		blah.numpoints = m->points;
		blah.numtexstages = iStages;
		blah.indices = indices;
		blah.numindices = m->faces * 3;*/
		
/*		if (m->faceL->material[0])
		{
			mat = lib3ds_file_material_by_name(f, m->faceL->material);
			TextureState = IdeRenderState_CreateRenderTexture();
			if (mat->texture1_map.name[0])
			{
				IdeResourceBase * rsc = IdeResourceManager_GetManager()->GetResource(mat->texture1_map.name, NULL);
				if (rsc)
				{
					IdeBitmap *BMP = (IdeBitmap*)rsc->GetRscInterface(IdeBitmap_GetRscInterfaceID());
					TextureState->Lock();
					TextureState->SetColorArg(0,1,IdeRenderTexture::TEXTUREARG_TEXTURE);
					TextureState->SetColorArg(0,2,IdeRenderTexture::TEXTUREARG_DIFFUSE);
					TextureState->SetColorOperation(0, IdeRenderTexture::TEXTUREOP_SELECTARG1);
					TextureState->SetBitmap(0,BMP);
					TextureState->Unlock();
					TextureState->SetWorldID(m_iWorld);
					BMP->Release();
					iStages = 1;
				}
			}
			int r, g, b, a;
			r = mat->diffuse[0] * 255.0;
			g = mat->diffuse[1] * 255.0;
			b = mat->diffuse[2] * 255.0;
			a = mat->diffuse[3] * 255.0;
			color = RGBA(r,g,b,a);
		}*/

//		s->SetDiffuseColor(color);
//		s->AddIndexedBuffer(blah);
//		TextureState->SetWorldID(m_iWorld);
		s->BuildIndexedBuffers();

		IdeSolidBrush * solidb = IdeSolidObject_CreateSolidBrush();
		deTransformInfo matrixI;
		deTransform matrix, matrixInv;
		deVec3d Left, Up, In, Translation;
		
		s->GetWorldTransform(matrixI);

		Left.x = m->matrix[0][0];
		Left.y = m->matrix[1][0];
		Left.z = m->matrix[2][0];

		In.x = m->matrix[0][1];
		In.y = m->matrix[1][1];
		In.z = m->matrix[2][1];

		Up.x = m->matrix[0][2];
		Up.y = m->matrix[1][2];
		Up.z = m->matrix[2][2];

		
		matrix.Reset();
		matrix.L = Left;
		matrix.U = Up;
		matrix.I = In;

		((deTransform&)matrixI).Multiply(matrix, matrixI);
		Lib3dsNode* node = lib3ds_file_node_by_name(f, m->name, LIB3DS_OBJECT_NODE);
		if (node)
		{
			Left.x = node->matrix[0][0];
			Left.y = node->matrix[1][0];
			Left.z = node->matrix[2][0];

			In.x = node->matrix[0][1];
			In.y = node->matrix[1][1];
			In.z = node->matrix[2][1];

			Up.x = node->matrix[0][2];
			Up.y = node->matrix[1][2];
			Up.z = node->matrix[2][2];

			
			matrix.Reset();
			matrix.L = Left;
			matrix.U = Up;
			matrix.I = In;

			matrix = matrix.GetTranspose();
			((deTransform&)matrixI).Multiply(matrix, matrixI);

			Left.x = m->matrix[0][0];
			Left.y = m->matrix[1][0];
			Left.z = m->matrix[2][0];

			In.x = m->matrix[0][1];
			In.y = m->matrix[1][1];
			In.z = m->matrix[2][1];

			Up.x = m->matrix[0][2];
			Up.y = m->matrix[1][2];
			Up.z = m->matrix[2][2];

			Translation.x = -node->data.object.pivot[0];
			Translation.y = -node->data.object.pivot[1];
			Translation.z = -node->data.object.pivot[2];

			matrix.Reset();
			matrix.Translation = Translation;
		}


		s->SetWorldTransform(matrixI);
		s->SetWorldID(m_iWorld);
		m_bNode->AddSolidObject(solidb);
		solidb->SetBrush(s);
		if (bAlpha)
			solidb->MakeTransparent();
		solidb->SetWorldID(m_iWorld);
		m_bNode->SetWorldID(m_iWorld);

		// free memory from index buffer lists
		delete[] verts;
		delete[] uvcoords;
		for (i = 0; i < indexArray.Length(); i++)
		{
			delete[] indexArray[i];
		}
/*		for (i = 0; i < textureArray.Length(); i++)
		{
			textureArray[i]->Release();
		}*/
//		lib3ds_node_free(node);
  }
#endif
//  lib3ds_mesh_free(m);
}

