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
|