vrshoot
diff libs/assimp/OgreMesh.cpp @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/assimp/OgreMesh.cpp Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,516 @@ 1.4 +/* 1.5 +Open Asset Import Library (assimp) 1.6 +---------------------------------------------------------------------- 1.7 + 1.8 +Copyright (c) 2006-2012, assimp team 1.9 +All rights reserved. 1.10 + 1.11 +Redistribution and use of this software in source and binary forms, 1.12 +with or without modification, are permitted provided that the 1.13 +following conditions are met: 1.14 + 1.15 +* Redistributions of source code must retain the above 1.16 + copyright notice, this list of conditions and the 1.17 + following disclaimer. 1.18 + 1.19 +* Redistributions in binary form must reproduce the above 1.20 + copyright notice, this list of conditions and the 1.21 + following disclaimer in the documentation and/or other 1.22 + materials provided with the distribution. 1.23 + 1.24 +* Neither the name of the assimp team, nor the names of its 1.25 + contributors may be used to endorse or promote products 1.26 + derived from this software without specific prior 1.27 + written permission of the assimp team. 1.28 + 1.29 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.30 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.31 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.32 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.33 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.34 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.35 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.36 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.37 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.38 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.39 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.40 + 1.41 +---------------------------------------------------------------------- 1.42 +*/ 1.43 + 1.44 +#include "AssimpPCH.h" 1.45 + 1.46 +#ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER 1.47 + 1.48 +#include "OgreImporter.hpp" 1.49 +#include "TinyFormatter.h" 1.50 + 1.51 +using namespace std; 1.52 + 1.53 +namespace Assimp 1.54 +{ 1.55 +namespace Ogre 1.56 +{ 1.57 + 1.58 + 1.59 +void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader) 1.60 +{ 1.61 + if(Reader->getAttributeValue("usesharedvertices")) 1.62 + theSubMesh.SharedData=GetAttribute<bool>(Reader, "usesharedvertices"); 1.63 + 1.64 + XmlRead(Reader); 1.65 + //TODO: maybe we have alsways just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order 1.66 + //of faces and geometry changed, and not if we have more than one of one 1.67 + while( Reader->getNodeName()==string("faces") 1.68 + || Reader->getNodeName()==string("geometry") 1.69 + || Reader->getNodeName()==string("boneassignments")) 1.70 + { 1.71 + if(string(Reader->getNodeName())=="faces")//Read the face list 1.72 + { 1.73 + //some info logging: 1.74 + unsigned int NumFaces=GetAttribute<int>(Reader, "count"); 1.75 + ostringstream ss; ss <<"Submesh has " << NumFaces << " Faces."; 1.76 + DefaultLogger::get()->debug(ss.str()); 1.77 + 1.78 + while(XmlRead(Reader) && Reader->getNodeName()==string("face")) 1.79 + { 1.80 + Face NewFace; 1.81 + NewFace.VertexIndices[0]=GetAttribute<int>(Reader, "v1"); 1.82 + NewFace.VertexIndices[1]=GetAttribute<int>(Reader, "v2"); 1.83 + NewFace.VertexIndices[2]=GetAttribute<int>(Reader, "v3"); 1.84 + if(Reader->getAttributeValue("v4"))//this should be supported in the future 1.85 + { 1.86 + DefaultLogger::get()->warn("Submesh has quads, only traingles are supported!"); 1.87 + //throw DeadlyImportError("Submesh has quads, only traingles are supported!"); 1.88 + } 1.89 + theSubMesh.FaceList.push_back(NewFace); 1.90 + } 1.91 + 1.92 + }//end of faces 1.93 + else if(string(Reader->getNodeName())=="geometry")//Read the vertexdata 1.94 + { 1.95 + //some info logging: 1.96 + unsigned int NumVertices=GetAttribute<int>(Reader, "vertexcount"); 1.97 + ostringstream ss; ss<<"VertexCount: " << NumVertices; 1.98 + DefaultLogger::get()->debug(ss.str()); 1.99 + 1.100 + //General Informations about vertices 1.101 + XmlRead(Reader); 1.102 + while(Reader->getNodeName()==string("vertexbuffer")) 1.103 + { 1.104 + ReadVertexBuffer(theSubMesh, Reader, NumVertices); 1.105 + } 1.106 + 1.107 + //some error checking on the loaded data 1.108 + if(!theSubMesh.HasPositions) 1.109 + throw DeadlyImportError("No positions could be loaded!"); 1.110 + 1.111 + if(theSubMesh.HasNormals && theSubMesh.Normals.size() != NumVertices) 1.112 + throw DeadlyImportError("Wrong Number of Normals loaded!"); 1.113 + 1.114 + if(theSubMesh.HasTangents && theSubMesh.Tangents.size() != NumVertices) 1.115 + throw DeadlyImportError("Wrong Number of Tangents loaded!"); 1.116 + 1.117 + for(unsigned int i=0; i<theSubMesh.Uvs.size(); ++i) 1.118 + { 1.119 + if(theSubMesh.Uvs[i].size() != NumVertices) 1.120 + throw DeadlyImportError("Wrong Number of Uvs loaded!"); 1.121 + } 1.122 + 1.123 + }//end of "geometry 1.124 + 1.125 + 1.126 + else if(Reader->getNodeName()==string("boneassignments")) 1.127 + { 1.128 + ReadBoneWeights(theSubMesh, Reader); 1.129 + } 1.130 + } 1.131 + DefaultLogger::get()->debug((Formatter::format(), 1.132 + "Positionen: ",theSubMesh.Positions.size(), 1.133 + " Normale: ",theSubMesh.Normals.size(), 1.134 + " TexCoords: ",theSubMesh.Uvs.size(), 1.135 + " Tantents: ",theSubMesh.Tangents.size() 1.136 + )); 1.137 +} 1.138 + 1.139 + 1.140 +void OgreImporter::ReadVertexBuffer(SubMesh &theSubMesh, XmlReader *Reader, unsigned int NumVertices) 1.141 +{ 1.142 + DefaultLogger::get()->debug("new Vertex Buffer"); 1.143 + 1.144 + bool ReadPositions=false; 1.145 + bool ReadNormals=false; 1.146 + bool ReadTangents=false; 1.147 + unsigned int NumUvs=0; 1.148 + 1.149 + //-------------------- check, what we need to read: -------------------------------- 1.150 + if(Reader->getAttributeValue("positions") && GetAttribute<bool>(Reader, "positions")) 1.151 + { 1.152 + ReadPositions=theSubMesh.HasPositions=true; 1.153 + theSubMesh.Positions.reserve(NumVertices); 1.154 + DefaultLogger::get()->debug("reading positions"); 1.155 + } 1.156 + if(Reader->getAttributeValue("normals") && GetAttribute<bool>(Reader, "normals")) 1.157 + { 1.158 + ReadNormals=theSubMesh.HasNormals=true; 1.159 + theSubMesh.Normals.reserve(NumVertices); 1.160 + DefaultLogger::get()->debug("reading normals"); 1.161 + } 1.162 + if(Reader->getAttributeValue("tangents") && GetAttribute<bool>(Reader, "tangents")) 1.163 + { 1.164 + ReadTangents=theSubMesh.HasTangents=true; 1.165 + theSubMesh.Tangents.reserve(NumVertices); 1.166 + DefaultLogger::get()->debug("reading tangents"); 1.167 + } 1.168 + 1.169 + if(Reader->getAttributeValue("texture_coords")) 1.170 + { 1.171 + NumUvs=GetAttribute<unsigned int>(Reader, "texture_coords"); 1.172 + theSubMesh.Uvs.resize(NumUvs); 1.173 + for(unsigned int i=0; i<theSubMesh.Uvs.size(); ++i) theSubMesh.Uvs[i].reserve(NumVertices); 1.174 + DefaultLogger::get()->debug("reading texture coords"); 1.175 + } 1.176 + //___________________________________________________________________ 1.177 + 1.178 + 1.179 + //check if we will load anything 1.180 + if(!( ReadPositions || ReadNormals || ReadTangents || (NumUvs>0) )) 1.181 + DefaultLogger::get()->warn("vertexbuffer seams to be empty!"); 1.182 + 1.183 + 1.184 + //read all the vertices: 1.185 + XmlRead(Reader); 1.186 + 1.187 + /*it might happen, that we have more than one attribute per vertex (they are not splitted to different buffers) 1.188 + so the break condition is a bit tricky */ 1.189 + while(Reader->getNodeName()==string("vertex") 1.190 + ||Reader->getNodeName()==string("position") 1.191 + ||Reader->getNodeName()==string("normal") 1.192 + ||Reader->getNodeName()==string("tangent") 1.193 + ||Reader->getNodeName()==string("texcoord") 1.194 + ||Reader->getNodeName()==string("colour_diffuse")) 1.195 + { 1.196 + if(Reader->getNodeName()==string("vertex")) 1.197 + XmlRead(Reader);//Read an attribute tag 1.198 + 1.199 + //Position 1.200 + if(ReadPositions && Reader->getNodeName()==string("position")) 1.201 + { 1.202 + aiVector3D NewPos; 1.203 + NewPos.x=GetAttribute<float>(Reader, "x"); 1.204 + NewPos.y=GetAttribute<float>(Reader, "y"); 1.205 + NewPos.z=GetAttribute<float>(Reader, "z"); 1.206 + theSubMesh.Positions.push_back(NewPos); 1.207 + } 1.208 + 1.209 + //Normal 1.210 + else if(ReadNormals && Reader->getNodeName()==string("normal")) 1.211 + { 1.212 + aiVector3D NewNormal; 1.213 + NewNormal.x=GetAttribute<float>(Reader, "x"); 1.214 + NewNormal.y=GetAttribute<float>(Reader, "y"); 1.215 + NewNormal.z=GetAttribute<float>(Reader, "z"); 1.216 + theSubMesh.Normals.push_back(NewNormal); 1.217 + } 1.218 + 1.219 + //Tangent 1.220 + else if(ReadTangents && Reader->getNodeName()==string("tangent")) 1.221 + { 1.222 + aiVector3D NewTangent; 1.223 + NewTangent.x=GetAttribute<float>(Reader, "x"); 1.224 + NewTangent.y=GetAttribute<float>(Reader, "y"); 1.225 + NewTangent.z=GetAttribute<float>(Reader, "z"); 1.226 + theSubMesh.Tangents.push_back(NewTangent); 1.227 + } 1.228 + 1.229 + //Uv: 1.230 + else if(NumUvs>0 && Reader->getNodeName()==string("texcoord")) 1.231 + { 1.232 + for(unsigned int i=0; i<NumUvs; ++i) 1.233 + { 1.234 + if(Reader->getNodeName()!=string("texcoord")) 1.235 + { 1.236 + DefaultLogger::get()->warn(string("Not enough UVs in Vertex: ")+Reader->getNodeName()); 1.237 + } 1.238 + aiVector3D NewUv; 1.239 + NewUv.x=GetAttribute<float>(Reader, "u"); 1.240 + NewUv.y=GetAttribute<float>(Reader, "v")*(-1)+1;//flip the uv vertikal, blender exports them so! 1.241 + theSubMesh.Uvs[i].push_back(NewUv); 1.242 + XmlRead(Reader); 1.243 + } 1.244 + continue;//because we already read the next node... 1.245 + } 1.246 + 1.247 + //Color: 1.248 + //TODO: actually save this data! 1.249 + else if(Reader->getNodeName()==string("colour_diffuse")) 1.250 + { 1.251 + //do nothing, because we not yet support them 1.252 + } 1.253 + 1.254 + //Attribute could not be read 1.255 + else 1.256 + { 1.257 + DefaultLogger::get()->warn(string("Attribute was not read: ")+Reader->getNodeName()); 1.258 + } 1.259 + 1.260 + XmlRead(Reader);//Read the Vertex tag 1.261 + } 1.262 +} 1.263 + 1.264 + 1.265 +void OgreImporter::ReadBoneWeights(SubMesh &theSubMesh, XmlReader *Reader) 1.266 +{ 1.267 + theSubMesh.Weights.resize(theSubMesh.Positions.size()); 1.268 + while(XmlRead(Reader) && Reader->getNodeName()==string("vertexboneassignment")) 1.269 + { 1.270 + Weight NewWeight; 1.271 + unsigned int VertexId=GetAttribute<int>(Reader, "vertexindex"); 1.272 + NewWeight.BoneId=GetAttribute<int>(Reader, "boneindex"); 1.273 + NewWeight.Value=GetAttribute<float>(Reader, "weight"); 1.274 + //calculate the number of bones used (this is the highest id +1 becuase bone ids start at 0) 1.275 + theSubMesh.BonesUsed=max(theSubMesh.BonesUsed, NewWeight.BoneId+1); 1.276 + 1.277 + theSubMesh.Weights[VertexId].push_back(NewWeight); 1.278 + } 1.279 +} 1.280 + 1.281 + 1.282 + 1.283 +void OgreImporter::ProcessSubMesh(SubMesh &theSubMesh, SubMesh &theSharedGeometry) 1.284 +{ 1.285 + //---------------Make all Vertexes unique: (this is required by assimp)----------------------- 1.286 + vector<Face> UniqueFaceList(theSubMesh.FaceList.size()); 1.287 + unsigned int UniqueVertexCount=theSubMesh.FaceList.size()*3;//*3 because each face consists of 3 vertexes, because we only support triangles^^ 1.288 + 1.289 + vector<aiVector3D> UniquePositions(UniqueVertexCount); 1.290 + 1.291 + vector<aiVector3D> UniqueNormals(UniqueVertexCount); 1.292 + 1.293 + vector<aiVector3D> UniqueTangents(UniqueVertexCount); 1.294 + 1.295 + vector< vector<Weight> > UniqueWeights(UniqueVertexCount); 1.296 + 1.297 + vector< vector<aiVector3D> > UniqueUvs(theSubMesh.Uvs.size()); 1.298 + for(unsigned int i=0; i<UniqueUvs.size(); ++i) UniqueUvs[i].resize(UniqueVertexCount); 1.299 + 1.300 + 1.301 + 1.302 + //Support for shared data: 1.303 + /*We can use this loop to copy vertex informations from the shared data pool. In order to do so 1.304 + we just use a reference to a submodel instead of our submodel itself*/ 1.305 + 1.306 + SubMesh& VertexSource= theSubMesh.SharedData ? theSharedGeometry : theSubMesh; 1.307 + if(theSubMesh.SharedData)//copy vertexinformations to our mesh: 1.308 + { 1.309 + theSubMesh.HasPositions=theSharedGeometry.HasPositions; 1.310 + theSubMesh.HasNormals=theSharedGeometry.HasNormals; 1.311 + theSubMesh.HasTangents=theSharedGeometry.HasTangents; 1.312 + 1.313 + theSubMesh.BonesUsed=theSharedGeometry.BonesUsed; 1.314 + 1.315 + UniqueUvs.resize(theSharedGeometry.Uvs.size()); 1.316 + for(unsigned int i=0; i<UniqueUvs.size(); ++i) UniqueUvs[i].resize(UniqueVertexCount); 1.317 + } 1.318 + 1.319 + for(unsigned int i=0; i<theSubMesh.FaceList.size(); ++i) 1.320 + { 1.321 + //We precalculate the index vlaues her, because we need them in all vertex attributes 1.322 + unsigned int Vertex1=theSubMesh.FaceList[i].VertexIndices[0]; 1.323 + unsigned int Vertex2=theSubMesh.FaceList[i].VertexIndices[1]; 1.324 + unsigned int Vertex3=theSubMesh.FaceList[i].VertexIndices[2]; 1.325 + 1.326 + UniquePositions[3*i+0]=VertexSource.Positions[Vertex1]; 1.327 + UniquePositions[3*i+1]=VertexSource.Positions[Vertex2]; 1.328 + UniquePositions[3*i+2]=VertexSource.Positions[Vertex3]; 1.329 + 1.330 + if(VertexSource.HasNormals) 1.331 + { 1.332 + UniqueNormals[3*i+0]=VertexSource.Normals[Vertex1]; 1.333 + UniqueNormals[3*i+1]=VertexSource.Normals[Vertex2]; 1.334 + UniqueNormals[3*i+2]=VertexSource.Normals[Vertex3]; 1.335 + } 1.336 + 1.337 + if(VertexSource.HasTangents) 1.338 + { 1.339 + UniqueTangents[3*i+0]=VertexSource.Tangents[Vertex1]; 1.340 + UniqueTangents[3*i+1]=VertexSource.Tangents[Vertex2]; 1.341 + UniqueTangents[3*i+2]=VertexSource.Tangents[Vertex3]; 1.342 + } 1.343 + 1.344 + if(UniqueUvs.size()>0) 1.345 + { 1.346 + for(unsigned int j=0; j<UniqueUvs.size(); ++j) 1.347 + { 1.348 + UniqueUvs[j][3*i+0]=VertexSource.Uvs[j][Vertex1]; 1.349 + UniqueUvs[j][3*i+1]=VertexSource.Uvs[j][Vertex2]; 1.350 + UniqueUvs[j][3*i+2]=VertexSource.Uvs[j][Vertex3]; 1.351 + } 1.352 + } 1.353 + 1.354 + if(VertexSource.Weights.size() > 0) 1.355 + { 1.356 + UniqueWeights[3*i+0]=VertexSource.Weights[Vertex1]; 1.357 + UniqueWeights[3*i+1]=VertexSource.Weights[Vertex2]; 1.358 + UniqueWeights[3*i+2]=VertexSource.Weights[Vertex3]; 1.359 + } 1.360 + 1.361 + //The indexvalues a just continuous numbers (0, 1, 2, 3, 4, 5, 6...) 1.362 + UniqueFaceList[i].VertexIndices[0]=3*i+0; 1.363 + UniqueFaceList[i].VertexIndices[1]=3*i+1; 1.364 + UniqueFaceList[i].VertexIndices[2]=3*i+2; 1.365 + } 1.366 + //_________________________________________________________________________________________ 1.367 + 1.368 + //now we have the unique datas, but want them in the SubMesh, so we swap all the containers: 1.369 + //if we don't have one of them, we just swap empty containers, so everything is ok 1.370 + theSubMesh.FaceList.swap(UniqueFaceList); 1.371 + theSubMesh.Positions.swap(UniquePositions); 1.372 + theSubMesh.Normals.swap(UniqueNormals); 1.373 + theSubMesh.Tangents.swap(UniqueTangents); 1.374 + theSubMesh.Uvs.swap(UniqueUvs); 1.375 + theSubMesh.Weights.swap(UniqueWeights); 1.376 + 1.377 + 1.378 + 1.379 + //------------- normalize weights ----------------------------- 1.380 + //The Blender exporter doesn't care about whether the sum of all boneweights for a single vertex equals 1 or not, 1.381 + //so we have to make this sure: 1.382 + for(unsigned int VertexId=0; VertexId<theSubMesh.Weights.size(); ++VertexId)//iterate over all vertices 1.383 + { 1.384 + float WeightSum=0.0f; 1.385 + for(unsigned int BoneId=0; BoneId<theSubMesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones 1.386 + { 1.387 + WeightSum+=theSubMesh.Weights[VertexId][BoneId].Value; 1.388 + } 1.389 + 1.390 + //check if the sum is too far away from 1 1.391 + if(WeightSum<1.0f-0.05f || WeightSum>1.0f+0.05f) 1.392 + { 1.393 + //normalize all weights: 1.394 + for(unsigned int BoneId=0; BoneId<theSubMesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones 1.395 + { 1.396 + theSubMesh.Weights[VertexId][BoneId].Value/=WeightSum; 1.397 + } 1.398 + } 1.399 + } 1.400 + //_________________________________________________________ 1.401 +} 1.402 + 1.403 + 1.404 + 1.405 + 1.406 +aiMesh* OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vector<Bone>& Bones) const 1.407 +{ 1.408 + const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene 1.409 + (void)m_CurrentScene; 1.410 + 1.411 + aiMesh* NewAiMesh=new aiMesh(); 1.412 + 1.413 + //Positions 1.414 + NewAiMesh->mVertices=new aiVector3D[theSubMesh.Positions.size()]; 1.415 + memcpy(NewAiMesh->mVertices, &theSubMesh.Positions[0], theSubMesh.Positions.size()*sizeof(aiVector3D)); 1.416 + NewAiMesh->mNumVertices=theSubMesh.Positions.size(); 1.417 + 1.418 + //Normals 1.419 + if(theSubMesh.HasNormals) 1.420 + { 1.421 + NewAiMesh->mNormals=new aiVector3D[theSubMesh.Normals.size()]; 1.422 + memcpy(NewAiMesh->mNormals, &theSubMesh.Normals[0], theSubMesh.Normals.size()*sizeof(aiVector3D)); 1.423 + } 1.424 + 1.425 + 1.426 + //until we have support for bitangents, no tangents will be written 1.427 + /* 1.428 + //Tangents 1.429 + if(theSubMesh.HasTangents) 1.430 + { 1.431 + NewAiMesh->mTangents=new aiVector3D[theSubMesh.Tangents.size()]; 1.432 + memcpy(NewAiMesh->mTangents, &theSubMesh.Tangents[0], theSubMesh.Tangents.size()*sizeof(aiVector3D)); 1.433 + } 1.434 + */ 1.435 + 1.436 + //Uvs 1.437 + if(theSubMesh.Uvs.size()>0) 1.438 + { 1.439 + for(unsigned int i=0; i<theSubMesh.Uvs.size(); ++i) 1.440 + { 1.441 + NewAiMesh->mNumUVComponents[i]=2; 1.442 + NewAiMesh->mTextureCoords[i]=new aiVector3D[theSubMesh.Uvs[i].size()]; 1.443 + memcpy(NewAiMesh->mTextureCoords[i], &(theSubMesh.Uvs[i][0]), theSubMesh.Uvs[i].size()*sizeof(aiVector3D)); 1.444 + } 1.445 + } 1.446 + 1.447 + 1.448 + //---------------------------------------- Bones -------------------------------------------- 1.449 + 1.450 + //Copy the weights in in Bone-Vertices Struktur 1.451 + //(we have them in a Vertex-Bones Structur, this is much easier for making them unique, which is required by assimp 1.452 + vector< vector<aiVertexWeight> > aiWeights(theSubMesh.BonesUsed);//now the outer list are the bones, and the inner vector the vertices 1.453 + for(unsigned int VertexId=0; VertexId<theSubMesh.Weights.size(); ++VertexId)//iterate over all vertices 1.454 + { 1.455 + for(unsigned int BoneId=0; BoneId<theSubMesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones 1.456 + { 1.457 + aiVertexWeight NewWeight; 1.458 + NewWeight.mVertexId=VertexId;//the current Vertex, we can't use the Id form the submehs weights, because they are bone id's 1.459 + NewWeight.mWeight=theSubMesh.Weights[VertexId][BoneId].Value; 1.460 + aiWeights[theSubMesh.Weights[VertexId][BoneId].BoneId].push_back(NewWeight); 1.461 + } 1.462 + } 1.463 + 1.464 + 1.465 + 1.466 + vector<aiBone*> aiBones; 1.467 + aiBones.reserve(theSubMesh.BonesUsed);//the vector might be smaller, because there might be empty bones (bones that are not attached to any vertex) 1.468 + 1.469 + //create all the bones and fill them with informations 1.470 + for(unsigned int i=0; i<theSubMesh.BonesUsed; ++i) 1.471 + { 1.472 + if(aiWeights[i].size()>0) 1.473 + { 1.474 + aiBone* NewBone=new aiBone(); 1.475 + NewBone->mNumWeights=aiWeights[i].size(); 1.476 + NewBone->mWeights=new aiVertexWeight[aiWeights[i].size()]; 1.477 + memcpy(NewBone->mWeights, &(aiWeights[i][0]), sizeof(aiVertexWeight)*aiWeights[i].size()); 1.478 + NewBone->mName=Bones[i].Name;//The bone list should be sorted after its id's, this was done in LoadSkeleton 1.479 + NewBone->mOffsetMatrix=Bones[i].BoneToWorldSpace; 1.480 + 1.481 + aiBones.push_back(NewBone); 1.482 + } 1.483 + } 1.484 + NewAiMesh->mNumBones=aiBones.size(); 1.485 + 1.486 + // mBones must be NULL if mNumBones is non 0 or the validation fails. 1.487 + if (aiBones.size()) { 1.488 + NewAiMesh->mBones=new aiBone* [aiBones.size()]; 1.489 + memcpy(NewAiMesh->mBones, &(aiBones[0]), aiBones.size()*sizeof(aiBone*)); 1.490 + } 1.491 + 1.492 + //______________________________________________________________________________________________________ 1.493 + 1.494 + 1.495 + 1.496 + //Faces 1.497 + NewAiMesh->mFaces=new aiFace[theSubMesh.FaceList.size()]; 1.498 + for(unsigned int i=0; i<theSubMesh.FaceList.size(); ++i) 1.499 + { 1.500 + NewAiMesh->mFaces[i].mNumIndices=3; 1.501 + NewAiMesh->mFaces[i].mIndices=new unsigned int[3]; 1.502 + 1.503 + NewAiMesh->mFaces[i].mIndices[0]=theSubMesh.FaceList[i].VertexIndices[0]; 1.504 + NewAiMesh->mFaces[i].mIndices[1]=theSubMesh.FaceList[i].VertexIndices[1]; 1.505 + NewAiMesh->mFaces[i].mIndices[2]=theSubMesh.FaceList[i].VertexIndices[2]; 1.506 + } 1.507 + NewAiMesh->mNumFaces=theSubMesh.FaceList.size(); 1.508 + 1.509 + //Link the material: 1.510 + NewAiMesh->mMaterialIndex=theSubMesh.MaterialIndex;//the index is set by the function who called ReadSubMesh 1.511 + 1.512 + return NewAiMesh; 1.513 +} 1.514 + 1.515 + 1.516 +}//namespace Ogre 1.517 +}//namespace Assimp 1.518 + 1.519 +#endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER