// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 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 Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #include "nel/misc/file.h" #include "nel/misc/path.h" #include "nel/3d/scene_group.h" #include "nel/3d/zone.h" #include "nel/3d/skeleton_shape.h" #include "nel/3d/register_3d.h" #include "nel/3d/mesh.h" #include "nel/3d/mesh_mrm.h" #include "nel/3d/mesh_mrm_skinned.h" #include "nel/3d/mesh_multi_lod.h" #ifdef NL_OS_WINDOWS #include #endif // NL_OS_WINDOWS #ifdef NL_OS_UNIX #include #include #include int _getch( ) { struct termios oldt, newt; int ch; tcgetattr( STDIN_FILENO, &oldt ); newt = oldt; newt.c_lflag &= ~( ICANON | ECHO ); tcsetattr( STDIN_FILENO, TCSANOW, &newt ); ch = getchar(); tcsetattr( STDIN_FILENO, TCSANOW, &oldt ); return ch; } #endif // NL_OS_UNIX using namespace std; using namespace NLMISC; using namespace NL3D; // *************************************************************************** void displayGeom(FILE *logStream, const CMeshGeom &geom) { uint i,j; uint numFaces=0; for(i=0;igetNbMaterial(); uint nLms= (uint)meshBase->_LightInfos.size(); MaxNumLightMap= max(MaxNumLightMap, nLms); if(nLms) { fprintf(logStream, "The Mesh has %d lightmaps for %d Materials\n", nLms, nMat ); for(uint i=0;i_LightInfos[i].LightGroup; string al= meshBase->_LightInfos[i].AnimatedLight; fprintf(logStream, " LightGroup=%d; AnimatedLight='%s'; mat/stage: ", lg, al.c_str()); std::list::iterator it= meshBase->_LightInfos[i].StageList.begin(); while(it!=meshBase->_LightInfos[i].StageList.end()) { fprintf(logStream, "%d/%d, ", it->MatId, it->StageId); it++; } fprintf(logStream, "\n"); } } else { fprintf(logStream, "The Mesh has %d Materials\n", nMat ); } fprintf(logStream, "The mesh has a LodCharacterTexture: %s\n", meshBase->getLodCharacterTexture()?"true":"false"); } // *************************************************************************** /// Dispaly info for file in stdout void displayInfoFileInStream(FILE *logStream, const char *fileName, const set &options, bool displayShortFileName) { if(fileName==NULL) return; bool ms = options.find ("-ms") != options.end(); bool vi = options.find ("-vi") != options.end(); bool vl = options.find ("-vl") != options.end(); bool vp = options.find ("-vp") != options.end(); bool veil = options.find ("-veil") != options.end(); // Special option. if( ms ) { if(strstr(fileName, ".shape")) { // read the skeleton. CIFile file(fileName); CShapeStream shapeStream; file.serial(shapeStream); // Test Type CMesh *mesh= dynamic_cast(shapeStream.getShapePointer()); // Mesh ?? if( mesh ) { if( mesh->getMeshGeom().isSkinned() ) { fprintf(logStream, "%s is Skinned, but without MRM!!!\n", fileName); } } // release delete shapeStream.getShapePointer(); shapeStream.setShapePointer(NULL); } } // Std Way. else { // some general info. if(displayShortFileName) { string sfn= CFile::getFilename(fileName); fprintf(logStream, "File: %s\n", sfn.c_str()); } else { fprintf(logStream, "File: %s\n", fileName); } fprintf(logStream, "***********\n\n"); if(strstr(fileName, ".zone")) { // read the zone. CIFile file(fileName); CZone zone; file.serial(zone); // retreive info on Zone CZoneInfo zoneInfo; zone.retrieve(zoneInfo); // display Info on the zone: fprintf(logStream, " Num Patchs: %d\n", zone.getNumPatchs() ); fprintf(logStream, " Num PointLights: %u\n", (uint)zoneInfo.PointLights.size() ); if (vl) { fprintf(logStream, " Lights\n"); uint k; for(k = 0; k < zoneInfo.PointLights.size(); ++k) { const CPointLightNamed &pl = zoneInfo.PointLights[k]; CRGBA diffuse = pl.getDiffuse(); CRGBA defaultDiffuse = pl.getDefaultDiffuse (); fprintf(logStream, " light group = %d, anim = \"%s\" x=%.1f, y=%.1f, z=%.1f, r=%d, g=%d, b=%d, dr=%d, dg=%d, db=%d\n", pl.LightGroup, pl.AnimatedLight.c_str(), pl.getPosition().x, pl.getPosition().y, pl.getPosition().z, diffuse.R, diffuse.G, diffuse.B, defaultDiffuse.R, defaultDiffuse.G, defaultDiffuse.B); } } if (vp) { CZoneInfo zoneInfo; zone.retrieve (zoneInfo); // Patch information uint k; for(k = 0; k < zoneInfo.Patchs.size(); ++k) { fprintf(logStream, " Patch %d, S %d, T %d, smooth flags %d %d %d %d, corner flags %d %d %d %d\n", k, zoneInfo.Patchs[k].OrderS, zoneInfo.Patchs[k].OrderT, zoneInfo.Patchs[k].getSmoothFlag (0), zoneInfo.Patchs[k].getSmoothFlag (1), zoneInfo.Patchs[k].getSmoothFlag (2), zoneInfo.Patchs[k].getSmoothFlag (3), zoneInfo.Patchs[k].getCornerSmoothFlag(0), zoneInfo.Patchs[k].getCornerSmoothFlag(1), zoneInfo.Patchs[k].getCornerSmoothFlag(2), zoneInfo.Patchs[k].getCornerSmoothFlag(3)); uint l; for (l=0; l<4; l++) { fprintf(logStream, " Bind edge %d, NPatchs %d, ZoneId %d, Next %d %d %d %d, Edge %d %d %d %d\n", l, zoneInfo.Patchs[k].BindEdges[l].NPatchs, zoneInfo.Patchs[k].BindEdges[l].ZoneId, zoneInfo.Patchs[k].BindEdges[l].Next[0], zoneInfo.Patchs[k].BindEdges[l].Next[1], zoneInfo.Patchs[k].BindEdges[l].Next[2], zoneInfo.Patchs[k].BindEdges[l].Next[3], zoneInfo.Patchs[k].BindEdges[l].Edge[0], zoneInfo.Patchs[k].BindEdges[l].Edge[1], zoneInfo.Patchs[k].BindEdges[l].Edge[2], zoneInfo.Patchs[k].BindEdges[l].Edge[3]); } } } } else if(strstr(fileName, ".ig")) { // read the ig. CIFile file(fileName); CInstanceGroup ig; file.serial(ig); // display Info on the ig: CVector gpos = ig.getGlobalPos(); fprintf(logStream, " Global pos : x = %.1f, y = %.1f, z =%.1f\n", gpos.x, gpos.y, gpos.z); fprintf(logStream, " Num Instances: %d\n", ig.getNumInstance() ); fprintf(logStream, " Num PointLights: %u\n", (uint)ig.getPointLightList().size() ); fprintf(logStream, " Realtime sun contribution = %s\n", ig.getRealTimeSunContribution() ? "on" : "off"); if (vi) { fprintf(logStream, " Instances:\n"); uint k; for(k = 0; k < ig._InstancesInfos.size(); ++k) { fprintf(logStream, " Instance %3d: shape = %s, name = %s, x = %.1f, y = %.1f, z = %.1f, sx = %.1f, sy = %.1f, sz = %.1f\n", k, ig._InstancesInfos[k].Name.c_str(), ig._InstancesInfos[k].InstanceName.c_str(), ig._InstancesInfos[k].Pos.x + gpos.x, ig._InstancesInfos[k].Pos.y + gpos.y, ig._InstancesInfos[k].Pos.z + gpos.z, ig._InstancesInfos[k].Scale.x, ig._InstancesInfos[k].Scale.y, ig._InstancesInfos[k].Scale.z); } } if (vl) { fprintf(logStream, " Lights:\n"); uint k; for(k = 0; k < ig.getNumPointLights(); ++k) { const CPointLightNamed &pl = ig.getPointLightNamed(k); CRGBA diffuse = pl.getDiffuse(); CRGBA defaultDiffuse = pl.getDefaultDiffuse (); fprintf(logStream, " Light %3d: Light group = %d, anim = \"%s\" x=%.1f, y=%.1f, z=%.1f, r=%d, g=%d, b=%d, dr=%d, dg=%d, db=%d\n", k, pl.LightGroup, pl.AnimatedLight.c_str(), pl.getPosition().x + gpos.x, pl.getPosition().y + gpos.y, pl.getPosition().z + gpos.z, diffuse.R, diffuse.G, diffuse.B, defaultDiffuse.R, defaultDiffuse.G, defaultDiffuse.B); } } if (veil) { fprintf(logStream, " Instances Bound To Lights:\n"); fprintf(logStream, " WordList:\n"); fprintf(logStream, " 'StaticLight Not Computed' means the instance has a ASP flag or the ig is not yet lighted\n"); fprintf(logStream, " If lighted, for each instance, the format is 'SunContribution(8Bit) - idLight0;idLight1 (or NOLIGHT) - LocalAmbientId (or GLOBAL_AMBIENT)' \n"); fprintf(logStream, " DCS means the instance don't cast shadow (used in the lighter)\n"); fprintf(logStream, " DCSINT Same but very special for ig_lighter only\n"); fprintf(logStream, " DCSEXT Same but very special for zone_lighter and zone_ig_lighter only\n"); fprintf(logStream, " ASP means the instance AvoidStaticLightPreCompute (used in the lighter)\n"); fprintf(logStream, " -------------------------------------------------------------\n"); uint k; for(k = 0; k < ig._InstancesInfos.size(); ++k) { CInstanceGroup::CInstance &instance= ig._InstancesInfos[k]; fprintf(logStream, " Instance %3d: ", k); if(!instance.StaticLightEnabled) fprintf(logStream, " StaticLight Not Computed."); else { fprintf(logStream, " %3d - ", instance.SunContribution); if(instance.Light[0]==0xFF) fprintf(logStream, "NOLIGHT - "); else { fprintf(logStream, "%3d;", instance.Light[0]); if(instance.Light[1]!=0xFF) fprintf(logStream, "%3d", instance.Light[1]); else fprintf(logStream, " "); //, instance.Light[1]); fprintf(logStream, " - "); } if(instance.LocalAmbientId==0xFF) fprintf(logStream, "GLOBAL_AMBIENT. "); else fprintf(logStream, "%d. ", instance.LocalAmbientId); } if(instance.DontCastShadow) fprintf(logStream, "DCS,"); if(instance.DontCastShadowForInterior) fprintf(logStream, "DCSINT,"); if(instance.DontCastShadowForExterior) fprintf(logStream, "DCSEXT,"); if(instance.AvoidStaticLightPreCompute) fprintf(logStream, "ASP,"); fprintf(logStream, "\n"); } } } else if(strstr(fileName, ".skel")) { // read the skeleton. CIFile file(fileName); CShapeStream shapeStream; file.serial(shapeStream); CSkeletonShape *skel= dynamic_cast(shapeStream.getShapePointer()); if(skel) { vector bones; skel->retrieve(bones); // Display Bone Infos. fprintf(logStream, "Num Bones: %u\n", (uint)bones.size()); for(uint i=0; i(shapeStream.getShapePointer()); CMeshMRM *meshMRM= dynamic_cast(shapeStream.getShapePointer()); CMeshMRMSkinned *meshMRMSkinned= dynamic_cast(shapeStream.getShapePointer()); CMeshMultiLod *meshMulti= dynamic_cast(shapeStream.getShapePointer()); // Material infos CMeshBase *meshBase= dynamic_cast(shapeStream.getShapePointer()); if(meshBase) { displayMeshBase(logStream, meshBase); } // Mesh ?? if( mesh ) { displayGeom(logStream, mesh->getMeshGeom()); } // MRM ?? else if( meshMRM ) { displayMRMGeom(logStream, meshMRM->getMeshGeom()); } else if( meshMRMSkinned ) { displayMRMSkinnedGeom(logStream, meshMRMSkinned->getMeshGeom()); } // MultiLod?? else if( meshMulti ) { uint numSlots= meshMulti->getNumSlotMesh (); fprintf(logStream, " Num Lods: %d\n", numSlots ); if(numSlots) { const CMeshGeom *meshGeom= dynamic_cast(&(meshMulti->getMeshGeom(0))); const CMeshMRMGeom *meshMRMGeom= dynamic_cast(&(meshMulti->getMeshGeom(0))); if( meshGeom ) displayGeom(logStream, *meshGeom); else if( meshMRMGeom ) displayMRMGeom(logStream, *meshMRMGeom); } } else { fprintf(logStream, "Unsupported .shape type for display info\n"); } // release delete shapeStream.getShapePointer(); shapeStream.setShapePointer(NULL); } else if(strstr(fileName, ".anim")) { // read the shape. CIFile file(fileName); CAnimation anim; file.serial(anim); // Enum the tracks std::set tracks; anim.getTrackNames (tracks); std::set::iterator ite = tracks.begin(); while (ite != tracks.end()) { // Track name fprintf(logStream, "Track name=%s", ite->c_str()); uint trackId = anim.getIdTrackByName (*ite); ITrack *track = anim.getTrack (trackId); if (track) { fprintf(logStream, " type=%s", typeid(*track).name()); UTrackKeyframer *keyFramer = dynamic_cast (track); if (keyFramer) { TAnimationTime begin = track->getBeginTime (); TAnimationTime end = track->getEndTime (); std::vector keys; keyFramer->getKeysInRange(begin, end, keys); if (!keys.empty()) { float fvalue; sint32 ivalue; CRGBA cvalue; CVector vvalue; CQuat qvalue; string svalue; bool bvalue; uint i; if (track->interpolate (begin, fvalue)) { fprintf(logStream, " floats\n"); for (i=0; iinterpolate (keys[i], fvalue)) fprintf(logStream, "\tKey %d : time=%f, value=%f\n", i, keys[i], fvalue); } } else if (track->interpolate (begin, ivalue)) { fprintf(logStream, " integers\n"); for (i=0; iinterpolate (keys[i], ivalue)) fprintf(logStream, "\tKey %d : time=%f, value=%d\n", i, keys[i], ivalue); } } else if (track->interpolate (begin, cvalue)) { fprintf(logStream, " color\n"); for (i=0; iinterpolate (keys[i], cvalue)) fprintf(logStream, "\tKey %d : time=%f, r=%d, g=%d, b=%d, a=%d\n", i, keys[i], cvalue.R, cvalue.G, cvalue.B, cvalue.A); } } else if (track->interpolate (begin, vvalue)) { fprintf(logStream, " vector\n"); for (i=0; iinterpolate (keys[i], vvalue)) fprintf(logStream, "\tKey %d : time=%f, x=%f, y=%f, z=%f\n", i, keys[i], vvalue.x, vvalue.y, vvalue.z); } } else if (track->interpolate (begin, qvalue)) { fprintf(logStream, " quaternion\n"); for (i=0; iinterpolate (keys[i], qvalue)) fprintf(logStream, "\tKey %d : time=%f, x=%f, y=%f, z=%f, w=%f\n", i, keys[i], qvalue.x, qvalue.y, qvalue.z, qvalue.w); } } else if (track->interpolate (begin, svalue)) { fprintf(logStream, " string\n"); for (i=0; iinterpolate (keys[i], svalue)) fprintf(logStream, "\tKey %d : time=%f, value=%s\n", i, keys[i], svalue.c_str()); } } else if (track->interpolate (begin, bvalue)) { fprintf(logStream, " bool\n"); for (i=0; iinterpolate (keys[i], bvalue)) fprintf(logStream, "\tKey %d : time=%f, value=%s\n", i, keys[i], bvalue?"true":"false"); } } } } } ite++; } } else { fprintf(logStream, "unsupported format\n"); } } } // *************************************************************************** // dispaly info for a file. void displayInfoFile(FILE *logStream, const char *fileName, const set &options, bool displayShortFileName) { // Display on screen. displayInfoFileInStream(stdout, fileName,options, displayShortFileName); // Display in log if(logStream) displayInfoFileInStream(logStream, fileName,options, displayShortFileName); } // *************************************************************************** /// Dispaly info cmd line int main(int argc, const char *argv[]) { registerSerial3d(); if(argc<2) { puts("Usage: ig_info file.??? [opt]"); puts("Usage: ig_info directory [opt]"); puts(" For now, only .ig, .zone, .skel, .shape are supported"); puts(" Results are displayed too in \"c:/temp/file_info.log\" "); puts(" [opt] can get: "); puts(" -ms display only a Warning if file is a .shape and is a Mesh, skinned, but without MRM"); puts(" -vi verbose instance information"); puts(" -vl verbose light information"); puts(" -vp verbose patche information"); puts(" -veil verbose instances bound to light extra information"); puts("Press any key"); _getch(); return -1; } // Parse options. set options; int i; for (i=2; i listFile; CPath::getPathContent (fileName, false, false, true, listFile); fprintf(stdout, "Scanning Directory '%s' .........\n\n\n", fileName); if(logStream) fprintf(logStream, "Scanning Directory '%s' .........\n\n\n", fileName); // For all files. for(uint i=0;i