I've downloaded what I think is the cvs head for the meshupgrader. It has the -b option, which I believe is the one that has been added to fix the bounding box issues for static meshes.
However when I try to run the upgrader with this option it asserts in the same location.
This is the code that I'm using (main.cpp in ogremeshupgrader). Can someone tell me if this is the right version to be using.
Code: Select all
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/
Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Lesser 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA, or go to
http://www.gnu.org/copyleft/lesser.txt.
You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "Ogre.h"
#include "OgreMeshSerializer.h"
#include "OgreSkeletonSerializer.h"
#include "OgreDefaultHardwareBufferManager.h"
#include "OgreHardwareVertexBuffer.h"
#include <iostream>
#include <sys/stat.h>
using namespace std;
using namespace Ogre;
void help(void)
{
// Print help message
cout << endl << "OgreMeshUpgrader: Upgrades .mesh files to the latest version." << endl;
cout << "Provided for OGRE by Steve Streeting 2004" << endl << endl;
cout << "Usage: OgreMeshUpgrader [-e] sourcefile [destfile] " << endl;
cout << "-i = Interactive mode, prompt for options" << endl;
cout << "-l lodlevels = number of LOD levels" << endl;
cout << "-d loddist = distance increment to reduce LOD" << endl;
cout << "-p lodpercent = Percentage triangle reduction amount per LOD" << endl;
cout << "-f lodnumtris = Fixed vertex reduction per LOD" << endl;
cout << "-e = DON'T generate edge lists (for stencil shadows)" << endl;
cout << "-t = Generate tangents (for normal mapping)" << endl;
cout << "-td [uvw|tangent]" << endl;
cout << " = Tangent vertex semantic destination (default tangent)" << endl;
cout << "-r = DON'T reorganise buffers to recommended format" << endl;
cout << "-d3d = Convert to D3D colour formats" << endl;
cout << "-gl = Convert to GL colour formats" << endl;
cout << "-srcd3d = Interpret ambiguous colours as D3D style" << endl;
cout << "-srcgl = Interpret ambiguous colours as GL style" << endl;
cout << "-E endian = Set endian mode 'big' 'little' or 'native' (default)" << endl;
cout << "-b = Recalculate bounding box (static meshes only)" << endl;
cout << "sourcefile = name of file to convert" << endl;
cout << "destfile = optional name of file to write to. If you don't" << endl;
cout << " specify this OGRE overwrites the existing file." << endl;
cout << endl;
}
struct UpgradeOptions
{
bool interactive;
bool suppressEdgeLists;
bool generateTangents;
VertexElementSemantic tangentSemantic;
bool dontReorganise;
bool destColourFormatSet;
VertexElementType destColourFormat;
bool srcColourFormatSet;
VertexElementType srcColourFormat;
unsigned short numLods;
Real lodDist;
Real lodPercent;
size_t lodFixed;
bool usePercent;
Serializer::Endian endian;
bool recalcBounds;
};
// Crappy globals
// NB some of these are not directly used, but are required to
// instantiate the singletons used in the dlls
LogManager* logMgr;
Math* mth;
MaterialManager* matMgr;
SkeletonManager* skelMgr;
MeshSerializer* meshSerializer;
SkeletonSerializer* skeletonSerializer;
DefaultHardwareBufferManager *bufferManager;
ResourceGroupManager* rgm;
MeshManager* meshMgr;
UpgradeOptions opts;
void parseOpts(UnaryOptionList& unOpts, BinaryOptionList& binOpts)
{
opts.interactive = false;
opts.suppressEdgeLists = false;
opts.generateTangents = false;
opts.tangentSemantic = VES_TANGENT;
opts.dontReorganise = false;
opts.endian = Serializer::ENDIAN_NATIVE;
opts.destColourFormatSet = false;
opts.srcColourFormatSet = false;
opts.lodDist = 500;
opts.lodFixed = 0;
opts.lodPercent = 20;
opts.numLods = 0;
opts.usePercent = true;
opts.recalcBounds = false;
UnaryOptionList::iterator ui = unOpts.find("-e");
opts.suppressEdgeLists = ui->second;
ui = unOpts.find("-t");
opts.generateTangents = ui->second;
ui = unOpts.find("-i");
opts.interactive = ui->second;
ui = unOpts.find("-r");
opts.dontReorganise = ui->second;
ui = unOpts.find("-d3d");
if (ui->second)
{
opts.destColourFormatSet = true;
opts.destColourFormat = VET_COLOUR_ARGB;
}
ui = unOpts.find("-gl");
if (ui->second)
{
opts.destColourFormatSet = true;
opts.destColourFormat = VET_COLOUR_ABGR;
}
ui = unOpts.find("-srcd3d");
if (ui->second)
{
opts.srcColourFormatSet = true;
opts.srcColourFormat = VET_COLOUR_ARGB;
}
ui = unOpts.find("-srcgl");
if (ui->second)
{
opts.srcColourFormatSet = true;
opts.srcColourFormat = VET_COLOUR_ABGR;
}
ui = unOpts.find("-b");
if (ui->second)
{
opts.recalcBounds = true;
}
BinaryOptionList::iterator bi = binOpts.find("-l");
if (!bi->second.empty())
{
opts.numLods = StringConverter::parseInt(bi->second);
}
bi = binOpts.find("-d");
if (!bi->second.empty())
{
opts.lodDist = StringConverter::parseReal(bi->second);
}
bi = binOpts.find("-p");
if (!bi->second.empty())
{
opts.lodPercent = StringConverter::parseReal(bi->second);
opts.usePercent = true;
}
bi = binOpts.find("-f");
if (!bi->second.empty())
{
opts.lodFixed = StringConverter::parseInt(bi->second);
opts.usePercent = false;
}
bi = binOpts.find("-E");
if (!bi->second.empty())
{
if (bi->second == "big")
opts.endian = Serializer::ENDIAN_BIG;
else if (bi->second == "little")
opts.endian = Serializer::ENDIAN_LITTLE;
else
opts.endian = Serializer::ENDIAN_NATIVE;
}
bi = binOpts.find("-td");
if (!bi->second.empty())
{
if (bi->second == "uvw")
opts.tangentSemantic = VES_TEXTURE_COORDINATES;
else // if (bi->second == "tangent"), or anything else
opts.tangentSemantic = VES_TANGENT;
}
}
String describeSemantic(VertexElementSemantic sem)
{
switch (sem)
{
case VES_POSITION:
return "Positions";
case VES_NORMAL:
return "Normals";
case VES_BLEND_WEIGHTS:
return "Blend Weights";
case VES_BLEND_INDICES:
return "Blend Indices";
case VES_DIFFUSE:
return "Diffuse";
case VES_SPECULAR:
return "Specular";
case VES_TEXTURE_COORDINATES:
return "Texture coordinates";
case VES_BINORMAL:
return "Binormals";
case VES_TANGENT:
return "Tangents";
};
return "";
}
void displayVertexBuffers(VertexDeclaration::VertexElementList& elemList)
{
// Iterate per buffer
unsigned short currentBuffer = 999;
unsigned short elemNum = 0;
VertexDeclaration::VertexElementList::iterator i, iend;
iend = elemList.end();
for (i = elemList.begin(); i != iend; ++i)
{
if (i->getSource() != currentBuffer)
{
currentBuffer = i->getSource();
cout << "> Buffer " << currentBuffer << ":" << endl;
}
cout << " - Element " << elemNum++ << ": " << describeSemantic(i->getSemantic());
if (i->getSemantic() == VES_TEXTURE_COORDINATES)
{
cout << " (index " << i->getIndex() << ")";
}
cout << endl;
}
}
// Sort routine for VertexElement
bool vertexElementLess(const VertexElement& e1, const VertexElement& e2)
{
// Sort by source first
if (e1.getSource() < e2.getSource())
{
return true;
}
else if (e1.getSource() == e2.getSource())
{
// Use ordering of semantics to sort
if (e1.getSemantic() < e2.getSemantic())
{
return true;
}
else if (e1.getSemantic() == e2.getSemantic())
{
// Use index to sort
if (e1.getIndex() < e2.getIndex())
{
return true;
}
}
}
return false;
}
void copyElems(VertexDeclaration* decl, VertexDeclaration::VertexElementList* elemList)
{
elemList->clear();
const VertexDeclaration::VertexElementList& origElems = decl->getElements();
VertexDeclaration::VertexElementList::const_iterator i, iend;
iend = origElems.end();
for (i = origElems.begin(); i != iend; ++i)
{
elemList->push_back(*i);
}
elemList->sort(VertexDeclaration::vertexElementLess);
}
// Utility function to allow the user to modify the layout of vertex buffers.
void reorganiseVertexBuffers(const String& desc, Mesh& mesh, VertexData* vertexData)
{
cout << endl << desc << ":- " << endl;
// Copy elements into a list
VertexDeclaration::VertexElementList elemList;
copyElems(vertexData->vertexDeclaration, &elemList);
bool finish = false;
bool anyChanges = false;
while (!finish)
{
displayVertexBuffers(elemList);
cout << endl;
cout << "Options: (a)utomatic" << endl;
cout << " (m)ove element" << endl;
cout << " (d)elete element" << endl;
cout << " (r)eset" << endl;
cout << " (f)inish" << endl;
String response = "";
while (response.empty())
{
cin >> response;
StringUtil::toLowerCase(response);
if (response == "m")
{
String moveResp;
cout << "Which element do you want to move (type number): ";
cin >> moveResp;
if (!moveResp.empty())
{
int eindex = StringConverter::parseInt(moveResp);
VertexDeclaration::VertexElementList::iterator movei = elemList.begin();
std::advance(movei, eindex);
cout << endl << "Move element " << eindex << "(" + describeSemantic(movei->getSemantic()) << ") to which buffer: ";
cin >> moveResp;
if (!moveResp.empty())
{
int bindex = StringConverter::parseInt(moveResp);
// Move (note offset will be wrong)
*movei = VertexElement(bindex, 0, movei->getType(),
movei->getSemantic(), movei->getIndex());
elemList.sort(vertexElementLess);
anyChanges = true;
}
}
}
else if (response == "a")
{
// Automatic
VertexDeclaration* newDcl =
vertexData->vertexDeclaration->getAutoOrganisedDeclaration(
mesh.hasSkeleton(), mesh.hasVertexAnimation());
copyElems(newDcl, &elemList);
HardwareBufferManager::getSingleton().destroyVertexDeclaration(newDcl);
anyChanges = true;
}
else if (response == "d")
{
String moveResp;
cout << "Which element do you want to delete (type number): ";
cin >> moveResp;
if (!moveResp.empty())
{
int eindex = StringConverter::parseInt(moveResp);
VertexDeclaration::VertexElementList::iterator movei = elemList.begin();
std::advance(movei, eindex);
cout << std::endl << "Delete element " << eindex << "(" + describeSemantic(movei->getSemantic()) << ")?: ";
cin >> moveResp;
StringUtil::toLowerCase(moveResp);
if (moveResp == "y")
{
elemList.erase(movei);
anyChanges = true;
}
}
}
else if (response == "r")
{
// reset
copyElems(vertexData->vertexDeclaration, &elemList);
anyChanges = false;
}
else if (response == "f")
{
// finish
finish = true;
}
else
{
response == "";
}
}
}
if (anyChanges)
{
String response;
while (response.empty())
{
displayVertexBuffers(elemList);
cout << "Really reorganise the vertex buffers this way?";
cin >> response;
StringUtil::toLowerCase(response);
if (response == "y")
{
VertexDeclaration* newDecl = HardwareBufferManager::getSingleton().createVertexDeclaration();
VertexDeclaration::VertexElementList::iterator i, iend;
iend = elemList.end();
unsigned short currentBuffer = 999;
size_t offset;
for (i = elemList.begin(); i != iend; ++i)
{
// Calc offsets since reorg changes them
if (i->getSource() != currentBuffer)
{
offset = 0;
currentBuffer = i->getSource();
}
newDecl->addElement(
currentBuffer,
offset,
i->getType(),
i->getSemantic(),
i->getIndex());
offset += VertexElement::getTypeSize(i->getType());
}
// Usages don't matter here since we're onlly exporting
BufferUsageList bufferUsages;
for (size_t u = 0; u <= newDecl->getMaxSource(); ++u)
bufferUsages.push_back(HardwareBuffer::HBU_STATIC_WRITE_ONLY);
vertexData->reorganiseBuffers(newDecl, bufferUsages);
}
else if (response == "n")
{
// do nothing
}
else
{
response = "";
}
}
}
}
// Utility function to allow the user to modify the layout of vertex buffers.
void reorganiseVertexBuffers(Mesh& mesh)
{
if (mesh.sharedVertexData)
{
if (opts.interactive)
reorganiseVertexBuffers("Shared Geometry", mesh, mesh.sharedVertexData);
else
{
// Automatic
VertexDeclaration* newDcl =
mesh.sharedVertexData->vertexDeclaration->getAutoOrganisedDeclaration(
mesh.hasSkeleton(), mesh.hasVertexAnimation());
if (*newDcl != *(mesh.sharedVertexData->vertexDeclaration))
{
// Usages don't matter here since we're onlly exporting
BufferUsageList bufferUsages;
for (size_t u = 0; u <= newDcl->getMaxSource(); ++u)
bufferUsages.push_back(HardwareBuffer::HBU_STATIC_WRITE_ONLY);
mesh.sharedVertexData->reorganiseBuffers(newDcl, bufferUsages);
}
}
}
Mesh::SubMeshIterator smIt = mesh.getSubMeshIterator();
unsigned short idx = 0;
while (smIt.hasMoreElements())
{
SubMesh* sm = smIt.getNext();
if (!sm->useSharedVertices)
{
if (opts.interactive)
{
StringUtil::StrStreamType str;
str << "SubMesh " << idx++;
reorganiseVertexBuffers(str.str(), mesh, sm->vertexData);
}
else
{
// Automatic
VertexDeclaration* newDcl =
sm->vertexData->vertexDeclaration->getAutoOrganisedDeclaration(
mesh.hasSkeleton(), mesh.hasVertexAnimation());
if (*newDcl != *(sm->vertexData->vertexDeclaration))
{
// Usages don't matter here since we're onlly exporting
BufferUsageList bufferUsages;
for (size_t u = 0; u <= newDcl->getMaxSource(); ++u)
bufferUsages.push_back(HardwareBuffer::HBU_STATIC_WRITE_ONLY);
sm->vertexData->reorganiseBuffers(newDcl, bufferUsages);
}
}
}
}
}
void vertexBufferReorg(Mesh& mesh)
{
String response;
if (opts.interactive)
{
// Check to see whether we would like to reorganise vertex buffers
std::cout << "\nWould you like to reorganise the vertex buffers for this mesh?";
while (response.empty())
{
cin >> response;
StringUtil::toLowerCase(response);
if (response == "y")
{
reorganiseVertexBuffers(mesh);
}
else if (response == "n")
{
// Do nothing
}
else
{
response = "";
}
}
}
else if (!opts.dontReorganise)
{
reorganiseVertexBuffers(mesh);
}
}
void buildLod(Mesh* mesh)
{
String response;
// Prompt for LOD generation?
bool genLod = false;
bool askLodDtls = false;
if (!opts.interactive) // derive from params if in batch mode
{
askLodDtls = false;
if (opts.numLods == 0)
{
genLod = false;
}
else
{
genLod = true;
}
}
else if(opts.numLods == 0) // otherwise only ask if not specified on command line
{
if (mesh->getNumLodLevels() > 1)
{
std::cout << "\nXML already contains level-of detail information.\n"
"Do you want to: (u)se it, (r)eplace it, or (d)rop it?";
while (response == "")
{
cin >> response;
StringUtil::toLowerCase(response);
if (response == "u")
{
// Do nothing
}
else if (response == "d")
{
mesh->removeLodLevels();
}
else if (response == "r")
{
genLod = true;
askLodDtls = true;
}
else
{
response = "";
}
}// while response == ""
}
else // no existing LOD
{
std::cout << "\nWould you like to generate LOD information? (y/n)";
while (response == "")
{
cin >> response;
StringUtil::toLowerCase(response);
if (response == "n")
{
// Do nothing
}
else if (response == "y")
{
genLod = true;
askLodDtls = true;
}
}
}
}
if (genLod)
{
unsigned short numLod;
ProgressiveMesh::VertexReductionQuota quota;
Real reduction;
Mesh::LodDistanceList distanceList;
if (askLodDtls)
{
cout << "\nHow many extra LOD levels would you like to generate?";
cin >> numLod;
cout << "\nWhat unit of reduction would you like to use:" <<
"\n(f)ixed or (p)roportional?";
cin >> response;
StringUtil::toLowerCase(response);
if (response == "f")
{
quota = ProgressiveMesh::VRQ_CONSTANT;
cout << "\nHow many vertices should be removed at each LOD?";
}
else
{
quota = ProgressiveMesh::VRQ_PROPORTIONAL;
cout << "\nWhat percentage of remaining vertices should be removed "
"\at each LOD (e.g. 50)?";
}
cin >> reduction;
if (quota == ProgressiveMesh::VRQ_PROPORTIONAL)
{
// Percentage -> parametric
reduction = reduction * 0.01f;
}
cout << "\nEnter the distance for each LOD to come into effect.";
Real distance;
for (unsigned short iLod = 0; iLod < numLod; ++iLod)
{
cout << "\nLOD Level " << (iLod+1) << ":";
cin >> distance;
distanceList.push_back(distance);
}
}
else
{
numLod = opts.numLods;
quota = opts.usePercent?
ProgressiveMesh::VRQ_PROPORTIONAL : ProgressiveMesh::VRQ_CONSTANT;
if (opts.usePercent)
{
reduction = opts.lodPercent * 0.01f;
}
else
{
reduction = opts.lodFixed;
}
Real currDist = 0;
for (unsigned short iLod = 0; iLod < numLod; ++iLod)
{
currDist += opts.lodDist;
distanceList.push_back(currDist);
}
}
mesh->generateLodLevels(distanceList, quota, reduction);
}
}
void checkColour(VertexData* vdata, bool &hasColour, bool &hasAmbiguousColour,
VertexElementType& originalType)
{
const VertexDeclaration::VertexElementList& elemList = vdata->vertexDeclaration->getElements();
for (VertexDeclaration::VertexElementList::const_iterator i = elemList.begin();
i != elemList.end(); ++i)
{
const VertexElement& elem = *i;
switch (elem.getType())
{
case VET_COLOUR:
hasAmbiguousColour = true;
case VET_COLOUR_ABGR:
case VET_COLOUR_ARGB:
hasColour = true;
originalType = elem.getType();
default:
// do nothing
;
};
}
}
void resolveColourAmbiguities(Mesh* mesh)
{
// Check what we're dealing with
bool hasColour = false;
bool hasAmbiguousColour = false;
VertexElementType originalType;
if (mesh->sharedVertexData)
{
checkColour(mesh->sharedVertexData, hasColour, hasAmbiguousColour, originalType);
}
for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
{
SubMesh* sm = mesh->getSubMesh(i);
if (sm->useSharedVertices == false)
{
checkColour(sm->vertexData, hasColour, hasAmbiguousColour, originalType);
}
}
String response;
if (hasAmbiguousColour)
{
if (opts.srcColourFormatSet)
{
originalType = opts.srcColourFormat;
}
else
{
// unknown input colour, have to ask
std::cout << "\nYour mesh has vertex colours but I don't know whether they were generated\n"
<< "using GL or D3D ordering. Please indicate which was used when the mesh was\n"
<< "created (type 'gl' or 'd3d').\n";
while (response.empty())
{
cin >> response;
StringUtil::toLowerCase(response);
if (response == "d3d")
{
originalType = VET_COLOUR_ARGB;
}
else if (response == "gl")
{
originalType = VET_COLOUR_ABGR;
}
else
{
response = "";
}
}
}
}
// Ask what format we want to save in
VertexElementType desiredType;
if (hasColour)
{
if (opts.destColourFormatSet)
{
desiredType = opts.destColourFormat;
}
else
{
if (opts.interactive)
{
response = "";
std::cout << "\nYour mesh has vertex colours, which can be stored in one of two layouts,\n"
<< "each of which will be slightly faster to load in a different render system.\n"
<< "Do you want to prefer Direct3D (d3d) or OpenGL (gl)?\n";
while (response.empty())
{
cin >> response;
StringUtil::toLowerCase(response);
if (response == "d3d")
{
desiredType = VET_COLOUR_ARGB;
}
else if (response == "gl")
{
desiredType = VET_COLOUR_ABGR;
}
else
{
response = "";
}
}
}
else
{
// 'do no harm'
return;
}
}
}
if (mesh->sharedVertexData && hasColour)
{
mesh->sharedVertexData->convertPackedColour(originalType, desiredType);
}
for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
{
SubMesh* sm = mesh->getSubMesh(i);
if (sm->useSharedVertices == false && hasColour)
{
sm->vertexData->convertPackedColour(originalType, desiredType);
}
}
}
void recalcBounds(const VertexData* vdata, AxisAlignedBox& aabb, Real& radius)
{
const VertexElement* posElem =
vdata->vertexDeclaration->findElementBySemantic(VES_POSITION);
const HardwareVertexBufferSharedPtr buf = vdata->vertexBufferBinding->getBuffer(
posElem->getSource());
void* pBase = buf->lock(HardwareBuffer::HBL_READ_ONLY);
for (size_t v = 0; v < vdata->vertexCount; ++v)
{
float* pFloat;
posElem->baseVertexPointerToElement(pBase, &pFloat);
Vector3 pos(pFloat[0], pFloat[1], pFloat[2]);
aabb.merge(pos);
radius = std::max(radius, pos.length());
pBase = static_cast<void*>(static_cast<char*>(pBase) + buf->getVertexSize());
}
buf->unlock();
}
void recalcBounds(Mesh* mesh)
{
AxisAlignedBox aabb;
Real radius = 0.0f;
if (mesh->sharedVertexData)
recalcBounds(mesh->sharedVertexData, aabb, radius);
for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i)
{
SubMesh* sm = mesh->getSubMesh(i);
if (!sm->useSharedVertices)
recalcBounds(sm->vertexData, aabb, radius);
}
mesh->_setBounds(aabb, false);
mesh->_setBoundingSphereRadius(radius);
}
int main(int numargs, char** args)
{
if (numargs < 2)
{
help();
return -1;
}
logMgr = new LogManager();
logMgr->createLog("OgreMeshUpgrade.log", true);
rgm = new ResourceGroupManager();
mth = new Math();
matMgr = new MaterialManager();
matMgr->initialise();
skelMgr = new SkeletonManager();
meshSerializer = new MeshSerializer();
skeletonSerializer = new SkeletonSerializer();
bufferManager = new DefaultHardwareBufferManager(); // needed because we don't have a rendersystem
meshMgr = new MeshManager();
// don't pad during upgrade
meshMgr->setBoundsPaddingFactor(0.0f);
UnaryOptionList unOptList;
BinaryOptionList binOptList;
unOptList["-i"] = false;
unOptList["-e"] = false;
unOptList["-t"] = false;
unOptList["-r"] = false;
unOptList["-gl"] = false;
unOptList["-d3d"] = false;
unOptList["-srcgl"] = false;
unOptList["-srcd3d"] = false;
unOptList["-b"] = false;
binOptList["-l"] = "";
binOptList["-d"] = "";
binOptList["-p"] = "";
binOptList["-f"] = "";
binOptList["-E"] = "";
binOptList["-td"] = "";
int startIdx = findCommandLineOpts(numargs, args, unOptList, binOptList);
parseOpts(unOptList, binOptList);
String source(args[startIdx]);
logMgr->createLog("OgreMeshUpgrader.log");
// Load the mesh
struct stat tagStat;
FILE* pFile = fopen( source.c_str(), "rb" );
if (!pFile)
{
OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND,
"File " + source + " not found.", "OgreMeshUpgrade");
}
stat( source.c_str(), &tagStat );
MemoryDataStream* memstream = new MemoryDataStream(source, tagStat.st_size, true);
fread( (void*)memstream->getPtr(), tagStat.st_size, 1, pFile );
fclose( pFile );
Mesh mesh(meshMgr, "conversion", 0, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
DataStreamPtr stream(memstream);
meshSerializer->importMesh(stream, &mesh);
// Write out the converted mesh
String dest;
if (numargs == startIdx + 2)
{
dest = args[startIdx + 1];
}
else
{
dest = source;
}
String response;
vertexBufferReorg(mesh);
// Deal with VET_COLOUR ambiguities
resolveColourAmbiguities(&mesh);
buildLod(&mesh);
// Make sure we generate edge lists, provided they are not deliberately disabled
if (!opts.suppressEdgeLists)
{
cout << "\nGenerating edge lists.." << std::endl;
mesh.buildEdgeList();
}
else
{
mesh.freeEdgeList();
}
// Generate tangents?
if (opts.generateTangents)
{
unsigned short srcTex, destTex;
bool existing = mesh.suggestTangentVectorBuildParams(opts.tangentSemantic, srcTex, destTex);
if (existing)
{
if (opts.interactive)
{
std::cout << "\nThis mesh appears to already have a set of tangents, " <<
"which would suggest tangent vectors have already been calculated. Do you really " <<
"want to generate new tangent vectors (may duplicate)? (y/n)";
while (response == "")
{
cin >> response;
StringUtil::toLowerCase(response);
if (response == "y")
{
// Do nothing
}
else if (response == "n")
{
opts.generateTangents = false;
}
else
{
response = "";
}
}
}
else
{
// safe
opts.generateTangents = false;
}
}
if (opts.generateTangents)
{
cout << "Generating tangent vectors...." << std::endl;
mesh.buildTangentVectors(opts.tangentSemantic, srcTex, destTex);
}
}
if (opts.recalcBounds)
recalcBounds(&mesh);
meshSerializer->exportMesh(&mesh, dest, opts.endian);
delete meshMgr;
delete skeletonSerializer;
delete meshSerializer;
delete skelMgr;
delete matMgr;
delete mth;
delete rgm;
delete logMgr;
return 0;
}