vrshoot

diff 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 diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libs/assimp/SkeletonMeshBuilder.cpp	Sat Feb 01 19:58:19 2014 +0200
     1.3 @@ -0,0 +1,267 @@
     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 +/** @file  SkeletonMeshBuilder.cpp
    1.45 + *  @brief Implementation of a little class to construct a dummy mesh for a skeleton 
    1.46 + */
    1.47 +
    1.48 +#include "AssimpPCH.h"
    1.49 +#include "assimp/scene.h"
    1.50 +#include "SkeletonMeshBuilder.h"
    1.51 +
    1.52 +using namespace Assimp;
    1.53 +
    1.54 +// ------------------------------------------------------------------------------------------------
    1.55 +// The constructor processes the given scene and adds a mesh there. 
    1.56 +SkeletonMeshBuilder::SkeletonMeshBuilder( aiScene* pScene, aiNode* root, bool bKnobsOnly)
    1.57 +{
    1.58 +	// nothing to do if there's mesh data already present at the scene
    1.59 +	if( pScene->mNumMeshes > 0 || pScene->mRootNode == NULL)
    1.60 +		return;
    1.61 +
    1.62 +	if (!root)
    1.63 +		root = pScene->mRootNode;
    1.64 +
    1.65 +	mKnobsOnly = bKnobsOnly;
    1.66 +
    1.67 +	// build some faces around each node 
    1.68 +	CreateGeometry( root );
    1.69 +
    1.70 +	// create a mesh to hold all the generated faces
    1.71 +	pScene->mNumMeshes = 1;
    1.72 +	pScene->mMeshes = new aiMesh*[1];
    1.73 +	pScene->mMeshes[0] = CreateMesh();
    1.74 +	// and install it at the root node
    1.75 +	root->mNumMeshes = 1;
    1.76 +	root->mMeshes = new unsigned int[1];
    1.77 +	root->mMeshes[0] = 0;
    1.78 +
    1.79 +	// create a dummy material for the mesh
    1.80 +	pScene->mNumMaterials = 1;
    1.81 +	pScene->mMaterials = new aiMaterial*[1];
    1.82 +	pScene->mMaterials[0] = CreateMaterial();
    1.83 +}
    1.84 +
    1.85 +// ------------------------------------------------------------------------------------------------
    1.86 +// Recursively builds a simple mesh representation for the given node 
    1.87 +void SkeletonMeshBuilder::CreateGeometry( const aiNode* pNode)
    1.88 +{
    1.89 +	// add a joint entry for the node. 
    1.90 +	const unsigned int vertexStartIndex = mVertices.size();
    1.91 +
    1.92 +	// now build the geometry. 
    1.93 +	if( pNode->mNumChildren > 0 && !mKnobsOnly)
    1.94 +	{
    1.95 +		// If the node has children, we build little pointers to each of them
    1.96 +		for( unsigned int a = 0; a < pNode->mNumChildren; a++)
    1.97 +		{
    1.98 +			// find a suitable coordinate system
    1.99 +			const aiMatrix4x4& childTransform = pNode->mChildren[a]->mTransformation;
   1.100 +			aiVector3D childpos( childTransform.a4, childTransform.b4, childTransform.c4);
   1.101 +			float distanceToChild = childpos.Length();
   1.102 +			if( distanceToChild < 0.0001f)
   1.103 +				continue;
   1.104 +			aiVector3D up = aiVector3D( childpos).Normalize();
   1.105 +
   1.106 +			aiVector3D orth( 1.0f, 0.0f, 0.0f);
   1.107 +			if( fabs( orth * up) > 0.99f)
   1.108 +				orth.Set( 0.0f, 1.0f, 0.0f);
   1.109 +
   1.110 +			aiVector3D front = (up ^ orth).Normalize();
   1.111 +			aiVector3D side = (front ^ up).Normalize();
   1.112 +
   1.113 +			unsigned int localVertexStart = mVertices.size();
   1.114 +			mVertices.push_back( -front * distanceToChild * 0.1f);
   1.115 +			mVertices.push_back( childpos);
   1.116 +			mVertices.push_back( -side * distanceToChild * 0.1f);
   1.117 +			mVertices.push_back( -side * distanceToChild * 0.1f);
   1.118 +			mVertices.push_back( childpos);
   1.119 +			mVertices.push_back( front * distanceToChild * 0.1f);
   1.120 +			mVertices.push_back( front * distanceToChild * 0.1f);
   1.121 +			mVertices.push_back( childpos);
   1.122 +			mVertices.push_back( side * distanceToChild * 0.1f);
   1.123 +			mVertices.push_back( side * distanceToChild * 0.1f);
   1.124 +			mVertices.push_back( childpos);
   1.125 +			mVertices.push_back( -front * distanceToChild * 0.1f);
   1.126 +
   1.127 +			mFaces.push_back( Face( localVertexStart + 0, localVertexStart + 1, localVertexStart + 2));
   1.128 +			mFaces.push_back( Face( localVertexStart + 3, localVertexStart + 4, localVertexStart + 5));
   1.129 +			mFaces.push_back( Face( localVertexStart + 6, localVertexStart + 7, localVertexStart + 8));
   1.130 +			mFaces.push_back( Face( localVertexStart + 9, localVertexStart + 10, localVertexStart + 11));
   1.131 +		}
   1.132 +	} 
   1.133 +	else
   1.134 +	{
   1.135 +		// if the node has no children, it's an end node. Put a little knob there instead
   1.136 +		aiVector3D ownpos( pNode->mTransformation.a4, pNode->mTransformation.b4, pNode->mTransformation.c4);
   1.137 +		float sizeEstimate = ownpos.Length() * 0.18f;
   1.138 +
   1.139 +		mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
   1.140 +		mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
   1.141 +		mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
   1.142 +		mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
   1.143 +		mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
   1.144 +		mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
   1.145 +		mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
   1.146 +		mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
   1.147 +		mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
   1.148 +		mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
   1.149 +		mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
   1.150 +		mVertices.push_back( aiVector3D( 0.0f, 0.0f, -sizeEstimate));
   1.151 +
   1.152 +		mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
   1.153 +		mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
   1.154 +		mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
   1.155 +		mVertices.push_back( aiVector3D( 0.0f, sizeEstimate, 0.0f));
   1.156 +		mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
   1.157 +		mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
   1.158 +		mVertices.push_back( aiVector3D( sizeEstimate, 0.0f, 0.0f));
   1.159 +		mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
   1.160 +		mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
   1.161 +		mVertices.push_back( aiVector3D( 0.0f, -sizeEstimate, 0.0f));
   1.162 +		mVertices.push_back( aiVector3D( 0.0f, 0.0f, sizeEstimate));
   1.163 +		mVertices.push_back( aiVector3D( -sizeEstimate, 0.0f, 0.0f));
   1.164 +
   1.165 +		mFaces.push_back( Face( vertexStartIndex + 0, vertexStartIndex + 1, vertexStartIndex + 2));
   1.166 +		mFaces.push_back( Face( vertexStartIndex + 3, vertexStartIndex + 4, vertexStartIndex + 5));
   1.167 +		mFaces.push_back( Face( vertexStartIndex + 6, vertexStartIndex + 7, vertexStartIndex + 8));
   1.168 +		mFaces.push_back( Face( vertexStartIndex + 9, vertexStartIndex + 10, vertexStartIndex + 11));
   1.169 +		mFaces.push_back( Face( vertexStartIndex + 12, vertexStartIndex + 13, vertexStartIndex + 14));
   1.170 +		mFaces.push_back( Face( vertexStartIndex + 15, vertexStartIndex + 16, vertexStartIndex + 17));
   1.171 +		mFaces.push_back( Face( vertexStartIndex + 18, vertexStartIndex + 19, vertexStartIndex + 20));
   1.172 +		mFaces.push_back( Face( vertexStartIndex + 21, vertexStartIndex + 22, vertexStartIndex + 23));
   1.173 +	}
   1.174 +
   1.175 +	unsigned int numVertices = mVertices.size() - vertexStartIndex;
   1.176 +	if( numVertices > 0)
   1.177 +	{
   1.178 +		// create a bone affecting all the newly created vertices
   1.179 +		aiBone* bone = new aiBone;
   1.180 +		mBones.push_back( bone);
   1.181 +		bone->mName = pNode->mName;
   1.182 +
   1.183 +		// calculate the bone offset matrix by concatenating the inverse transformations of all parents
   1.184 +		bone->mOffsetMatrix = aiMatrix4x4( pNode->mTransformation).Inverse();
   1.185 +		for( aiNode* parent = pNode->mParent; parent != NULL; parent = parent->mParent)
   1.186 +			bone->mOffsetMatrix = aiMatrix4x4( parent->mTransformation).Inverse() * bone->mOffsetMatrix;
   1.187 +
   1.188 +		// add all the vertices to the bone's influences
   1.189 +		bone->mNumWeights = numVertices;
   1.190 +		bone->mWeights = new aiVertexWeight[numVertices];
   1.191 +		for( unsigned int a = 0; a < numVertices; a++)
   1.192 +			bone->mWeights[a] = aiVertexWeight( vertexStartIndex + a, 1.0f);
   1.193 +
   1.194 +		// HACK: (thom) transform all vertices to the bone's local space. Should be done before adding
   1.195 +		// them to the array, but I'm tired now and I'm annoyed.
   1.196 +		aiMatrix4x4 boneToMeshTransform = aiMatrix4x4( bone->mOffsetMatrix).Inverse();
   1.197 +		for( unsigned int a = vertexStartIndex; a < mVertices.size(); a++)
   1.198 +			mVertices[a] = boneToMeshTransform * mVertices[a];
   1.199 +	}
   1.200 +
   1.201 +	// and finally recurse into the children list
   1.202 +	for( unsigned int a = 0; a < pNode->mNumChildren; a++)
   1.203 +		CreateGeometry( pNode->mChildren[a]);
   1.204 +}
   1.205 +
   1.206 +// ------------------------------------------------------------------------------------------------
   1.207 +// Creates the mesh from the internally accumulated stuff and returns it.
   1.208 +aiMesh* SkeletonMeshBuilder::CreateMesh()
   1.209 +{
   1.210 +	aiMesh* mesh = new aiMesh();
   1.211 +
   1.212 +	// add points
   1.213 +	mesh->mNumVertices = mVertices.size();
   1.214 +	mesh->mVertices = new aiVector3D[mesh->mNumVertices];
   1.215 +	std::copy( mVertices.begin(), mVertices.end(), mesh->mVertices);
   1.216 +
   1.217 +	mesh->mNormals = new aiVector3D[mesh->mNumVertices];
   1.218 +
   1.219 +	// add faces
   1.220 +	mesh->mNumFaces = mFaces.size();
   1.221 +	mesh->mFaces = new aiFace[mesh->mNumFaces];
   1.222 +	for( unsigned int a = 0; a < mesh->mNumFaces; a++)
   1.223 +	{
   1.224 +		const Face& inface = mFaces[a];
   1.225 +		aiFace& outface = mesh->mFaces[a];
   1.226 +		outface.mNumIndices = 3;
   1.227 +		outface.mIndices = new unsigned int[3];
   1.228 +		outface.mIndices[0] = inface.mIndices[0];
   1.229 +		outface.mIndices[1] = inface.mIndices[1];
   1.230 +		outface.mIndices[2] = inface.mIndices[2];
   1.231 +
   1.232 +		// Compute per-face normals ... we don't want the bones to be smoothed ... they're built to visualize
   1.233 +		// the skeleton, so it's good if there's a visual difference to the rest of the geometry
   1.234 +		aiVector3D nor = ((mVertices[inface.mIndices[2]] - mVertices[inface.mIndices[0]]) ^ 
   1.235 +			(mVertices[inface.mIndices[1]] - mVertices[inface.mIndices[0]]));
   1.236 +
   1.237 +		if (nor.Length() < 1e-5f) /* ensure that FindInvalidData won't remove us ...*/
   1.238 +			nor = aiVector3D(1.f,0.f,0.f);
   1.239 +
   1.240 +		for (unsigned int n = 0; n < 3; ++n)
   1.241 +			mesh->mNormals[inface.mIndices[n]] = nor;
   1.242 +	}
   1.243 +
   1.244 +	// add the bones
   1.245 +	mesh->mNumBones = mBones.size();
   1.246 +	mesh->mBones = new aiBone*[mesh->mNumBones];
   1.247 +	std::copy( mBones.begin(), mBones.end(), mesh->mBones);
   1.248 +
   1.249 +	// default
   1.250 +	mesh->mMaterialIndex = 0;
   1.251 +
   1.252 +	return mesh;
   1.253 +}
   1.254 +
   1.255 +// ------------------------------------------------------------------------------------------------
   1.256 +// Creates a dummy material and returns it.
   1.257 +aiMaterial* SkeletonMeshBuilder::CreateMaterial()
   1.258 +{
   1.259 +	aiMaterial* matHelper = new aiMaterial;
   1.260 +
   1.261 +	// Name
   1.262 +	aiString matName( std::string( "SkeletonMaterial"));
   1.263 +	matHelper->AddProperty( &matName, AI_MATKEY_NAME);
   1.264 +
   1.265 +	// Prevent backface culling
   1.266 +	const int no_cull = 1;
   1.267 +	matHelper->AddProperty(&no_cull,1,AI_MATKEY_TWOSIDED);
   1.268 +
   1.269 +	return matHelper;
   1.270 +}