/****************************************************************************** libx42.net - skinned vertex animation library (.NET API) Copyright (C) 2007 HermitWorks Entertainment Corporation This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA. ******************************************************************************/ #include "Stdafx.h" #include "AnimationBuffer.h" #include "Model.h" #include "Group.h" #include "Pose.h" #include "Vector.h" #include "UtilTypes.h" namespace Libx42 { typedef mem_helper< __m128 > xmm_helper; AnimationBuffer::AnimationBuffer( Model ^owner, AnimationFlags flags ) : owner( owner ) { size_t numVerts = owner->m->header.numVerts; xmm_helper posHelper( numVerts ); xmm_helper normHelper, tanHelper, binHelper; if( (flags & AnimationFlags::IncludeNormals) != AnimationFlags::None ) normHelper.alloc( numVerts ); if( (flags & AnimationFlags::IncludeTangents) != AnimationFlags::None ) tanHelper.alloc( numVerts ); if( (flags & AnimationFlags::IncludeBinormals) != AnimationFlags::None ) binHelper.alloc( numVerts ); posBuf = posHelper.get(); normBuf = normHelper.get(); tanBuf = tanHelper.get(); binBuf = binHelper.get(); posStream = gcnew DataStream< Math::Vector3 >( owner, posBuf, sizeof( __m128 ), sizeof( float ), (int)numVerts ); if( normBuf ) normStream = gcnew DataStream< Math::Vector3 >( owner, normBuf, sizeof( __m128 ), sizeof( float ), (int)numVerts ); if( tanBuf ) tanStream = gcnew DataStream< Math::Vector3 >( owner, tanBuf, sizeof( __m128 ), sizeof( float ), (int)numVerts ); if( binBuf ) binStream = gcnew DataStream< Math::Vector3 >( owner, binBuf, sizeof( __m128 ), sizeof( float ), (int)numVerts ); posHelper.release(); normHelper.release(); tanHelper.release(); binHelper.release(); } AnimationBuffer::~AnimationBuffer( void ) { AnimationBuffer::!AnimationBuffer(); } AnimationBuffer::!AnimationBuffer( void ) { xmm_helper::free( posBuf ); xmm_helper::free( normBuf ); xmm_helper::free( tanBuf ); xmm_helper::free( binBuf ); } void AnimationBuffer::AnimateVertices( Pose ^pose ) { if( !pose ) throw gcnew ArgumentNullException( "pose" ); for( uint i = 0; i < owner->m->header.numGroups; i++ ) AnimateVertices( pose, i ); } void AnimationBuffer::AnimateVertices( Pose ^pose, Group ^group ) { if( !pose ) throw gcnew ArgumentNullException( "pose" ); if( !group ) throw gcnew ArgumentNullException( "group" ); if( group->Owner != owner ) throw gcnew ArgumentException(); AnimateVertices( pose, group->Index ); } void AnimationBuffer::AnimateVertices( Pose ^pose, ... array< Group^ > ^groupsToUpdate ) { if( !pose ) throw gcnew ArgumentNullException( "pose" ); if( !groupsToUpdate ) throw gcnew ArgumentNullException( "groupsToUpdate" ); for( int i = 0; i < groupsToUpdate->Length; i++ ) { Group ^group = groupsToUpdate[i]; if( group->Owner != owner ) throw gcnew ArgumentException(); AnimateVertices( pose, group->Index ); } } void AnimationBuffer::AnimateVertices( Pose ^pose, uint groupNum ) { x42memStream_t sPos; x42memStream_t sNorm, *pNorm = 0; x42memStream_t sTan, *pTan = 0; x42memStream_t sBin, *pBin = 0; uint firstVert = owner->m->groups[groupNum].firstVert; sPos.pStreamZero = posBuf + firstVert; sPos.scratchBytes = 4; sPos.stride = 16; if( normBuf ) { sNorm.pStreamZero = normBuf + firstVert; sNorm.scratchBytes = 4; sNorm.stride = 16; pNorm = &sNorm; } if( tanBuf ) { sTan.pStreamZero = tanBuf + firstVert; sTan.scratchBytes = 4; sTan.stride = 16; pTan = &sTan; } if( binBuf ) { sBin.pStreamZero = binBuf + firstVert; sBin.scratchBytes = 4; sBin.stride = 16; pBin = &sBin; } bool didAnim = x42_SkinGroupVerts( &sPos, pNorm, pTan, pBin, owner->m, groupNum, pose->boneMats, owner->Opts->opts ); if( !didAnim ) throw gcnew Exception( "Failed to animate vertices." ); } };