vrshoot

annotate libs/assimp/OgreMesh.cpp @ 1:e7ca128b8713

looks nice :)
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 02 Feb 2014 00:35:22 +0200
parents
children
rev   line source
nuclear@0 1 /*
nuclear@0 2 Open Asset Import Library (assimp)
nuclear@0 3 ----------------------------------------------------------------------
nuclear@0 4
nuclear@0 5 Copyright (c) 2006-2012, assimp team
nuclear@0 6 All rights reserved.
nuclear@0 7
nuclear@0 8 Redistribution and use of this software in source and binary forms,
nuclear@0 9 with or without modification, are permitted provided that the
nuclear@0 10 following conditions are met:
nuclear@0 11
nuclear@0 12 * Redistributions of source code must retain the above
nuclear@0 13 copyright notice, this list of conditions and the
nuclear@0 14 following disclaimer.
nuclear@0 15
nuclear@0 16 * Redistributions in binary form must reproduce the above
nuclear@0 17 copyright notice, this list of conditions and the
nuclear@0 18 following disclaimer in the documentation and/or other
nuclear@0 19 materials provided with the distribution.
nuclear@0 20
nuclear@0 21 * Neither the name of the assimp team, nor the names of its
nuclear@0 22 contributors may be used to endorse or promote products
nuclear@0 23 derived from this software without specific prior
nuclear@0 24 written permission of the assimp team.
nuclear@0 25
nuclear@0 26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
nuclear@0 27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
nuclear@0 28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
nuclear@0 29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
nuclear@0 30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
nuclear@0 31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
nuclear@0 32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
nuclear@0 33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
nuclear@0 34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
nuclear@0 35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
nuclear@0 36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
nuclear@0 37
nuclear@0 38 ----------------------------------------------------------------------
nuclear@0 39 */
nuclear@0 40
nuclear@0 41 #include "AssimpPCH.h"
nuclear@0 42
nuclear@0 43 #ifndef ASSIMP_BUILD_NO_OGRE_IMPORTER
nuclear@0 44
nuclear@0 45 #include "OgreImporter.hpp"
nuclear@0 46 #include "TinyFormatter.h"
nuclear@0 47
nuclear@0 48 using namespace std;
nuclear@0 49
nuclear@0 50 namespace Assimp
nuclear@0 51 {
nuclear@0 52 namespace Ogre
nuclear@0 53 {
nuclear@0 54
nuclear@0 55
nuclear@0 56 void OgreImporter::ReadSubMesh(SubMesh &theSubMesh, XmlReader *Reader)
nuclear@0 57 {
nuclear@0 58 if(Reader->getAttributeValue("usesharedvertices"))
nuclear@0 59 theSubMesh.SharedData=GetAttribute<bool>(Reader, "usesharedvertices");
nuclear@0 60
nuclear@0 61 XmlRead(Reader);
nuclear@0 62 //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
nuclear@0 63 //of faces and geometry changed, and not if we have more than one of one
nuclear@0 64 while( Reader->getNodeName()==string("faces")
nuclear@0 65 || Reader->getNodeName()==string("geometry")
nuclear@0 66 || Reader->getNodeName()==string("boneassignments"))
nuclear@0 67 {
nuclear@0 68 if(string(Reader->getNodeName())=="faces")//Read the face list
nuclear@0 69 {
nuclear@0 70 //some info logging:
nuclear@0 71 unsigned int NumFaces=GetAttribute<int>(Reader, "count");
nuclear@0 72 ostringstream ss; ss <<"Submesh has " << NumFaces << " Faces.";
nuclear@0 73 DefaultLogger::get()->debug(ss.str());
nuclear@0 74
nuclear@0 75 while(XmlRead(Reader) && Reader->getNodeName()==string("face"))
nuclear@0 76 {
nuclear@0 77 Face NewFace;
nuclear@0 78 NewFace.VertexIndices[0]=GetAttribute<int>(Reader, "v1");
nuclear@0 79 NewFace.VertexIndices[1]=GetAttribute<int>(Reader, "v2");
nuclear@0 80 NewFace.VertexIndices[2]=GetAttribute<int>(Reader, "v3");
nuclear@0 81 if(Reader->getAttributeValue("v4"))//this should be supported in the future
nuclear@0 82 {
nuclear@0 83 DefaultLogger::get()->warn("Submesh has quads, only traingles are supported!");
nuclear@0 84 //throw DeadlyImportError("Submesh has quads, only traingles are supported!");
nuclear@0 85 }
nuclear@0 86 theSubMesh.FaceList.push_back(NewFace);
nuclear@0 87 }
nuclear@0 88
nuclear@0 89 }//end of faces
nuclear@0 90 else if(string(Reader->getNodeName())=="geometry")//Read the vertexdata
nuclear@0 91 {
nuclear@0 92 //some info logging:
nuclear@0 93 unsigned int NumVertices=GetAttribute<int>(Reader, "vertexcount");
nuclear@0 94 ostringstream ss; ss<<"VertexCount: " << NumVertices;
nuclear@0 95 DefaultLogger::get()->debug(ss.str());
nuclear@0 96
nuclear@0 97 //General Informations about vertices
nuclear@0 98 XmlRead(Reader);
nuclear@0 99 while(Reader->getNodeName()==string("vertexbuffer"))
nuclear@0 100 {
nuclear@0 101 ReadVertexBuffer(theSubMesh, Reader, NumVertices);
nuclear@0 102 }
nuclear@0 103
nuclear@0 104 //some error checking on the loaded data
nuclear@0 105 if(!theSubMesh.HasPositions)
nuclear@0 106 throw DeadlyImportError("No positions could be loaded!");
nuclear@0 107
nuclear@0 108 if(theSubMesh.HasNormals && theSubMesh.Normals.size() != NumVertices)
nuclear@0 109 throw DeadlyImportError("Wrong Number of Normals loaded!");
nuclear@0 110
nuclear@0 111 if(theSubMesh.HasTangents && theSubMesh.Tangents.size() != NumVertices)
nuclear@0 112 throw DeadlyImportError("Wrong Number of Tangents loaded!");
nuclear@0 113
nuclear@0 114 for(unsigned int i=0; i<theSubMesh.Uvs.size(); ++i)
nuclear@0 115 {
nuclear@0 116 if(theSubMesh.Uvs[i].size() != NumVertices)
nuclear@0 117 throw DeadlyImportError("Wrong Number of Uvs loaded!");
nuclear@0 118 }
nuclear@0 119
nuclear@0 120 }//end of "geometry
nuclear@0 121
nuclear@0 122
nuclear@0 123 else if(Reader->getNodeName()==string("boneassignments"))
nuclear@0 124 {
nuclear@0 125 ReadBoneWeights(theSubMesh, Reader);
nuclear@0 126 }
nuclear@0 127 }
nuclear@0 128 DefaultLogger::get()->debug((Formatter::format(),
nuclear@0 129 "Positionen: ",theSubMesh.Positions.size(),
nuclear@0 130 " Normale: ",theSubMesh.Normals.size(),
nuclear@0 131 " TexCoords: ",theSubMesh.Uvs.size(),
nuclear@0 132 " Tantents: ",theSubMesh.Tangents.size()
nuclear@0 133 ));
nuclear@0 134 }
nuclear@0 135
nuclear@0 136
nuclear@0 137 void OgreImporter::ReadVertexBuffer(SubMesh &theSubMesh, XmlReader *Reader, unsigned int NumVertices)
nuclear@0 138 {
nuclear@0 139 DefaultLogger::get()->debug("new Vertex Buffer");
nuclear@0 140
nuclear@0 141 bool ReadPositions=false;
nuclear@0 142 bool ReadNormals=false;
nuclear@0 143 bool ReadTangents=false;
nuclear@0 144 unsigned int NumUvs=0;
nuclear@0 145
nuclear@0 146 //-------------------- check, what we need to read: --------------------------------
nuclear@0 147 if(Reader->getAttributeValue("positions") && GetAttribute<bool>(Reader, "positions"))
nuclear@0 148 {
nuclear@0 149 ReadPositions=theSubMesh.HasPositions=true;
nuclear@0 150 theSubMesh.Positions.reserve(NumVertices);
nuclear@0 151 DefaultLogger::get()->debug("reading positions");
nuclear@0 152 }
nuclear@0 153 if(Reader->getAttributeValue("normals") && GetAttribute<bool>(Reader, "normals"))
nuclear@0 154 {
nuclear@0 155 ReadNormals=theSubMesh.HasNormals=true;
nuclear@0 156 theSubMesh.Normals.reserve(NumVertices);
nuclear@0 157 DefaultLogger::get()->debug("reading normals");
nuclear@0 158 }
nuclear@0 159 if(Reader->getAttributeValue("tangents") && GetAttribute<bool>(Reader, "tangents"))
nuclear@0 160 {
nuclear@0 161 ReadTangents=theSubMesh.HasTangents=true;
nuclear@0 162 theSubMesh.Tangents.reserve(NumVertices);
nuclear@0 163 DefaultLogger::get()->debug("reading tangents");
nuclear@0 164 }
nuclear@0 165
nuclear@0 166 if(Reader->getAttributeValue("texture_coords"))
nuclear@0 167 {
nuclear@0 168 NumUvs=GetAttribute<unsigned int>(Reader, "texture_coords");
nuclear@0 169 theSubMesh.Uvs.resize(NumUvs);
nuclear@0 170 for(unsigned int i=0; i<theSubMesh.Uvs.size(); ++i) theSubMesh.Uvs[i].reserve(NumVertices);
nuclear@0 171 DefaultLogger::get()->debug("reading texture coords");
nuclear@0 172 }
nuclear@0 173 //___________________________________________________________________
nuclear@0 174
nuclear@0 175
nuclear@0 176 //check if we will load anything
nuclear@0 177 if(!( ReadPositions || ReadNormals || ReadTangents || (NumUvs>0) ))
nuclear@0 178 DefaultLogger::get()->warn("vertexbuffer seams to be empty!");
nuclear@0 179
nuclear@0 180
nuclear@0 181 //read all the vertices:
nuclear@0 182 XmlRead(Reader);
nuclear@0 183
nuclear@0 184 /*it might happen, that we have more than one attribute per vertex (they are not splitted to different buffers)
nuclear@0 185 so the break condition is a bit tricky */
nuclear@0 186 while(Reader->getNodeName()==string("vertex")
nuclear@0 187 ||Reader->getNodeName()==string("position")
nuclear@0 188 ||Reader->getNodeName()==string("normal")
nuclear@0 189 ||Reader->getNodeName()==string("tangent")
nuclear@0 190 ||Reader->getNodeName()==string("texcoord")
nuclear@0 191 ||Reader->getNodeName()==string("colour_diffuse"))
nuclear@0 192 {
nuclear@0 193 if(Reader->getNodeName()==string("vertex"))
nuclear@0 194 XmlRead(Reader);//Read an attribute tag
nuclear@0 195
nuclear@0 196 //Position
nuclear@0 197 if(ReadPositions && Reader->getNodeName()==string("position"))
nuclear@0 198 {
nuclear@0 199 aiVector3D NewPos;
nuclear@0 200 NewPos.x=GetAttribute<float>(Reader, "x");
nuclear@0 201 NewPos.y=GetAttribute<float>(Reader, "y");
nuclear@0 202 NewPos.z=GetAttribute<float>(Reader, "z");
nuclear@0 203 theSubMesh.Positions.push_back(NewPos);
nuclear@0 204 }
nuclear@0 205
nuclear@0 206 //Normal
nuclear@0 207 else if(ReadNormals && Reader->getNodeName()==string("normal"))
nuclear@0 208 {
nuclear@0 209 aiVector3D NewNormal;
nuclear@0 210 NewNormal.x=GetAttribute<float>(Reader, "x");
nuclear@0 211 NewNormal.y=GetAttribute<float>(Reader, "y");
nuclear@0 212 NewNormal.z=GetAttribute<float>(Reader, "z");
nuclear@0 213 theSubMesh.Normals.push_back(NewNormal);
nuclear@0 214 }
nuclear@0 215
nuclear@0 216 //Tangent
nuclear@0 217 else if(ReadTangents && Reader->getNodeName()==string("tangent"))
nuclear@0 218 {
nuclear@0 219 aiVector3D NewTangent;
nuclear@0 220 NewTangent.x=GetAttribute<float>(Reader, "x");
nuclear@0 221 NewTangent.y=GetAttribute<float>(Reader, "y");
nuclear@0 222 NewTangent.z=GetAttribute<float>(Reader, "z");
nuclear@0 223 theSubMesh.Tangents.push_back(NewTangent);
nuclear@0 224 }
nuclear@0 225
nuclear@0 226 //Uv:
nuclear@0 227 else if(NumUvs>0 && Reader->getNodeName()==string("texcoord"))
nuclear@0 228 {
nuclear@0 229 for(unsigned int i=0; i<NumUvs; ++i)
nuclear@0 230 {
nuclear@0 231 if(Reader->getNodeName()!=string("texcoord"))
nuclear@0 232 {
nuclear@0 233 DefaultLogger::get()->warn(string("Not enough UVs in Vertex: ")+Reader->getNodeName());
nuclear@0 234 }
nuclear@0 235 aiVector3D NewUv;
nuclear@0 236 NewUv.x=GetAttribute<float>(Reader, "u");
nuclear@0 237 NewUv.y=GetAttribute<float>(Reader, "v")*(-1)+1;//flip the uv vertikal, blender exports them so!
nuclear@0 238 theSubMesh.Uvs[i].push_back(NewUv);
nuclear@0 239 XmlRead(Reader);
nuclear@0 240 }
nuclear@0 241 continue;//because we already read the next node...
nuclear@0 242 }
nuclear@0 243
nuclear@0 244 //Color:
nuclear@0 245 //TODO: actually save this data!
nuclear@0 246 else if(Reader->getNodeName()==string("colour_diffuse"))
nuclear@0 247 {
nuclear@0 248 //do nothing, because we not yet support them
nuclear@0 249 }
nuclear@0 250
nuclear@0 251 //Attribute could not be read
nuclear@0 252 else
nuclear@0 253 {
nuclear@0 254 DefaultLogger::get()->warn(string("Attribute was not read: ")+Reader->getNodeName());
nuclear@0 255 }
nuclear@0 256
nuclear@0 257 XmlRead(Reader);//Read the Vertex tag
nuclear@0 258 }
nuclear@0 259 }
nuclear@0 260
nuclear@0 261
nuclear@0 262 void OgreImporter::ReadBoneWeights(SubMesh &theSubMesh, XmlReader *Reader)
nuclear@0 263 {
nuclear@0 264 theSubMesh.Weights.resize(theSubMesh.Positions.size());
nuclear@0 265 while(XmlRead(Reader) && Reader->getNodeName()==string("vertexboneassignment"))
nuclear@0 266 {
nuclear@0 267 Weight NewWeight;
nuclear@0 268 unsigned int VertexId=GetAttribute<int>(Reader, "vertexindex");
nuclear@0 269 NewWeight.BoneId=GetAttribute<int>(Reader, "boneindex");
nuclear@0 270 NewWeight.Value=GetAttribute<float>(Reader, "weight");
nuclear@0 271 //calculate the number of bones used (this is the highest id +1 becuase bone ids start at 0)
nuclear@0 272 theSubMesh.BonesUsed=max(theSubMesh.BonesUsed, NewWeight.BoneId+1);
nuclear@0 273
nuclear@0 274 theSubMesh.Weights[VertexId].push_back(NewWeight);
nuclear@0 275 }
nuclear@0 276 }
nuclear@0 277
nuclear@0 278
nuclear@0 279
nuclear@0 280 void OgreImporter::ProcessSubMesh(SubMesh &theSubMesh, SubMesh &theSharedGeometry)
nuclear@0 281 {
nuclear@0 282 //---------------Make all Vertexes unique: (this is required by assimp)-----------------------
nuclear@0 283 vector<Face> UniqueFaceList(theSubMesh.FaceList.size());
nuclear@0 284 unsigned int UniqueVertexCount=theSubMesh.FaceList.size()*3;//*3 because each face consists of 3 vertexes, because we only support triangles^^
nuclear@0 285
nuclear@0 286 vector<aiVector3D> UniquePositions(UniqueVertexCount);
nuclear@0 287
nuclear@0 288 vector<aiVector3D> UniqueNormals(UniqueVertexCount);
nuclear@0 289
nuclear@0 290 vector<aiVector3D> UniqueTangents(UniqueVertexCount);
nuclear@0 291
nuclear@0 292 vector< vector<Weight> > UniqueWeights(UniqueVertexCount);
nuclear@0 293
nuclear@0 294 vector< vector<aiVector3D> > UniqueUvs(theSubMesh.Uvs.size());
nuclear@0 295 for(unsigned int i=0; i<UniqueUvs.size(); ++i) UniqueUvs[i].resize(UniqueVertexCount);
nuclear@0 296
nuclear@0 297
nuclear@0 298
nuclear@0 299 //Support for shared data:
nuclear@0 300 /*We can use this loop to copy vertex informations from the shared data pool. In order to do so
nuclear@0 301 we just use a reference to a submodel instead of our submodel itself*/
nuclear@0 302
nuclear@0 303 SubMesh& VertexSource= theSubMesh.SharedData ? theSharedGeometry : theSubMesh;
nuclear@0 304 if(theSubMesh.SharedData)//copy vertexinformations to our mesh:
nuclear@0 305 {
nuclear@0 306 theSubMesh.HasPositions=theSharedGeometry.HasPositions;
nuclear@0 307 theSubMesh.HasNormals=theSharedGeometry.HasNormals;
nuclear@0 308 theSubMesh.HasTangents=theSharedGeometry.HasTangents;
nuclear@0 309
nuclear@0 310 theSubMesh.BonesUsed=theSharedGeometry.BonesUsed;
nuclear@0 311
nuclear@0 312 UniqueUvs.resize(theSharedGeometry.Uvs.size());
nuclear@0 313 for(unsigned int i=0; i<UniqueUvs.size(); ++i) UniqueUvs[i].resize(UniqueVertexCount);
nuclear@0 314 }
nuclear@0 315
nuclear@0 316 for(unsigned int i=0; i<theSubMesh.FaceList.size(); ++i)
nuclear@0 317 {
nuclear@0 318 //We precalculate the index vlaues her, because we need them in all vertex attributes
nuclear@0 319 unsigned int Vertex1=theSubMesh.FaceList[i].VertexIndices[0];
nuclear@0 320 unsigned int Vertex2=theSubMesh.FaceList[i].VertexIndices[1];
nuclear@0 321 unsigned int Vertex3=theSubMesh.FaceList[i].VertexIndices[2];
nuclear@0 322
nuclear@0 323 UniquePositions[3*i+0]=VertexSource.Positions[Vertex1];
nuclear@0 324 UniquePositions[3*i+1]=VertexSource.Positions[Vertex2];
nuclear@0 325 UniquePositions[3*i+2]=VertexSource.Positions[Vertex3];
nuclear@0 326
nuclear@0 327 if(VertexSource.HasNormals)
nuclear@0 328 {
nuclear@0 329 UniqueNormals[3*i+0]=VertexSource.Normals[Vertex1];
nuclear@0 330 UniqueNormals[3*i+1]=VertexSource.Normals[Vertex2];
nuclear@0 331 UniqueNormals[3*i+2]=VertexSource.Normals[Vertex3];
nuclear@0 332 }
nuclear@0 333
nuclear@0 334 if(VertexSource.HasTangents)
nuclear@0 335 {
nuclear@0 336 UniqueTangents[3*i+0]=VertexSource.Tangents[Vertex1];
nuclear@0 337 UniqueTangents[3*i+1]=VertexSource.Tangents[Vertex2];
nuclear@0 338 UniqueTangents[3*i+2]=VertexSource.Tangents[Vertex3];
nuclear@0 339 }
nuclear@0 340
nuclear@0 341 if(UniqueUvs.size()>0)
nuclear@0 342 {
nuclear@0 343 for(unsigned int j=0; j<UniqueUvs.size(); ++j)
nuclear@0 344 {
nuclear@0 345 UniqueUvs[j][3*i+0]=VertexSource.Uvs[j][Vertex1];
nuclear@0 346 UniqueUvs[j][3*i+1]=VertexSource.Uvs[j][Vertex2];
nuclear@0 347 UniqueUvs[j][3*i+2]=VertexSource.Uvs[j][Vertex3];
nuclear@0 348 }
nuclear@0 349 }
nuclear@0 350
nuclear@0 351 if(VertexSource.Weights.size() > 0)
nuclear@0 352 {
nuclear@0 353 UniqueWeights[3*i+0]=VertexSource.Weights[Vertex1];
nuclear@0 354 UniqueWeights[3*i+1]=VertexSource.Weights[Vertex2];
nuclear@0 355 UniqueWeights[3*i+2]=VertexSource.Weights[Vertex3];
nuclear@0 356 }
nuclear@0 357
nuclear@0 358 //The indexvalues a just continuous numbers (0, 1, 2, 3, 4, 5, 6...)
nuclear@0 359 UniqueFaceList[i].VertexIndices[0]=3*i+0;
nuclear@0 360 UniqueFaceList[i].VertexIndices[1]=3*i+1;
nuclear@0 361 UniqueFaceList[i].VertexIndices[2]=3*i+2;
nuclear@0 362 }
nuclear@0 363 //_________________________________________________________________________________________
nuclear@0 364
nuclear@0 365 //now we have the unique datas, but want them in the SubMesh, so we swap all the containers:
nuclear@0 366 //if we don't have one of them, we just swap empty containers, so everything is ok
nuclear@0 367 theSubMesh.FaceList.swap(UniqueFaceList);
nuclear@0 368 theSubMesh.Positions.swap(UniquePositions);
nuclear@0 369 theSubMesh.Normals.swap(UniqueNormals);
nuclear@0 370 theSubMesh.Tangents.swap(UniqueTangents);
nuclear@0 371 theSubMesh.Uvs.swap(UniqueUvs);
nuclear@0 372 theSubMesh.Weights.swap(UniqueWeights);
nuclear@0 373
nuclear@0 374
nuclear@0 375
nuclear@0 376 //------------- normalize weights -----------------------------
nuclear@0 377 //The Blender exporter doesn't care about whether the sum of all boneweights for a single vertex equals 1 or not,
nuclear@0 378 //so we have to make this sure:
nuclear@0 379 for(unsigned int VertexId=0; VertexId<theSubMesh.Weights.size(); ++VertexId)//iterate over all vertices
nuclear@0 380 {
nuclear@0 381 float WeightSum=0.0f;
nuclear@0 382 for(unsigned int BoneId=0; BoneId<theSubMesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones
nuclear@0 383 {
nuclear@0 384 WeightSum+=theSubMesh.Weights[VertexId][BoneId].Value;
nuclear@0 385 }
nuclear@0 386
nuclear@0 387 //check if the sum is too far away from 1
nuclear@0 388 if(WeightSum<1.0f-0.05f || WeightSum>1.0f+0.05f)
nuclear@0 389 {
nuclear@0 390 //normalize all weights:
nuclear@0 391 for(unsigned int BoneId=0; BoneId<theSubMesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones
nuclear@0 392 {
nuclear@0 393 theSubMesh.Weights[VertexId][BoneId].Value/=WeightSum;
nuclear@0 394 }
nuclear@0 395 }
nuclear@0 396 }
nuclear@0 397 //_________________________________________________________
nuclear@0 398 }
nuclear@0 399
nuclear@0 400
nuclear@0 401
nuclear@0 402
nuclear@0 403 aiMesh* OgreImporter::CreateAssimpSubMesh(const SubMesh& theSubMesh, const vector<Bone>& Bones) const
nuclear@0 404 {
nuclear@0 405 const aiScene* const m_CurrentScene=this->m_CurrentScene;//make sure, that we can access but not change the scene
nuclear@0 406 (void)m_CurrentScene;
nuclear@0 407
nuclear@0 408 aiMesh* NewAiMesh=new aiMesh();
nuclear@0 409
nuclear@0 410 //Positions
nuclear@0 411 NewAiMesh->mVertices=new aiVector3D[theSubMesh.Positions.size()];
nuclear@0 412 memcpy(NewAiMesh->mVertices, &theSubMesh.Positions[0], theSubMesh.Positions.size()*sizeof(aiVector3D));
nuclear@0 413 NewAiMesh->mNumVertices=theSubMesh.Positions.size();
nuclear@0 414
nuclear@0 415 //Normals
nuclear@0 416 if(theSubMesh.HasNormals)
nuclear@0 417 {
nuclear@0 418 NewAiMesh->mNormals=new aiVector3D[theSubMesh.Normals.size()];
nuclear@0 419 memcpy(NewAiMesh->mNormals, &theSubMesh.Normals[0], theSubMesh.Normals.size()*sizeof(aiVector3D));
nuclear@0 420 }
nuclear@0 421
nuclear@0 422
nuclear@0 423 //until we have support for bitangents, no tangents will be written
nuclear@0 424 /*
nuclear@0 425 //Tangents
nuclear@0 426 if(theSubMesh.HasTangents)
nuclear@0 427 {
nuclear@0 428 NewAiMesh->mTangents=new aiVector3D[theSubMesh.Tangents.size()];
nuclear@0 429 memcpy(NewAiMesh->mTangents, &theSubMesh.Tangents[0], theSubMesh.Tangents.size()*sizeof(aiVector3D));
nuclear@0 430 }
nuclear@0 431 */
nuclear@0 432
nuclear@0 433 //Uvs
nuclear@0 434 if(theSubMesh.Uvs.size()>0)
nuclear@0 435 {
nuclear@0 436 for(unsigned int i=0; i<theSubMesh.Uvs.size(); ++i)
nuclear@0 437 {
nuclear@0 438 NewAiMesh->mNumUVComponents[i]=2;
nuclear@0 439 NewAiMesh->mTextureCoords[i]=new aiVector3D[theSubMesh.Uvs[i].size()];
nuclear@0 440 memcpy(NewAiMesh->mTextureCoords[i], &(theSubMesh.Uvs[i][0]), theSubMesh.Uvs[i].size()*sizeof(aiVector3D));
nuclear@0 441 }
nuclear@0 442 }
nuclear@0 443
nuclear@0 444
nuclear@0 445 //---------------------------------------- Bones --------------------------------------------
nuclear@0 446
nuclear@0 447 //Copy the weights in in Bone-Vertices Struktur
nuclear@0 448 //(we have them in a Vertex-Bones Structur, this is much easier for making them unique, which is required by assimp
nuclear@0 449 vector< vector<aiVertexWeight> > aiWeights(theSubMesh.BonesUsed);//now the outer list are the bones, and the inner vector the vertices
nuclear@0 450 for(unsigned int VertexId=0; VertexId<theSubMesh.Weights.size(); ++VertexId)//iterate over all vertices
nuclear@0 451 {
nuclear@0 452 for(unsigned int BoneId=0; BoneId<theSubMesh.Weights[VertexId].size(); ++BoneId)//iterate over all bones
nuclear@0 453 {
nuclear@0 454 aiVertexWeight NewWeight;
nuclear@0 455 NewWeight.mVertexId=VertexId;//the current Vertex, we can't use the Id form the submehs weights, because they are bone id's
nuclear@0 456 NewWeight.mWeight=theSubMesh.Weights[VertexId][BoneId].Value;
nuclear@0 457 aiWeights[theSubMesh.Weights[VertexId][BoneId].BoneId].push_back(NewWeight);
nuclear@0 458 }
nuclear@0 459 }
nuclear@0 460
nuclear@0 461
nuclear@0 462
nuclear@0 463 vector<aiBone*> aiBones;
nuclear@0 464 aiBones.reserve(theSubMesh.BonesUsed);//the vector might be smaller, because there might be empty bones (bones that are not attached to any vertex)
nuclear@0 465
nuclear@0 466 //create all the bones and fill them with informations
nuclear@0 467 for(unsigned int i=0; i<theSubMesh.BonesUsed; ++i)
nuclear@0 468 {
nuclear@0 469 if(aiWeights[i].size()>0)
nuclear@0 470 {
nuclear@0 471 aiBone* NewBone=new aiBone();
nuclear@0 472 NewBone->mNumWeights=aiWeights[i].size();
nuclear@0 473 NewBone->mWeights=new aiVertexWeight[aiWeights[i].size()];
nuclear@0 474 memcpy(NewBone->mWeights, &(aiWeights[i][0]), sizeof(aiVertexWeight)*aiWeights[i].size());
nuclear@0 475 NewBone->mName=Bones[i].Name;//The bone list should be sorted after its id's, this was done in LoadSkeleton
nuclear@0 476 NewBone->mOffsetMatrix=Bones[i].BoneToWorldSpace;
nuclear@0 477
nuclear@0 478 aiBones.push_back(NewBone);
nuclear@0 479 }
nuclear@0 480 }
nuclear@0 481 NewAiMesh->mNumBones=aiBones.size();
nuclear@0 482
nuclear@0 483 // mBones must be NULL if mNumBones is non 0 or the validation fails.
nuclear@0 484 if (aiBones.size()) {
nuclear@0 485 NewAiMesh->mBones=new aiBone* [aiBones.size()];
nuclear@0 486 memcpy(NewAiMesh->mBones, &(aiBones[0]), aiBones.size()*sizeof(aiBone*));
nuclear@0 487 }
nuclear@0 488
nuclear@0 489 //______________________________________________________________________________________________________
nuclear@0 490
nuclear@0 491
nuclear@0 492
nuclear@0 493 //Faces
nuclear@0 494 NewAiMesh->mFaces=new aiFace[theSubMesh.FaceList.size()];
nuclear@0 495 for(unsigned int i=0; i<theSubMesh.FaceList.size(); ++i)
nuclear@0 496 {
nuclear@0 497 NewAiMesh->mFaces[i].mNumIndices=3;
nuclear@0 498 NewAiMesh->mFaces[i].mIndices=new unsigned int[3];
nuclear@0 499
nuclear@0 500 NewAiMesh->mFaces[i].mIndices[0]=theSubMesh.FaceList[i].VertexIndices[0];
nuclear@0 501 NewAiMesh->mFaces[i].mIndices[1]=theSubMesh.FaceList[i].VertexIndices[1];
nuclear@0 502 NewAiMesh->mFaces[i].mIndices[2]=theSubMesh.FaceList[i].VertexIndices[2];
nuclear@0 503 }
nuclear@0 504 NewAiMesh->mNumFaces=theSubMesh.FaceList.size();
nuclear@0 505
nuclear@0 506 //Link the material:
nuclear@0 507 NewAiMesh->mMaterialIndex=theSubMesh.MaterialIndex;//the index is set by the function who called ReadSubMesh
nuclear@0 508
nuclear@0 509 return NewAiMesh;
nuclear@0 510 }
nuclear@0 511
nuclear@0 512
nuclear@0 513 }//namespace Ogre
nuclear@0 514 }//namespace Assimp
nuclear@0 515
nuclear@0 516 #endif // !! ASSIMP_BUILD_NO_OGRE_IMPORTER