diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 8b06dec49..a58a851f2 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -48,7 +48,7 @@ namespace MWClass const std::string &model = ref->base->model; assert (ref->base != NULL); if(!model.empty()){ - physics.insertActorPhysics(ptr, "meshes\\" + model); + // physics.insertActorPhysics(ptr, "meshes\\" + model); } } diff --git a/components/nifogre/ogre_nif_loader.cpp b/components/nifogre/ogre_nif_loader.cpp index 6db23c5ce..796ece5be 100644 --- a/components/nifogre/ogre_nif_loader.cpp +++ b/components/nifogre/ogre_nif_loader.cpp @@ -1103,7 +1103,7 @@ void NIFLoader::handleNode(Nif::Node *node, int flags, handleNode(&list[i], flags, node->trafo, bounds, bone, boneSequence); } } - else if (node->recType == RC_NiTriShape) + else if (node->recType == RC_NiTriShape && bNiTri) { std::string nodename = node->name.toString(); @@ -1128,6 +1128,10 @@ void NIFLoader::loadResource(Resource *resource) flip = false; name = resource->getName(); char suffix = name.at(name.length() - 2); + bool addAnim = true; + bool hasAnim = false; + bool baddin = false; + bNiTri = true; if(suffix == '*') { @@ -1144,12 +1148,12 @@ void NIFLoader::loadResource(Resource *resource) } else if(suffix == '>') { - - //bNiTri = false; - //baddin = true; + baddin = true; + bNiTri = false; std::string sub = name.substr(name.length() - 6, 4); - //if(sub.compare("0000") != 0) - // addAnim = false; + + if(sub.compare("0000") != 0) + addAnim = false; } @@ -1233,7 +1237,31 @@ void NIFLoader::loadResource(Resource *resource) handleNode(node, 0, NULL, bounds, 0, boneSequence); + if(addAnim) + { + for(int i = 0; i < nif.numRecords(); i++) + { + Nif::NiKeyframeController *f = dynamic_cast(nif.getRecord(i)); + Nif::Node *n = dynamic_cast(nif.getRecord(i)); + if(f != NULL) + { + hasAnim = true; + Nif::Node *o = dynamic_cast(f->target.getPtr()); + Nif::NiKeyframeDataPtr data = f->data; + + if (f->timeStart == FLT_MAX) + continue; + data->setBonename(o->name.toString()); + data->setStartTime(f->timeStart); + data->setStopTime(f->timeStop); + + allanim.push_back(data.get()); + + + } + } + } // set the bounding value. if (bounds.isValid()) { @@ -1241,13 +1269,45 @@ void NIFLoader::loadResource(Resource *resource) bounds.maxX(), bounds.maxY(), bounds.maxZ())); mesh->_setBoundingSphereRadius(bounds.getRadius()); } + if(hasAnim && addAnim){ + //std::cout << "Lower" << lowername << "\n"; + //std::cout << "Adding the animations\n"; + allanimmap[name] = allanim; + alltextmappings[name] = textmappings; + } + if(!mSkel.isNull() && shapes.size() > 0 && addAnim) + { + allshapesmap[name] = shapes; + } + if(baddin){ + /*if(addAnim){ + if(isBeast) + npcknaSkel = mSkel; + else + npcSkel = mSkel; + }*/ + for(int i = 0; i < addin.size(); i++){ + insertMeshInsideBase(addin[i]); + } + addin.clear(); + } + if(flip){ + mesh->_setBounds(mBoundingBox, false); + } if (!mSkel.isNull()) { mesh->_notifySkeleton(mSkel); } + flip = false; } +void NIFLoader::addInMesh(Ogre::Mesh* input){ + addin.push_back(input); +} + + + MeshPtr NIFLoader::load(const std::string &name, const std::string &group) { @@ -1266,6 +1326,276 @@ MeshPtr NIFLoader::load(const std::string &name, return themesh; } +/* +This function shares much of the same code handleShapes() in MWRender::Animation +This function also creates new position and normal buffers for submeshes. +This function points to existing texture and IndexData buffers +*/ + +std::vector& NIFLoader::getAnim(std::string lowername){ + + std::map,ciLessBoost>::iterator iter = allanimmap.find(lowername); + if(iter != allanimmap.end()) + mAnim = iter->second; + return mAnim; + +} +std::vector& NIFLoader::getShapes(std::string lowername){ + + std::map,ciLessBoost>::iterator iter = allshapesmap.find(lowername); + if(iter != allshapesmap.end()) + mS = iter->second; + return mS; +} + +float NIFLoader::getTime(std::string filename, std::string text){ + std::map,ciLessBoost>::iterator iter = alltextmappings.find(filename); + if(iter != alltextmappings.end()){ + std::map::iterator insideiter = (iter->second).find(text); + if(insideiter != (iter->second).end()) + return insideiter->second; + else + return -20000000.0; + } + + return -10000000.0; +} + +void NIFLoader::insertMeshInsideBase(Ogre::Mesh* input) +{ + /*if(addin) + { + std::cout << "InsideBase:" << addin->getName() << "\n"; + }*/ + if(input) + { + std::vector shapes = NIFLoader::getSingletonPtr()->getShapes(input->getName()); + for(int i = 0; i < shapes.size(); i++){ + + //std::cout << "Shapes" << shapes[i].sname; + + Ogre::SubMesh* sub = input->getSubMesh(shapes[i].sname); + Ogre::SubMesh* subNew = mesh->createSubMesh(shapes[i].sname); + + + int nextBuf = 0; + + + //----------------------------------------VERTICES---------------------------------------- + int numVerts = shapes[i].vertices.size(); + subNew->vertexData = new VertexData(); + subNew->vertexData->vertexCount = numVerts; + subNew->useSharedVertices = false; + + //-----------------------------------------POSITIONS--------------------------------------- + + + VertexDeclaration *decl = subNew->vertexData->vertexDeclaration; + const VertexElement* position = + sub->vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); + Ogre::HardwareVertexBufferSharedPtr vbuf; + HardwareVertexBufferSharedPtr newvbuf; + float* pRealNormal = new float[numVerts * 3]; + VertexBufferBinding* bind; + + + + + + + //std::cout << "X " << pReal[0] << "Y " << pReal[1] << "Z" << pReal[2] << "\n"; + float* pReal = new float[numVerts * 3]; + + std::map vertices; + std::map normals; + std::vector boneinfovector = shapes[i].boneinfo; + + //std::cout << "Name " << copy.sname << "\n"; + + if(boneinfovector.size() > 0){ + + + for (int j = 0; j < boneinfovector.size(); j++) + { + Nif::NiSkinData::BoneInfoCopy boneinfo = boneinfovector[j]; + Ogre::Bone *bonePtr = mSkel->getBone(boneinfo.bonename); + Ogre::Vector3 vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfo.trafo.trans; + Ogre::Quaternion vecRot = bonePtr->_getDerivedOrientation() * boneinfo.trafo.rotation; + //std::cout << "Bone" << bonePtr->getName() << "\n"; + for (unsigned int k=0; k< boneinfo.weights.size(); k++) + { + unsigned int verIndex = boneinfo.weights[k].vertex; + if(vertices.find(verIndex) == vertices.end()) + { + Ogre::Vector3 absVertPos = vecPos + vecRot * shapes[i].vertices[verIndex]; + vertices[verIndex] = true; + absVertPos = absVertPos * boneinfo.weights[k].weight; + Ogre::Real* addr = (pReal + 3 * verIndex); + *addr = absVertPos.x; + *(addr+1) = absVertPos.y; + *(addr+2) = absVertPos.z; + + //std::cout << "Vertex" << vertices[verIndex] << "\n"; + } + else + { + Ogre::Vector3 absVertPos = vecPos + vecRot * shapes[i].vertices[verIndex]; + absVertPos = absVertPos * boneinfo.weights[k].weight; + Ogre::Vector3 old = Ogre::Vector3(pReal + 3 * verIndex); + absVertPos = absVertPos + old; + Ogre::Real* addr = (pReal + 3 * verIndex); + *addr = absVertPos.x; + *(addr+1) = absVertPos.y; + *(addr+2) = absVertPos.z; + + } + + if(normals.find(verIndex) == normals.end()) + { + Ogre::Vector3 absNormalsPos = vecRot * shapes[i].normals[verIndex]; + absNormalsPos = absNormalsPos * boneinfo.weights[k].weight; + normals[verIndex] = true; + Ogre::Real* addr = (pRealNormal + 3 * verIndex); + *addr = absNormalsPos.x; + *(addr+1) = absNormalsPos.y; + *(addr+2) = absNormalsPos.z; + } + else{ + Ogre::Vector3 absNormalsPos = vecRot * shapes[i].normals[verIndex]; + absNormalsPos = absNormalsPos * boneinfo.weights[k].weight; + Ogre::Vector3 old = Ogre::Vector3(pRealNormal + 3 * verIndex); + absNormalsPos = absNormalsPos + old; + + Ogre::Real* addr = (pRealNormal + 3 * verIndex); + *addr = absNormalsPos.x; + *(addr+1) = absNormalsPos.y; + *(addr+2) = absNormalsPos.z; + } + + } + + /* + std::cout << "TransformRot:" << boneinfo.trafo.rotation << "TransformTrans:" << boneinfo.trafo.trans << "\n"; + std::vector weights = boneinfo.weights; + for (int j = 0; j < weights.size(); j++){ + std::cout << "Vertex: " << weights[j].vertex << " Weight: " << weights[j].weight << "\n"; + }*/ + } + } + + if(position){ + decl->addElement(nextBuf, 0, VET_FLOAT3, VES_POSITION); + + + + newvbuf = + HardwareBufferManager::getSingleton().createVertexBuffer( + VertexElement::getTypeSize(VET_FLOAT3), + numVerts, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); + + newvbuf->writeData(0, newvbuf->getSizeInBytes(), pReal, false); + + + bind = subNew->vertexData->vertexBufferBinding; + bind->setBinding(nextBuf++, newvbuf); + + + } + //----------------------------------------NORMALS------------------------------------------- + + const VertexElement* normal = + sub->vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_NORMAL); + if(normal) + { + decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL); + newvbuf = HardwareBufferManager::getSingleton().createVertexBuffer( + VertexElement::getTypeSize(VET_FLOAT3), + numVerts, HardwareBuffer::HBU_DYNAMIC); + + + newvbuf->writeData(0, newvbuf->getSizeInBytes(), pRealNormal, false); + + bind->setBinding(nextBuf++, newvbuf); + } + + + //--------------------------------------COLORS-------------------------------------------- + const VertexElement* color = + sub->vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_DIFFUSE); + if(color) + { + + decl->addElement(nextBuf, 0, VET_COLOUR, VES_DIFFUSE); + + vbuf = sub->vertexData->vertexBufferBinding->getBuffer(color->getSource()); + newvbuf = vbuf; + //RGBA* pReal2 = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); + //newvbuf->writeData(0, vbuf->getSizeInBytes(), pReal2, false); + + //vbuf->unlock(); + + bind->setBinding(nextBuf++, newvbuf); + } + + //-------------------------------------TEXTURES------------------------------------------- + + const VertexElement* text = + sub->vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES); + if(text){ + vbuf = sub->vertexData->vertexBufferBinding->getBuffer(text->getSource()); + + decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES); + newvbuf = vbuf; + //float* pRealf = static_cast(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); + + //std::cout << "SIze" << vbuf->getSizeInBytes(); + + // newvbuf->writeData(0, vbuf->getSizeInBytes(), pRealf, false); + //vbuf->unlock(); + bind->setBinding(nextBuf++, newvbuf); + } + + //----------------------------------INDEX DATA-------------------------------------- + int numFaces = sub->indexData->indexCount; + subNew->indexData->indexCount = numFaces; + subNew->indexData->indexStart = 0; + + HardwareIndexBufferSharedPtr ibuf = sub->indexData->indexBuffer; + HardwareIndexBufferSharedPtr ibufNew = ibuf; + + //uint16* tri = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); + //ibufNew->writeData(0, ibuf->getSizeInBytes(), tri, false); + subNew->indexData->indexBuffer = ibufNew; + //ibuf->unlock(); + + if (!sub->getMaterialName().empty()){ + subNew->setMaterialName(sub->getMaterialName()); + } + + //Ogre::SubMesh::VertexBoneAssignmentList bonelist = sub->getBoneAssignments(); + + /* + Ogre::VertexBoneAssignment assign; + assign.boneIndex = 0; + assign.vertexIndex = 0; + assign.weight = 1.0; + subNew->addBoneAssignment(assign);*/ + + Ogre::SubMesh::BoneAssignmentIterator boneiter = sub->getBoneAssignmentIterator(); + while(boneiter.hasMoreElements()) + { + subNew->addBoneAssignment(boneiter.current()->second); + boneiter.getNext(); + } + subNew->addBoneAssignment(boneiter.current()->second); + + + + } + } + +} + /* More code currently not in use, from the old D source. This was used in the first attempt at loading NIF meshes, where each submesh diff --git a/components/nifogre/ogre_nif_loader.hpp b/components/nifogre/ogre_nif_loader.hpp index a110e7e4f..a5b33bcbe 100644 --- a/components/nifogre/ogre_nif_loader.hpp +++ b/components/nifogre/ogre_nif_loader.hpp @@ -108,7 +108,11 @@ class NIFLoader : Ogre::ManualResourceLoader static Ogre::MeshPtr load(const std::string &name, const std::string &group="General"); - + void insertMeshInsideBase(Ogre::Mesh* mesh); + std::vector& getAnim(std::string name); + std::vector& getShapes(std::string name); + float getTime(std::string filename, std::string text); + void addInMesh(Ogre::Mesh* input); Ogre::Vector3 convertVector3(const Nif::Vector& vec); @@ -163,6 +167,7 @@ class NIFLoader : Ogre::ManualResourceLoader bool flip; bool mNormaliseNormals; bool mFlipVertexWinding; + bool bNiTri; std::multimap MaterialMap; // pointer to the ogre mesh which is currently build @@ -177,6 +182,9 @@ class NIFLoader : Ogre::ManualResourceLoader std::map,ciLessBoost> alltextmappings; std::map,ciLessBoost> allanimmap; std::map,ciLessBoost> allshapesmap; + std::vector addin; + std::vector mAnim; + std::vector mS; }; }