📄 lwo2mesh.cpp
字号:
#include "Vector3.h"
#include "lwo2mesh.h"
#include "Ogre.h"
#include "OgreMesh.h"
#include "OgreStringConverter.h"
#include "OgreDefaultHardwareBufferManager.h"
#if OGRE_PLATFORM == PLATFORM_LINUX
#include <math.h>
#include <float.h> // FLT_MIN, FLT_MAX
#include <libgen.h> // dirname(), basename().
#include <string.h> // strtok();
#include <string> // string class
#endif
#define POLYLIMIT 0x5555
#define POINTLIMIT 0x5555
extern Mesh::LodDistanceList distanceList;
extern Real reduction;
extern bool flags[NUMFLAGS];
extern MaterialSerializer* materialSerializer;
extern char *matPrefix;
extern ostream& nl(ostream& os);
#if OGRE_PLATFORM == PLATFORM_LINUX
/* We expect the caller to provide an arrays of chars for the output. */
void _splitpath( const char *_fn, char *_drive, char *_dir, char *_node, char *_ext ) {
/* A crazy mix of both c and c++.. */
const char *delimiters = ".";
char buf[ _MAX_DRIVE+_MAX_DIR+_MAX_FNAME+_MAX_EXT + 5 ];
char *exte, *ddir, *fnam, *_ext_tmp;
strcpy( buf, _fn );
strcpy( _drive, "" ); // _drive is always empth on linux.
if ( String( buf ).empty() ) {
strcpy( _node, "" );
strcpy( _dir, "" );
strcpy( _ext, "" );
return;
}
fnam = basename( buf );
strcpy( _node, fnam );
ddir = dirname( buf );
strcpy( _dir, ddir );
_ext_tmp = strtok( fnam, delimiters );
while ( ( _ext_tmp = strtok( NULL, delimiters ) ) != NULL ) exte = _ext_tmp;
strcpy( _ext, exte );
_node[ strlen(_node) - strlen(_ext) - 1 ] = '\0';
}
/* We expect the caller to provide an array of chars for the output. */
void _makepath( char *_fn, const char *_drive, const char *_dir,
const char *_node, const char *_ext ) {
/* A crazy mix of both c and c++.. */
std::string buf("");
if ( _drive != NULL ) // On Linux, this is usually empty.
buf += _drive;
if ( _dir != NULL ) { // The directory part.
if ( std::string(_dir).empty() )
buf += ".";
buf += _dir;
buf += "/";
}
if ( _node != NULL ) // The filename without the extension.
buf += _node;
if ( _ext != NULL ) { // The extension.
if ( std::string( _ext ).compare( 0, 1, "." ) != 0 )
buf += ".";
buf += _ext;
}
strcpy( _fn, buf.c_str() );
}
#endif
void Lwo2MeshWriter::doExportMaterials()
{
char
drive[ _MAX_DRIVE ],
dir[ _MAX_DIR ],
node[ _MAX_FNAME ],
ext[ _MAX_EXT ],
texname [128];
unsigned int slength = 0;
if (flags[RenameMaterials])
{
if (flags[UseInteractiveMethod])
{
for (unsigned int i = 0; i < object->surfaces.size(); ++i)
{
lwSurface *surface = object->surfaces[i];
cout << "Rename surface " << surface->name << " to: ";
cin >> texname;
surface->setname(texname);
}
} else {
_splitpath( dest, drive, dir, node, ext );
for (unsigned int i = 0; i < object->surfaces.size(); ++i)
{
lwSurface *surface = object->surfaces[i];
if (flags[UsePrefixMethod])
strcpy(texname,matPrefix);
else
{
strcpy(texname,node);
strcat(texname,"_");
}
strcat(texname, surface->name);
surface->setname(texname);
}
}
}
for (unsigned int i = 0; i < object->surfaces.size(); ++i)
{
lwSurface *surface = object->surfaces[i];
// Create deferred material so no load
Material* ogreMat = (Material*)MaterialManager::getSingleton().getByName(surface->name);
if (!ogreMat)
{
ogreMat = (Material*)MaterialManager::getSingleton().create(surface->name);
ogreMat->setAmbient
(
surface->color.rgb[0],
surface->color.rgb[1],
surface->color.rgb[2]
);
ogreMat->setDiffuse
(
surface->diffuse.val * surface->color.rgb[0],
surface->diffuse.val * surface->color.rgb[1],
surface->diffuse.val * surface->color.rgb[2],
1.0f
);
ogreMat->setSpecular
(
surface->specularity.val * surface->color.rgb[0],
surface->specularity.val * surface->color.rgb[1],
surface->specularity.val * surface->color.rgb[2],
1.0f
);
ogreMat->setShininess(surface->glossiness.val);
ogreMat->setSelfIllumination
(
surface->luminosity.val * surface->color.rgb[0],
surface->luminosity.val * surface->color.rgb[1],
surface->luminosity.val * surface->color.rgb[2]
);
for (unsigned int j = 0; j < surface->color.textures.size(); j++)
{
lwTexture *tex = surface->color.textures[j];
int cindex = tex->param.imap->cindex;
lwClip *clip = object->lwFindClip(cindex);
if (clip)
{
_splitpath( clip->source.still->name, drive, dir, node, ext );
_makepath( texname, 0, 0, node, ext );
ogreMat->getTechnique(0)->getPass(0)->createTextureUnitState(texname);
}
}
materialSerializer->queueForExport(ogreMat);
}
}
}
Skeleton *Lwo2MeshWriter::doExportSkeleton(const String &skelName, int l)
{
vpolygons bones;
bones.clear();
bones.reserve(256);
vpoints bonepoints;
bonepoints.clear();
bonepoints.reserve(512);
if (l == -1)
{
for (l = 0; l < object->layers.size(); ++l)
{
copyPoints(-1, ID_BONE, object->layers[l]->points, bonepoints);
copyPolygons(-1, ID_BONE, object->layers[l]->polygons, bones);
}
}
else
{
copyPoints(-1, ID_BONE, object->layers[l]->points, bonepoints);
copyPolygons(-1, ID_BONE, object->layers[l]->polygons, bones);
}
if (!bones.size()) return NULL; // no bones means no skeleton
Skeleton *ogreskel = new Skeleton(skelName);
unsigned int i;
// Create all the bones in turn
for (i = 0; i < bones.size(); ++i)
{
lwPolygon* bone = bones[i];
if (bone->vertices.size() != 2) continue; // a bone has only 2 sides
Bone* ogreBone = ogreskel->createBone("Bone");
Ogre::Vector3 bonePos(bone->vertices[0]->point->x, bone->vertices[0]->point->y, bone->vertices[0]->point->z);
ogreBone->setPosition(bonePos);
// Hmm, Milkshape has chosen a Euler angle representation of orientation which is not smart
// Rotation Matrix or Quaternion would have been the smarter choice
// Might we have Gimbal lock here? What order are these 3 angles supposed to be applied?
// Grr, we'll try our best anyway...
Quaternion qx, qy, qz, qfinal;
/*
qx.FromAngleAxis(msBoneRot[0], Vector3::UNIT_X);
qy.FromAngleAxis(msBoneRot[1], Vector3::UNIT_Y);
qz.FromAngleAxis(msBoneRot[2], Vector3::UNIT_Z);
*/
// Assume rotate by x then y then z
qfinal = qz * qy * qx;
ogreBone->setOrientation(qfinal);
}
/*
for (i = 0; i < numBones; ++i)
{
msBone* bone = msModel_GetBoneAt(pModel, i);
if (strlen(bone->szParentName) == 0)
{
}
else
{
Bone* ogrechild = ogreskel->getBone(bone->szName);
Bone* ogreparent = ogreskel->getBone(bone->szParentName);
if (ogrechild == 0)
{
continue;
}
if (ogreparent == 0)
{
continue;
}
// Make child
ogreparent->addChild(ogrechild);
}
}
// Create the Animation(s)
doExportAnimations(pModel, ogreskel);
// Create skeleton serializer & export
SkeletonSerializer serializer;
serializer.exportSkeleton(ogreskel, szFile);
ogreMesh->_notifySkeleton(ogreskel);
return ogreskel;
*/
delete ogreskel;
return NULL;
}
#define POSITION_BINDING 0
#define NORMAL_BINDING 1
#define TEXCOORD_BINDING 2
VertexData *Lwo2MeshWriter::setupVertexData(unsigned short vertexCount, VertexData *oldVertexData, bool deleteOldVertexData)
{
VertexData *vertexData = new VertexData();
if (oldVertexData)
{
// Basic vertex info
vertexData->vertexStart = oldVertexData->vertexStart;
vertexData->vertexCount = oldVertexData->vertexCount + vertexCount;
const VertexBufferBinding::VertexBufferBindingMap bindings = oldVertexData->vertexBufferBinding->getBindings();
VertexBufferBinding::VertexBufferBindingMap::const_iterator vbi, vbend;
vbend = bindings.end();
for (vbi = bindings.begin(); vbi != vbend; ++vbi)
{
HardwareVertexBufferSharedPtr srcbuf = vbi->second;
// create new buffer with the same settings
HardwareVertexBufferSharedPtr dstBuf =
HardwareBufferManager::getSingleton().createVertexBuffer(
srcbuf->getVertexSize(), srcbuf->getNumVertices() + vertexCount, srcbuf->getUsage(), srcbuf->isSystemMemory());
// copy data
dstBuf->copyData(*srcbuf, 0, 0, srcbuf->getSizeInBytes(), true);
// Copy binding
vertexData->vertexBufferBinding->setBinding(vbi->first, dstBuf);
}
// Copy elements
const VertexDeclaration::VertexElementList elems = oldVertexData->vertexDeclaration->getElements();
VertexDeclaration::VertexElementList::const_iterator ei, eiend;
eiend = elems.end();
for (ei = elems.begin(); ei != eiend; ++ei)
{
vertexData->vertexDeclaration->addElement(
ei->getSource(),
ei->getOffset(),
ei->getType(),
ei->getSemantic(),
ei->getIndex() );
}
if (deleteOldVertexData) delete oldVertexData;
}
else
{
vertexData->vertexCount = vertexCount;
VertexBufferBinding* bind = vertexData->vertexBufferBinding;
VertexDeclaration* decl = vertexData->vertexDeclaration;
decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION);
HardwareVertexBufferSharedPtr pbuf = HardwareBufferManager::getSingleton().createVertexBuffer(decl->getVertexSize(POSITION_BINDING), vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC, false);
bind->setBinding(POSITION_BINDING, pbuf);
decl->addElement(NORMAL_BINDING, 0, VET_FLOAT3, VES_NORMAL);
HardwareVertexBufferSharedPtr nbuf = HardwareBufferManager::getSingleton().createVertexBuffer(decl->getVertexSize(NORMAL_BINDING), vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC, false);
bind->setBinding(NORMAL_BINDING, nbuf);
decl->addElement(TEXCOORD_BINDING, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES);
HardwareVertexBufferSharedPtr tbuf = HardwareBufferManager::getSingleton().createVertexBuffer(decl->getVertexSize(TEXCOORD_BINDING), vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC, false);
bind->setBinding(TEXCOORD_BINDING, tbuf);
}
return vertexData;
}
void Lwo2MeshWriter::copyPoints(int surfaceIndex, unsigned long polygontype, vpoints &sourcepoints, vpoints &destpoints)
{
for (unsigned int i = 0; i < sourcepoints.size(); i++)
{
lwPoint *point = sourcepoints[i];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -