treemagik 1.0b to irrlicht

A forum to store posts deemed exceptionally wise and useful
Post Reply
drac_gd
Posts: 132
Joined: Sun Apr 09, 2006 8:43 pm

treemagik 1.0b to irrlicht

Post by drac_gd »

first off the trees generated by treemagik are not very good. If you have the money or the skills another method would probably be better ( I have neither ) I'm a programmer Jim not a artist.

treemagik can be found at

http://gdlib.net/index.php?name=Downloa ... ails&id=29

from another thread

1. made a tree in treemagik, saved the media and .x file (if it ask you how to save the mesh: answer both with "1" )

2. downloaded a program called "LithUnwrap". you can find it here (rightclick/save as ..):
http://mitglied.lycos.de/animespy2003/d ... _setup.zip

3. downloaded meshviewer. you can find it here (rightclick/save as ..):
http://mitglied.lycos.de/animespy2003/d ... /mview.zip

note: can someone please mirror this files? i dont have much traffic or tripod will lock/bann my account

4. opened the .x exported mesh from treemagik in lithunwrap (file/model/open)

5. optimized the model (tools/optimize model) but you dont have to do it

6. saved the model (file/model/save) as text (but binary works too i guess)

7. opened the mesh in Mview (DirectX Meshviewer) and saved it as text.

8. loaded it in irrlicht (you dont have to set texture mapping). the textures have to be in the same folder as the meshfile.

9. ignore the errors in the console

Now comes more fun. I couldnt get the alpha channel to show and so this is what I did.

1. )convert the chunk files exported by treemagic to 32 bit tga files
I opened them in windows paint.. saved as 24bit bmp then opened in photoshop and added alpha channel and saved as tga

2. ) edit your directx treefile with notepad or whatever and change the file name extension in the TextureFilename part of the .x file to be .tga instead of bmp

3. ) In CXAnimatedPlayer.cpp make the following changes so that textures with alpha channels use the alpha channel by default

Code: Select all

video::SMaterial CXAnimationPlayer::getMaterialFromXMaterial(CXFileReader::SXMaterial& xmat)
{
	video::SMaterial mat;
	mat.EmissiveColor = xmat.Emissive.toSColor();
	mat.DiffuseColor = xmat.FaceColor.toSColor();
	mat.SpecularColor = xmat.Specular.toSColor();
	mat.Shininess = xmat.Power;
	
	//if (mat.Shininess > core::ROUNDING_ERROR)
	//	mat. TODO: enable specular highlights

	if (xmat.TextureFileName.size() != 0)
	{
		mat.Texture1 = Driver->getTexture(getTextureFileName(xmat.TextureFileName).c_str());
		if (mat.Texture1 == 0)
			mat.Texture1 = Driver->getTexture(xmat.TextureFileName.c_str());
		//brj added so defaults to using alpha channel if available
		irr::video::ECOLOR_FORMAT eColorFormat = mat.Texture1->getColorFormat();
		if( (eColorFormat == irr::video::ECF_A1R5G5B5) || ( eColorFormat == irr::video::ECF_A8R8G8B8 ) )
		{
			mat.MaterialType = irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL;
		}
		//brj end of addition
	}

	return mat;
}
recompile and run.. should work now :)

EDIT when you make the alpha channel mask its sometimes tricky so I made a fuction to set the black background to transparent.. It only works if the tga file is 32 bit color (RGBA) and will probably not work with big endian OS.
EDIT AGAIN after midnights snide remark I thought I should explain the
function TgaSetColorToTransparent.. It was not ment to be put in irrlicht or your app. I just thought it might be handy.. It was easier for me to make this function to call and modify the tga file from my mesh viewer than to to get photoshop's magic wand to select correctly an make the the alpha channel mask perfect.

Code: Select all

//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// Header of tga type bitmap file
//
#pragma pack(1)
typedef struct typeTgaHeader 
{
	unsigned char 	ucIdLength;
	unsigned char   ucColormapType;
	unsigned char	ucImageType;
	unsigned short	usFirstColormapIndex;
	unsigned short	usColormapLength;
	unsigned char	ucColormapSize;
	unsigned short	usXOrigin;
	unsigned short  usYOrigin;
	unsigned short  usWidth;
	unsigned short	usHeight;
	unsigned char	ucBitsPerPixel;
	unsigned char	ucAttributes;
}TgaHeader;
#pragma pack()

class TmpColor32
{
public:
	unsigned char u8Red;
	unsigned char u8Green;
	unsigned char u8Blue;
	unsigned char u8Alpha;
};

//-----------------------------------------------------------------------------
//! sets the alpha channel of the given color to transparent
int TgaSetColorToTransparent( const char * pFileName, unsigned char u8Red, unsigned char u8Green, unsigned char u8Blue )
{
	TgaHeader * pgHdr;
	FILE * pgFile;
	pgFile = fopen( pFileName, "rb+" );
	if( 0 == pgFile )
	{
		// couldnt open file
		return -1;
	}
	fseek( pgFile, 0, SEEK_END );
	unsigned long u32Len = ftell( pgFile );
	if( 0 == u32Len )
	{
		// error getting file size
		fclose( pgFile );
		return -1;
	}
	fseek( pgFile, 0, SEEK_SET );
	char * pTgaMem = new char[ u32Len ];
	if( u32Len != fread( pTgaMem, 1, u32Len, pgFile ) )
	{
		// failed reading file
		delete pTgaMem;
		fclose( pgFile );
		return -1;
	}
	pgHdr = (TgaHeader *)pTgaMem;
	if( pgHdr->ucBitsPerPixel != 32 )
	{
		// we dont handle anything but 32 bit color
		delete pTgaMem;
		fclose( pgFile );
		return -1;
	}
	TmpColor32 * pgColors = (TmpColor32 *) (pTgaMem + sizeof( TgaHeader ));
	for( int iRow = 0; iRow < pgHdr->usHeight; iRow++ )
	{
		for( int iCol = 0; iCol < pgHdr->usWidth; iCol++ )
		{
			if( (pgColors->u8Red == u8Red) &&
				(pgColors->u8Green == u8Green) &&
				(pgColors->u8Blue == u8Blue) )
			{
				pgColors->u8Alpha = 0x00;
			}
			pgColors++;
		}
	}
	// write out the changes
	fseek( pgFile, 0, SEEK_SET );
	if( u32Len != fwrite( pTgaMem, 1,u32Len, pgFile ) )
	{
		// failed reading file
		delete pTgaMem;
		fclose( pgFile );
		return -1;
	}
	delete pTgaMem;
	fclose( pgFile );
	return 0;
}


This next section I posted before but it was ignored so I am posting here again. This section is not neccessary for treemagik objects. only multi mesh complex directx objects

If when you load a multi part direct x model the pieces are all out of place it is because some exporters export empty subframes and irrlicht does not handle it correctly. I added some code to fix this but its a hack. Hopefully someone will eventually fix it correctly. Opening the file in mview.exe then saving also usually fixes this.

Add

Code: Select all

	//! loop through hiearchy and combine frames that have no mesh or name into parent frame
	void optimizeFrames( SXFrame * pgCurFrame,  SXFrame * pgParent );
	bool m_bFrameRemoved;

to CXFileReader.h

In CXFileReader.cpp change function parseFile

Code: Select all

//! Parses the file
bool CXFileReader::parseFile()
{
	while(parseDataObject())
	{
		// loop
	}
	//brj loop through hiearchy and combine frames that have no mesh
	// and no name into its parent
	
	u32 u32Idx;
	m_bFrameRemoved = false;
	for( u32Idx = 0; u32Idx < RootFrames.size(); u32Idx++ )
	{
		optimizeFrames( &RootFrames[ u32Idx ], 0 );
	}
	while( m_bFrameRemoved )
	{
		m_bFrameRemoved = false;
		for( u32Idx = 0; u32Idx < RootFrames.size(); u32Idx++ )
		{
			optimizeFrames( &RootFrames[ u32Idx ], 0 );
		}
	}
	return true;
}
last add the optimize function

Code: Select all

//-----------------------------------------------------------------------------
//! loop through hiearchy and combine frames that have no mesh or name into parent frame
void CXFileReader::optimizeFrames( SXFrame * pgFrame,  SXFrame * pgParent )
{
	if( pgParent )
	{
		if( (0 == pgParent->Meshes.size()) &&
			(0 == strlen( pgFrame->Name.c_str() )) &&
			strlen( pgParent->Name.c_str() ) )
		{
			// combine this frame with parent
			// add child frames to parent
			pgParent->LocalMatrix = pgParent->LocalMatrix * pgFrame->LocalMatrix;
			for( u32 c=0; c<pgFrame->ChildFrames.size(); ++c )
			{
				// add child frames to parent
				for (u32 c=0; c<pgFrame->ChildFrames.size(); ++c)
				{
					pgParent->ChildFrames.push_back(pgFrame->ChildFrames[c]);
				}
			}
			// add meshes to parent
			for( u32 c=0; c<pgFrame->Meshes.size(); ++c )
			{
				// add meshes frames to parent
				pgParent->Meshes.push_back( pgFrame->Meshes[c] );
			}

			// remove child fames in our list
			pgFrame->ChildFrames.clear();
			// remove meshes
			pgFrame->Meshes.clear();

			// find ourselve and remove from parent frame
			for( u32 c=0; c< pgParent->ChildFrames.size(); ++c )
			{
				if( &pgParent->ChildFrames[c] == pgFrame )
				{
					//found ourself
					pgParent->ChildFrames.erase( c, 1 );
					m_bFrameRemoved = true;
					return;
				}
			}
		}
	}
	for (u32 c=0; c<pgFrame->ChildFrames.size(); ++c)
		optimizeFrames( &pgFrame->ChildFrames[c], pgFrame );
}
Last edited by drac_gd on Wed Dec 27, 2006 1:47 pm, edited 3 times in total.
Midnight
Posts: 1772
Joined: Fri Jul 02, 2004 2:37 pm
Location: Wonderland

Post by Midnight »

holy crap that is a lot for a simple alpha channel. :shock:
drac_gd
Posts: 132
Joined: Sun Apr 09, 2006 8:43 pm

Post by drac_gd »

Thanks midnight for your helpful reply.. If you dont like the code dont use it. No one is twisting your arm
Post Reply