/****************************************************************************** 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 "Pose.h" #include "Model.h" #include "UtilTypes.h" namespace Libx42 { Pose::Pose( Model ^owner ) : owner( owner ) { size_t cbAnimFrames = x42_GetAnimFramesSize( owner->m ); size_t cbAnimLerp = x42_GetAnimLerpSize( owner->m ); buf_helper animFramesHelper( cbAnimFrames ); buf_helper animLerpHelper( cbAnimLerp ); buf_helper boneMatsHelper( sizeof( affine_t ) * owner->m->header.numBones ); buf_helper tagMatsHelper( sizeof( affine_t ) * owner->m->header.numTags ); animFrames = x42_CreateAnimFrames( animFramesHelper.get(), owner->m ); if( animFrames != animFramesHelper.get() ) throw gcnew Exception( "Failed to create animation frames buffer." ); animLerp = x42_CreateAnimLerp( animLerpHelper.get(), owner->m ); if( animLerp != animLerpHelper.get() ) throw gcnew Exception( "Failed to create animation values buffer." ); boneMats = (affine_t*)boneMatsHelper.get(); tagMats = (affine_t*)tagMatsHelper.get(); boneMatsColl = gcnew DataStream< Math::Affine >( owner, boneMats, sizeof( x42::math::affine ), 0, owner->m->header.numBones, true ); tagMatsColl = gcnew DataStream< Math::Affine >( owner, tagMats, sizeof( x42::math::affine ), 0, owner->m->header.numTags, true ); posStream = gcnew DataStream< Math::Vector3 >( owner, animLerp->p, sizeof( x42::math::vec3 ), 0, owner->m->header.numBones, true ); rotStream = gcnew DataStream< Math::Quaternion >( owner, animLerp->r, sizeof( x42::math::quat ), 0, owner->m->header.numBones, true ); scaleStream = gcnew DataStream< Math::Vector3 >( owner, animLerp->s, sizeof( x42::math::vec3 ), 0, owner->m->header.numBones, true ); Build( 0.0F ); animFramesHelper.release(); animLerpHelper.release(); boneMatsHelper.release(); tagMatsHelper.release(); } Pose::~Pose() { Pose::!Pose(); } Pose::!Pose() { buf_helper::free( animFrames ); buf_helper::free( animLerp ); buf_helper::free( boneMats ); buf_helper::free( tagMats ); } void Pose::GeneratePoseValues( float time ) { bool stat; if( !animFrames ) throw gcnew ObjectDisposedException( "Pose" ); if( !owner->m->header.numBones ) return; if( time < owner->BaseFrame ) time = (float)owner->BaseFrame; if( time > owner->BaseFrame + owner->FrameCount - 1.0F ) time = owner->BaseFrame + owner->FrameCount - 1.0F; array< float > ^times = gcnew array< float >( owner->m->header.numAnimGroups ); for( int i = 0; i < times->Length; i++ ) times[i] = time; pin_ptr< float > pinTimes = ×[0]; stat = x42_UpdateAnimFrames( animFrames, owner->m, pinTimes, owner->Opts->opts ); pinTimes = nullptr; if( !stat ) throw gcnew Exception( "Failed to update anim frames." ); stat = x42_LerpAnims( animLerp, owner->m, animFrames, owner->Opts->opts ); if( !stat ) throw gcnew Exception( "Failed to buld pose." ); } void Pose::GenerateMatrices( void ) { if( !animFrames ) throw gcnew ObjectDisposedException( "Pose" ); affine_t *tmp; tmp = x42_GetAnimBoneMatrices( boneMats, owner->m, animLerp, owner->Opts->opts ); if( tmp != boneMats ) throw gcnew Exception( "Failed to build pose." ); tmp = x42_GetAnimTagMatrices( tagMats, owner->m, boneMats, owner->Opts->opts ); if( tmp != tagMats ) throw gcnew Exception( "Failed to build pose." ); tagMatsColl->pBase = tagMats; } void Pose::GeneratePoseData( void ) { if( !animFrames ) throw gcnew ObjectDisposedException( "Pose" ); //nop } void Pose::Build( float time ) { GeneratePoseValues( time ); GenerateMatrices(); GeneratePoseData(); } }