From d3a31a24ce860cb907defe2288bf5bfd7a9c871c Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 9 Jul 2012 20:53:54 -0700 Subject: [PATCH] Use proper strings and vectors instead of slice arrays for NIF files Slice arrays use pre-allocated pointers whose memory is managed externally. This is unnecessary and ultimately detrimental since it prevents any kind of data fixup (e.g. little endian to big endian, p[adding handling), and it also makes it difficult to use Ogre data streams. --- components/nif/controlled.hpp | 2 +- components/nif/data.hpp | 10 +-- components/nif/extra.hpp | 4 +- components/nif/nif_file.cpp | 8 +- components/nif/nif_file.hpp | 28 +++++-- components/nif/node.hpp | 8 +- components/nif/record.hpp | 2 +- components/nifbullet/bullet_nif_loader.cpp | 8 +- components/nifogre/ogre_nif_loader.cpp | 93 +++++++++++----------- 9 files changed, 86 insertions(+), 77 deletions(-) diff --git a/components/nif/controlled.hpp b/components/nif/controlled.hpp index 24281146f5..b9d84b58ab 100644 --- a/components/nif/controlled.hpp +++ b/components/nif/controlled.hpp @@ -53,7 +53,7 @@ public: class Named : public Controlled { public: - Misc::SString name; + std::string name; void read(NIFFile *nif) { diff --git a/components/nif/data.hpp b/components/nif/data.hpp index 0684470ec5..9cdbec537b 100644 --- a/components/nif/data.hpp +++ b/components/nif/data.hpp @@ -39,8 +39,8 @@ public: // internal (data is inside the nif itself) texture? bool external; - Misc::SString filename; // In case of external textures - NiPixelDataPtr data; // In case of internal textures + std::string filename; // In case of external textures + NiPixelDataPtr data; // In case of internal textures /* Pixel layout 0 - Palettised @@ -96,7 +96,7 @@ public: class ShapeData : public Record { public: - Misc::FloatArray vertices, normals, colors, uvlist; + std::vector vertices, normals, colors, uvlist; const Vector *center; float radius; @@ -131,7 +131,7 @@ class NiTriShapeData : public ShapeData { public: // Triangles, three vertex indices per triangle - Misc::SliceArray triangles; + std::vector triangles; void read(NIFFile *nif) { @@ -390,7 +390,7 @@ public: { const BoneTrafo *trafo; const Vector4 *unknown; - Misc::SliceArray weights; + std::vector weights; }; struct BoneInfoCopy { diff --git a/components/nif/extra.hpp b/components/nif/extra.hpp index ad788661af..e5829fdfc2 100644 --- a/components/nif/extra.hpp +++ b/components/nif/extra.hpp @@ -66,7 +66,7 @@ public: struct TextKey { float time; - Misc::SString text; + std::string text; }; std::vector list; @@ -93,7 +93,7 @@ public: "MRK" - marker, only visible in the editor, not rendered in-game "NCO" - no collision */ - Misc::SString string; + std::string string; void read(NIFFile *nif) { diff --git a/components/nif/nif_file.cpp b/components/nif/nif_file.cpp index 42aa43f8b1..35714bfbeb 100644 --- a/components/nif/nif_file.cpp +++ b/components/nif/nif_file.cpp @@ -46,8 +46,8 @@ using namespace Misc; void NIFFile::parse() { // Check the header string - const char* head = getString(40); - if(!begins(head, "NetImmerse File Format")) + std::string head = getString(40); + if(head.compare(0, 22, "NetImmerse File Format") != 0) fail("Invalid NIF header"); // Get BCD version @@ -70,7 +70,7 @@ void NIFFile::parse() for(int i=0;irecType != RC_MISSING); diff --git a/components/nif/nif_file.hpp b/components/nif/nif_file.hpp index bb6f732599..d3f5f7c06f 100644 --- a/components/nif/nif_file.hpp +++ b/components/nif/nif_file.hpp @@ -122,29 +122,41 @@ public: char getByte() { return getType(); } template - Misc::SliceArray getArrayLen(int num) - { return Misc::SliceArray((const X*)inp->getPtr(num*sizeof(X)),num); } + std::vector getArrayLen(int num) + { + std::vector v(num); + memcpy(&v[0], inp->getPtr(num*sizeof(X)), num*sizeof(X)); + return v; + } template - Misc::SliceArray getArray() + std::vector getArray() { int len = getInt(); return getArrayLen(len); } - Misc::SString getString() { return getArray(); } - const Vector *getVector() { return getPtr(); } const Matrix *getMatrix() { return getPtr(); } const Transformation *getTrafo() { return getPtr(); } const Vector4 *getVector4() { return getPtr(); } - Misc::FloatArray getFloatLen(int num) + std::vector getFloatLen(int num) { return getArrayLen(num); } // For fixed-size strings where you already know the size - const char *getString(int size) - { return (const char*)inp->getPtr(size); } + std::string getString(size_t size) + { + std::string str; + str.resize(size); + memcpy(&str[0], inp->getPtr(size), size); + return str.substr(0, str.find('\0')); + } + std::string getString() + { + size_t size = getInt(); + return getString(size); + } }; } // Namespace diff --git a/components/nif/node.hpp b/components/nif/node.hpp index 5a2847b6c2..9d99dbd1df 100644 --- a/components/nif/node.hpp +++ b/components/nif/node.hpp @@ -186,10 +186,10 @@ struct NiTriShape : Node NiTriShapeCopy clone() { NiTriShapeCopy copy; - copy.sname = name.toString(); - float *ptr = (float*)data->vertices.ptr; - float *ptrNormals = (float*)data->normals.ptr; - int numVerts = data->vertices.length / 3; + copy.sname = name; + float *ptr = (float*)&data->vertices[0]; + float *ptrNormals = (float*)&data->normals[0]; + int numVerts = data->vertices.size() / 3; for(int i = 0; i < numVerts; i++) { float *current = (float*) (ptr + i * 3); diff --git a/components/nif/record.hpp b/components/nif/record.hpp index 06fdce55e7..84f253eb89 100644 --- a/components/nif/record.hpp +++ b/components/nif/record.hpp @@ -90,7 +90,7 @@ struct Record { // Record type and type name int recType; - Misc::SString recName; + std::string recName; Record() : recType(RC_MISSING) {} diff --git a/components/nifbullet/bullet_nif_loader.cpp b/components/nifbullet/bullet_nif_loader.cpp index 30cb4562d0..9f31a3eed5 100644 --- a/components/nifbullet/bullet_nif_loader.cpp +++ b/components/nifbullet/bullet_nif_loader.cpp @@ -124,7 +124,7 @@ void ManualBulletShapeLoader::loadResource(Ogre::Resource *resource) if (node == NULL) { warn("First record in file was not a node, but a " + - r->recName.toString() + ". Skipping file."); + r->recName + ". Skipping file."); return; } @@ -292,10 +292,10 @@ void ManualBulletShapeLoader::handleNiTriShape(Nif::NiTriShape *shape, int flags Nif::NiTriShapeData *data = shape->data.getPtr(); - float* vertices = (float*)data->vertices.ptr; - unsigned short* triangles = (unsigned short*)data->triangles.ptr; + float* vertices = (float*)&data->vertices[0]; + unsigned short* triangles = (unsigned short*)&data->triangles[0]; - for(unsigned int i=0; i < data->triangles.length; i = i+3) + for(unsigned int i=0; i < data->triangles.size(); i = i+3) { Ogre::Vector3 b1(vertices[triangles[i+0]*3]*parentScale,vertices[triangles[i+0]*3+1]*parentScale,vertices[triangles[i+0]*3+2]*parentScale); Ogre::Vector3 b2(vertices[triangles[i+1]*3]*parentScale,vertices[triangles[i+1]*3+1]*parentScale,vertices[triangles[i+1]*3+2]*parentScale); diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 895c51a0d9..55dbba5185 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -399,7 +399,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std { // cout << "s:" << shape << "\n"; NiTriShapeData *data = shape->data.getPtr(); - SubMesh *sub = mesh->createSubMesh(shape->name.toString()); + SubMesh *sub = mesh->createSubMesh(shape->name); int nextBuf = 0; @@ -407,7 +407,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std // great. // Add vertices - int numVerts = data->vertices.length / 3; + int numVerts = data->vertices.size() / 3; sub->vertexData = new VertexData(); sub->vertexData->vertexCount = numVerts; sub->useSharedVertices = false; @@ -422,12 +422,12 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std if(flip) { - float *datamod = new float[data->vertices.length]; + float *datamod = new float[data->vertices.size()]; //std::cout << "Shape" << shape->name.toString() << "\n"; for(int i = 0; i < numVerts; i++) { int index = i * 3; - const float *pos = data->vertices.ptr + index; + const float *pos = &data->vertices[index]; Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2)); original = mTransform * original; mBoundingBox.merge(original); @@ -440,14 +440,14 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std } else { - vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, false); + vbuf->writeData(0, vbuf->getSizeInBytes(), &data->vertices[0], false); } VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding; bind->setBinding(nextBuf++, vbuf); - if (data->normals.length) + if (data->normals.size()) { decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL); vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( @@ -459,11 +459,11 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std Quaternion rotation = mTransform.extractQuaternion(); rotation.normalise(); - float *datamod = new float[data->normals.length]; + float *datamod = new float[data->normals.size()]; for(int i = 0; i < numVerts; i++) { int index = i * 3; - const float *pos = data->normals.ptr + index; + const float *pos = &data->normals[index]; Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2)); original = rotation * original; if (mNormaliseNormals) @@ -481,16 +481,16 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std } else { - vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, false); + vbuf->writeData(0, vbuf->getSizeInBytes(), &data->normals[0], false); } bind->setBinding(nextBuf++, vbuf); } // Vertex colors - if (data->colors.length) + if (data->colors.size()) { - const float *colors = data->colors.ptr; + const float *colors = &data->colors[0]; RenderSystem* rs = Root::getSingleton().getRenderSystem(); std::vector colorsRGB(numVerts); RGBA *pColour = &colorsRGB.front(); @@ -508,7 +508,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std bind->setBinding(nextBuf++, vbuf); } - if (data->uvlist.length) + if (data->uvlist.size()) { decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES); @@ -518,12 +518,12 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std if(flip) { - float *datamod = new float[data->uvlist.length]; + float *datamod = new float[data->uvlist.size()]; - for(unsigned int i = 0; i < data->uvlist.length; i+=2){ - float x = *(data->uvlist.ptr + i); + for(unsigned int i = 0; i < data->uvlist.size(); i+=2){ + float x = data->uvlist[i]; - float y = *(data->uvlist.ptr + i + 1); + float y = data->uvlist[i + 1]; datamod[i] =x; datamod[i + 1] =y; @@ -532,13 +532,12 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std delete [] datamod; } else - vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, false); + vbuf->writeData(0, vbuf->getSizeInBytes(), &data->uvlist[0], false); bind->setBinding(nextBuf++, vbuf); } // Triangle faces - The total number of triangle points - int numFaces = data->triangles.length; - + int numFaces = data->triangles.size(); if (numFaces) { @@ -558,7 +557,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std for (size_t i = 0; i < sub->indexData->indexCount; i+=3) { - const short *pos = data->triangles.ptr + index; + const short *pos = &data->triangles[index]; uint16 i0 = (uint16) *(pos+0); uint16 i1 = (uint16) *(pos+1); uint16 i2 = (uint16) *(pos+2); @@ -578,7 +577,7 @@ void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std } else - ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, false); + ibuf->writeData(0, ibuf->getSizeInBytes(), &data->triangles[0], false); sub->indexData->indexBuffer = ibuf; } @@ -706,8 +705,6 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou NiSourceTexture *st = t->textures[0].texture.getPtr(); if (st->external) { - SString tname = st->filename; - /* findRealTexture checks if the file actually exists. If it doesn't, and the name ends in .tga, it will try replacing the extension with .dds instead @@ -721,7 +718,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou problem since all the nif data is stored in a local throwaway buffer. */ - texName = "textures\\" + tname.toString(); + texName = "textures\\" + st->filename; findRealTexture(texName); } else warn("Found internal texture, ignoring."); @@ -795,9 +792,9 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou level. */ NiTriShapeData *data = shape->data.getPtr(); - int numVerts = data->vertices.length / 3; + int numVerts = data->vertices.size() / 3; - float *ptr = (float*)data->vertices.ptr; + float *ptr = (float*)&data->vertices[0]; float *optr = ptr; std::list vertexBoneAssignments; @@ -828,7 +825,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou std::vector vertexPosOriginal(numVerts, Ogre::Vector3::ZERO); std::vector vertexNormalOriginal(numVerts, Ogre::Vector3::ZERO); - float *ptrNormals = (float*)data->normals.ptr; + float *ptrNormals = (float*)&data->normals[0]; //the bone from skin->bones[boneIndex] is linked to skin->data->bones[boneIndex] //the first one contains a link to the bone, the second vertex transformation //relative to the bone @@ -849,13 +846,13 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou { if(mSkel.isNull()) { - std::cout << "No skeleton for :" << shape->skin->bones[boneIndex].name.toString() << std::endl; + std::cout << "No skeleton for :" << shape->skin->bones[boneIndex].name << std::endl; break; } //get the bone from bones array of skindata - if(!mSkel->hasBone(shape->skin->bones[boneIndex].name.toString())) + if(!mSkel->hasBone(shape->skin->bones[boneIndex].name)) std::cout << "We don't have this bone"; - bonePtr = mSkel->getBone(shape->skin->bones[boneIndex].name.toString()); + bonePtr = mSkel->getBone(shape->skin->bones[boneIndex].name); // final_vector = old_vector + old_rotation*new_vector*old_scale @@ -863,19 +860,19 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou Nif::NiSkinData::BoneInfoCopy boneinfocopy; boneinfocopy.trafo.rotation = convertRotation(it->trafo->rotation); boneinfocopy.trafo.trans = convertVector3(it->trafo->trans); - boneinfocopy.bonename = shape->skin->bones[boneIndex].name.toString(); + boneinfocopy.bonename = shape->skin->bones[boneIndex].name; boneinfocopy.bonehandle = bonePtr->getHandle(); copy.boneinfo.push_back(boneinfocopy); - for (unsigned int i=0; iweights.length; i++) + for (unsigned int i=0; iweights.size(); i++) { vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * convertVector3(it->trafo->trans); vecRot = bonePtr->_getDerivedOrientation() * convertRotation(it->trafo->rotation); - unsigned int verIndex = (it->weights.ptr + i)->vertex; + unsigned int verIndex = it->weights[i].vertex; //boneinfo.weights.push_back(*(it->weights.ptr + i)); Nif::NiSkinData::IndividualWeight ind; - ind.weight = (it->weights.ptr + i)->weight; + ind.weight = it->weights[i].weight; ind.boneinfocopyindex = copy.boneinfo.size() - 1; if(copy.vertsToWeights.find(verIndex) == copy.vertsToWeights.end()) { @@ -893,7 +890,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou { //apply transformation to the vertices Vector3 absVertPos = vecPos + vecRot * Vector3(ptr + verIndex *3); - absVertPos = absVertPos * (it->weights.ptr + i)->weight; + absVertPos = absVertPos * it->weights[i].weight; vertexPosOriginal[verIndex] = Vector3(ptr + verIndex *3); mBoundingBox.merge(absVertPos); @@ -903,10 +900,10 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou //apply rotation to the normals (not every vertex has a normal) //FIXME: I guessed that vertex[i] = normal[i], is that true? - if (verIndex < data->normals.length) + if (verIndex < data->normals.size()) { Vector3 absNormalsPos = vecRot * Vector3(ptrNormals + verIndex *3); - absNormalsPos = absNormalsPos * (it->weights.ptr + i)->weight; + absNormalsPos = absNormalsPos * it->weights[i].weight; vertexNormalOriginal[verIndex] = Vector3(ptrNormals + verIndex *3); for (int j=0; j<3; j++) @@ -918,7 +915,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou else { Vector3 absVertPos = vecPos + vecRot * vertexPosOriginal[verIndex]; - absVertPos = absVertPos * (it->weights.ptr + i)->weight; + absVertPos = absVertPos * it->weights[i].weight; Vector3 old = Vector3(ptr + verIndex *3); absVertPos = absVertPos + old; @@ -929,10 +926,10 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou //apply rotation to the normals (not every vertex has a normal) //FIXME: I guessed that vertex[i] = normal[i], is that true? - if (verIndex < data->normals.length) + if (verIndex < data->normals.size()) { Vector3 absNormalsPos = vecRot * vertexNormalOriginal[verIndex]; - absNormalsPos = absNormalsPos * (it->weights.ptr + i)->weight; + absNormalsPos = absNormalsPos * it->weights[i].weight; Vector3 oldNormal = Vector3(ptrNormals + verIndex *3); absNormalsPos = absNormalsPos + oldNormal; @@ -945,7 +942,7 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou VertexBoneAssignment vba; vba.boneIndex = bonePtr->getHandle(); vba.vertexIndex = verIndex; - vba.weight = (it->weights.ptr + i)->weight; + vba.weight = it->weights[i].weight; vertexBoneAssignments.push_back(vba); @@ -981,9 +978,9 @@ void NIFLoader::handleNiTriShape(NiTriShape *shape, int flags, BoundsFinder &bou } // Remember to rotate all the vertex normals as well - if (data->normals.length) + if (data->normals.size()) { - ptr = (float*)data->normals.ptr; + ptr = (float*)&data->normals[0]; for (int i=0; i::iterator textiter = extra->list.begin(); textiter != extra->list.end(); textiter++) { - std::string text = textiter->text.toString(); + std::string text = textiter->text; replace(text.begin(), text.end(), '\n', '/'); @@ -1138,7 +1135,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, if (!mSkel.isNull()) //if there is a skeleton { - std::string name = node->name.toString(); + std::string name = node->name; // Quick-n-dirty workaround for the fact that several // bones may have the same name. @@ -1192,7 +1189,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, } else if (node->recType == RC_NiTriShape && bNiTri) { - std::string nodename = node->name.toString(); + std::string nodename = node->name; if (triname == "") { @@ -1334,7 +1331,7 @@ void NIFLoader::loadResource(Resource *resource) if (node == NULL) { warn("First record in file was not a node, but a " + - r->recName.toString() + ". Skipping file."); + r->recName + ". Skipping file."); return; } @@ -1358,7 +1355,7 @@ void NIFLoader::loadResource(Resource *resource) if (f->timeStart >= 10000000000000000.0f) continue; - data->setBonename(o->name.toString()); + data->setBonename(o->name); data->setStartTime(f->timeStart); data->setStopTime(f->timeStop);