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