/* =========================================================================== maya2q3 - export .md3 files from maya Copyright (C) 2005 HermitWorks Entertainment Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. =========================================================================== */ #include "common.h" #include "bsp-local.h" namespace bsp { class BspColorDumpCmd : public MPxCommand { public: static void* CDECL Creator() { return new BspColorDumpCmd; } static MSyntax CDECL SyntaxCreator() { MSyntax ret; ret.addFlag( "-cf", "-colorFill", MSyntax::kDouble, //r MSyntax::kDouble, //g MSyntax::kDouble //b ); ret.addArg( MSyntax::kString ); //path return ret; } virtual MStatus /* override */ doIt( const MArgList &argList ); private: void DoColorDump( const MArgList &argList ); void DoColorDump( std::iostream &stm, const MDagPathArray &paths, bool colorFill, byte fillColor[4] ); void DoColorDump( std::vector< q3::drawVert_t > &verts, const MDagPath &path ); }; MStatus BspColorDumpCmd::doIt( const MArgList &argList ) { try { DoColorDump( argList ); return MStatus::kSuccess; } catch( std::exception &ex ) { MGlobal::displayError( MString( ex.what() ) ); return MStatus::kFailure; } catch( ... ) { MGlobal::displayError( "An error occurred." ); return MStatus::kFailure; } } void BspColorDumpCmd::DoColorDump( const MArgList &argList ) { MStatus stat; MArgDatabase args( syntax(), argList, &stat ); check_status( stat ); MString path; stat = args.getCommandArgument( 0, path ); check_status( stat ); byte fillColor[4]; bool doFill = args.isFlagSet( "-cf", &stat ); check_status( stat ); if( doFill ) { double r, g, b; stat = args.getFlagArgument( "-cf", 0, r ); check_status( stat ); stat = args.getFlagArgument( "-cf", 1, g ); check_status( stat ); stat = args.getFlagArgument( "-cf", 2, b ); check_status( stat ); fillColor[0] = (byte)clamp( r * 0xFF, 0.0, (double)0xFF ); fillColor[1] = (byte)clamp( g * 0xFF, 0.0, (double)0xFF ); fillColor[2] = (byte)clamp( b * 0xFF, 0.0, (double)0xFF ); fillColor[3] = 0xFF; } MDagPathArray meshes; MItDag iter( MItDag::kBreadthFirst, MFn::kInvalid, &stat ); check_status( stat ); for( ; ; ) { bool done = iter.isDone( &stat ); check_status( stat ); if( done ) break; MDagPath path; stat = iter.getPath( path ); check_status( stat ); //move to the next one now that we have the current so we //can freely use continue to skip ahead stat = iter.next(); check_status( stat ); MObject node = path.node( &stat ); check_status( stat ); if( node.apiType() != MFn::kMesh ) continue; MFnDagNode dagNode( node, &stat ); check_status( stat ); bool intermediate = dagNode.isIntermediateObject( &stat ); check_status( stat ); if( intermediate ) continue; meshes.append( path ); } std::fstream file; file.open( path.asChar(), std::ios::in | std::ios::out | std::ios::binary ); DoColorDump( file, meshes, doFill, fillColor ); file.close(); } void BspColorDumpCmd::DoColorDump( std::iostream &stm, const MDagPathArray &paths, bool colorFill, byte fillColor[4] ) { size_t base_pos = stm.tellg(); q3::dheader_t header; stm.read( (char*)&header, sizeof( q3::dheader_t ) ); const q3::lump_t &lVerts = header.lumps[q3::LUMP_DRAWVERTS]; if( lVerts.filelen % sizeof( q3::drawVert_t ) ) throw std::exception( "Funny lump size." ); std::vector< q3::drawVert_t > verts( lVerts.filelen / sizeof( q3::drawVert_t ) ); stm.seekg( base_pos + lVerts.fileofs, std::ios_base::beg ); stm.read( (char*)&verts[0], lVerts.filelen ); if( colorFill ) { for( size_t i = 0; i < verts.size(); i++ ) { verts[i].color[0] = fillColor[0]; verts[i].color[1] = fillColor[1]; verts[i].color[2] = fillColor[2]; verts[i].color[3] = fillColor[3]; } } for( uint i = 0; i < paths.length(); i++ ) DoColorDump( verts, paths[i] ); stm.seekg( base_pos + lVerts.fileofs, std::ios_base::beg ); stm.write( (const char*)&verts[0], lVerts.filelen ); } void BspColorDumpCmd::DoColorDump( std::vector< q3::drawVert_t > &verts, const MDagPath &path ) { MStatus stat; MFnMesh mesh( path, &stat ); check_status( stat ); MString colorSet( McVertexLightSet ); MStringArray colorNames; stat = mesh.getColorSetNames( colorNames ); check_status( stat ); bool hasSet = false; for( uint i = 0; i < colorNames.length(); i++ ) { if( colorNames[i] == colorSet ) { hasSet = true; break; } } if( !hasSet ) return; MColorArray colors; stat = mesh.getColors( colors, &colorSet ); check_status( stat ); MString attrName( BdSourceVertexAttr ); MObject meshObj = path.node( &stat ); check_status( stat ); MItMeshFaceVertex iter( meshObj, &stat ); check_status( stat ); for( ; ; ) { bool done = iter.isDone( &stat ); check_status( stat ); if( done ) break; int faceId = iter.faceId( &stat ); check_status( stat ); int faceVertId = iter.faceVertId( &stat ); check_status( stat ); int vertId = iter.vertId( &stat ); check_status( stat ); //move to the next one now that we have the current so we //can freely use continue to skip ahead stat = iter.next(); check_status( stat ); int blindIndex; stat = mesh.getFaceVertexBlindDataIndex( faceId, vertId, blindIndex ); check_status( stat ); int sourceVert; stat = mesh.getIntBlindData( blindIndex, MFn::kMeshFaceVertComponent, BdSourceVertexId, attrName, sourceVert ); if( !stat || sourceVert < 0 || (size_t)sourceVert >= verts.size() ) continue; int colorIdx; stat = mesh.getColorIndex( faceId, faceVertId, colorIdx, &colorSet ); if( !stat ) continue; MColor cl = colors[colorIdx]; q3::drawVert_t &v = verts[sourceVert]; v.color[0] = (byte)clamp( cl.r * 0xFF, 0.0F, (float)0xFF ); v.color[1] = (byte)clamp( cl.g * 0xFF, 0.0F, (float)0xFF ); v.color[2] = (byte)clamp( cl.b * 0xFF, 0.0F, (float)0xFF ); v.color[3] = 0xFF; } } const char *g_clDmpCmdName = "bspColorDump"; void* (CDECL *g_clDmpCmdCreator)() = &BspColorDumpCmd::Creator; MSyntax (CDECL *g_clDmpSyntaxCreator)() = &BspColorDumpCmd::SyntaxCreator; };