vrshoot

view libs/assimp/SkeletonMeshBuilder.cpp @ 0:b2f14e535253

initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 01 Feb 2014 19:58:19 +0200
parents
children
line source
1 /*
2 Open Asset Import Library (assimp)
3 ----------------------------------------------------------------------
5 Copyright (c) 2006-2012, assimp team
6 All rights reserved.
8 Redistribution and use of this software in source and binary forms,
9 with or without modification, are permitted provided that the
10 following conditions are met:
12 * Redistributions of source code must retain the above
13 copyright notice, this list of conditions and the
14 following disclaimer.
16 * Redistributions in binary form must reproduce the above
17 copyright notice, this list of conditions and the
18 following disclaimer in the documentation and/or other
19 materials provided with the distribution.
21 * Neither the name of the assimp team, nor the names of its
22 contributors may be used to endorse or promote products
23 derived from this software without specific prior
24 written permission of the assimp team.
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
29 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
30 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
31 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
33 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
34 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
35 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
36 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 ----------------------------------------------------------------------
39 */
41 /** @file SkeletonMeshBuilder.cpp
42 * @brief Implementation of a little class to construct a dummy mesh for a skeleton
43 */
45 #include "AssimpPCH.h"
46 #include "assimp/scene.h"
47 #include "SkeletonMeshBuilder.h"
49 using namespace Assimp;
51 // ------------------------------------------------------------------------------------------------
52 // The constructor processes the given scene and adds a mesh there.
53 SkeletonMeshBuilder::SkeletonMeshBuilder( aiScene* pScene, aiNode* root, bool bKnobsOnly)
54 {
55 // nothing to do if there's mesh data already present at the scene
56 if( pScene->mNumMeshes > 0 || pScene->mRootNode == NULL)
57 return;
59 if (!root)
60 root = pScene->mRootNode;
62 mKnobsOnly = bKnobsOnly;
64 // build some faces around each node
65 CreateGeometry( root );
67 // create a mesh to hold all the generated faces
68 pScene->mNumMeshes = 1;
69 pScene->mMeshes = new aiMesh*[1];
70 pScene->mMeshes[0] = CreateMesh();
71 // and install it at the root node
72 root->mNumMeshes = 1;
73 root->mMeshes = new unsigned int[1];
74 root->mMeshes[0] = 0;
76 // create a dummy material for the mesh
77 pScene->mNumMaterials = 1;
78 pScene->mMaterials = new aiMaterial*[1];
79 pScene->mMaterials[0] = CreateMaterial();
80 }
82 // ------------------------------------------------------------------------------------------------
83 // Recursively builds a simple mesh representation for the given node
84 void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode)
85 {
86 // add a joint entry for the node.
87 const unsigned int vertexStartIndex = mVertices.size();
89 // now build the geometry.
90 if( pNode->mNumChildren > 0 && !mKnobsOnly)
91 {
92 // If the node has children, we build little pointers to each of them
93 for( unsigned int a = 0; a < pNode->mNumChildren; a++)
94 {
95 // find a suitable coordinate system
96 const aiMatrix4x4& childTransform = pNode->mChildren[a]->mTransformation;
97 aiVector3D childpos( childTransform.a4, childTransform.b4, childTransform.c4);
98 float distanceToChild = childpos.Length();
99 if( distanceToChild < 0.0001f)
100 continue;
101 aiVector3D up = aiVector3D( childpos).Normalize();
103 aiVector3D orth( 1.0f, 0.0f, 0.0f);
104 if( fabs( orth * up) > 0.99f)
105 orth.Set( 0.0f, 1.0f, 0.0f);
107 aiVector3D front = (up ^ orth).Normalize();
108 aiVector3D side = (front ^ up).Normalize();
110 unsigned int localVertexStart = mVertices.size();
111 mVertices.push_back( -front * distanceToChild * 0.1f);
112 mVertices.push_back( childpos);
113 mVertices.push_back( -side * distanceToChild * 0.1f);
114 mVertices.push_back( -side * distanceToChild * 0.1f);
115 mVertices.push_back( childpos);
116 mVertices.push_back( front * distanceToChild * 0.1f);
117 mVertices.push_back( front * distanceToChild * 0.1f);
118 mVertices.push_back( childpos);
119 mVertices.push_back( side * distanceToChild * 0.1f);
120 mVertices.push_back( side * distanceToChild * 0.1f);
121 mVertices.push_back( childpos);
122 mVertices.push_back( -front * distanceToChild * 0.1f);
124 mFaces.push_back( Face( localVertexStart + 0, localVertexStart + 1, localVertexStart + 2));
125 mFaces.push_back( Face( localVertexStart + 3, localVertexStart + 4, localVertexStart + 5));
126 mFaces.push_back( Face( localVertexStart + 6, localVertexStart + 7, localVertexStart + 8));
127 mFaces.push_back( Face( localVertexStart + 9, localVertexStart + 10, localVertexStart + 11));
128 }
129 }
130 else
131 {
132 // if the node has no children, it's an end node. Put a little knob there instead
133 aiVector3D ownpos( pNode->mTransformation.a4, pNode->mTransformation.b4, pNode->mTransformation.c4);
134 float sizeEstimate = ownpos.Length() * 0.18f;
136 mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
137 mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
138 mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
139 mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
140 mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
141 mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
142 mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
143 mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
144 mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
145 mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
146 mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
147 mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
149 mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
150 mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
151 mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
152 mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
153 mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
154 mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
155 mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
156 mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
157 mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
158 mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
159 mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
160 mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
162 mFaces.push_back( Face( vertexStartIndex + 0, vertexStartIndex + 1, vertexStartIndex + 2));
163 mFaces.push_back( Face( vertexStartIndex + 3, vertexStartIndex + 4, vertexStartIndex + 5));
164 mFaces.push_back( Face( vertexStartIndex + 6, vertexStartIndex + 7, vertexStartIndex + 8));
165 mFaces.push_back( Face( vertexStartIndex + 9, vertexStartIndex + 10, vertexStartIndex + 11));
166 mFaces.push_back( Face( vertexStartIndex + 12, vertexStartIndex + 13, vertexStartIndex + 14));
167 mFaces.push_back( Face( vertexStartIndex + 15, vertexStartIndex + 16, vertexStartIndex + 17));
168 mFaces.push_back( Face( vertexStartIndex + 18, vertexStartIndex + 19, vertexStartIndex + 20));
169 mFaces.push_back( Face( vertexStartIndex + 21, vertexStartIndex + 22, vertexStartIndex + 23));
170 }
172 unsigned int numVertices = mVertices.size() - vertexStartIndex;
173 if( numVertices > 0)
174 {
175 // create a bone affecting all the newly created vertices
176 aiBone* bone = new aiBone;
177 mBones.push_back( bone);
178 bone->mName = pNode->mName;
180 // calculate the bone offset matrix by concatenating the inverse transformations of all parents
181 bone->mOffsetMatrix = aiMatrix4x4( pNode->mTransformation).Inverse();
182 for( aiNode* parent = pNode->mParent; parent != NULL; parent = parent->mParent)
183 bone->mOffsetMatrix = aiMatrix4x4( parent->mTransformation).Inverse() * bone->mOffsetMatrix;
185 // add all the vertices to the bone's influences
186 bone->mNumWeights = numVertices;
187 bone->mWeights = new aiVertexWeight[numVertices];
188 for( unsigned int a = 0; a < numVertices; a++)
189 bone->mWeights[a] = aiVertexWeight( vertexStartIndex + a, 1.0f);
191 // HACK: (thom) transform all vertices to the bone's local space. Should be done before adding
192 // them to the array, but I'm tired now and I'm annoyed.
193 aiMatrix4x4 boneToMeshTransform = aiMatrix4x4( bone->mOffsetMatrix).Inverse();
194 for( unsigned int a = vertexStartIndex; a < mVertices.size(); a++)
195 mVertices[a] = boneToMeshTransform * mVertices[a];
196 }
198 // and finally recurse into the children list
199 for( unsigned int a = 0; a < pNode->mNumChildren; a++)
200 CreateGeometry( pNode->mChildren[a]);
201 }
203 // ------------------------------------------------------------------------------------------------
204 // Creates the mesh from the internally accumulated stuff and returns it.
205 aiMesh* SkeletonMeshBuilder::CreateMesh()
206 {
207 aiMesh* mesh = new aiMesh();
209 // add points
210 mesh->mNumVertices = mVertices.size();
211 mesh->mVertices = new aiVector3D[mesh->mNumVertices];
212 std::copy( mVertices.begin(), mVertices.end(), mesh->mVertices);
214 mesh->mNormals = new aiVector3D[mesh->mNumVertices];
216 // add faces
217 mesh->mNumFaces = mFaces.size();
218 mesh->mFaces = new aiFace[mesh->mNumFaces];
219 for( unsigned int a = 0; a < mesh->mNumFaces; a++)
220 {
221 const Face& inface = mFaces[a];
222 aiFace& outface = mesh->mFaces[a];
223 outface.mNumIndices = 3;
224 outface.mIndices = new unsigned int[3];
225 outface.mIndices[0] = inface.mIndices[0];
226 outface.mIndices[1] = inface.mIndices[1];
227 outface.mIndices[2] = inface.mIndices[2];
229 // Compute per-face normals ... we don't want the bones to be smoothed ... they're built to visualize
230 // the skeleton, so it's good if there's a visual difference to the rest of the geometry
231 aiVector3D nor = ((mVertices[inface.mIndices[2]] - mVertices[inface.mIndices[0]]) ^
232 (mVertices[inface.mIndices[1]] - mVertices[inface.mIndices[0]]));
234 if (nor.Length() < 1e-5f) /* ensure that FindInvalidData won't remove us ...*/
235 nor = aiVector3D(1.f,0.f,0.f);
237 for (unsigned int n = 0; n < 3; ++n)
238 mesh->mNormals[inface.mIndices[n]] = nor;
239 }
241 // add the bones
242 mesh->mNumBones = mBones.size();
243 mesh->mBones = new aiBone*[mesh->mNumBones];
244 std::copy( mBones.begin(), mBones.end(), mesh->mBones);
246 // default
247 mesh->mMaterialIndex = 0;
249 return mesh;
250 }
252 // ------------------------------------------------------------------------------------------------
253 // Creates a dummy material and returns it.
254 aiMaterial* SkeletonMeshBuilder::CreateMaterial()
255 {
256 aiMaterial* matHelper = new aiMaterial;
258 // Name
259 aiString matName( std::string( "SkeletonMaterial"));
260 matHelper->AddProperty( &matName, AI_MATKEY_NAME);
262 // Prevent backface culling
263 const int no_cull = 1;
264 matHelper->AddProperty(&no_cull,1,AI_MATKEY_TWOSIDED);
266 return matHelper;
267 }