/****************************************************************************** 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 "Model.h" #include "UtilTypes.h" #include "StreamAdapter.h" #include "AnimationBuffer.h" #include "Bone.h" #include "AnimationGroup.h" #include "AnimationData.h" #include "Influence.h" #include "Tag.h" #include "Group.h" #include "Lod.h" #include "Pose.h" #include "IndexCollection.h" #include "VertexData.h" using namespace System; using namespace System::Collections::Generic; using namespace System::IO; namespace Libx42 { Model::Model( String ^path ) { if( !path ) throw gcnew ArgumentNullException( "path" ); FileStream file( path, FileMode::Open, FileAccess::Read, FileShare::Read ); StreamAdapter adapter( %file ); InitFromStream( %adapter ); } Model::Model( System::IO::Stream ^stream ) { if( !stream ) throw gcnew ArgumentNullException( "stream" ); if( !stream->CanRead ) throw gcnew ArgumentException(); StreamAdapter adapter( stream ); InitFromStream( %adapter ); } Model::Model( Runtime::Serialization::SerializationInfo^ info, Runtime::Serialization::StreamingContext /* context */ ) { if( !info ) throw gcnew ArgumentNullException( "info" ); array< Byte > ^buf = static_cast< array< Byte >^ >( info->GetValue( "m", array< Byte >::typeid ) ); pin_ptr< Byte > rawBuf = &buf[0]; InitFromBuffer( (x42data_t*)rawBuf, buf->Length ); } Model::Model( const x42data_t *src, size_t cb ) { InitFromBuffer( src, cb ); } Model::Model( Model ^src ) { if( !src ) throw gcnew ArgumentNullException( "src" ); InitFromBuffer( src->m, src->mBuf_size ); } void Model::InitFromStream( StreamAdapter ^adapter ) { x42header_t hBuf, *h; h = x42_LoadHeaderFromStream( &hBuf, adapter->InStream ); if( !h ) throw gcnew Exception( "Failed to read file header." ); size_t cb = x42_GetLoadedSize( h, X42_PERSIST_EVERYTHING ); if( !cb ) throw gcnew Exception( "Failed to compute model data size." ); mBuf_size = (int)cb; buf_helper mHelper( cb ); m = x42_LoadDataFromStream( mHelper.get(), h, X42_PERSIST_EVERYTHING, adapter->InStream ); if( m != mHelper.get() ) throw gcnew Exception( "Failed to load model data." ); FinishInit(); mHelper.release(); } void Model::InitFromBuffer( const x42data_t *src, size_t cb ) { buf_helper mHelper( cb ); m = x42_CopyRuntimeData( mHelper.get(), src ); if( m != mHelper.get() ) throw gcnew Exception( "Failed to load model data." ); FinishInit(); mHelper.release(); } void Model::FinishInit( void ) { bones = gcnew BoneCollection( this ); animGroups = gcnew AnimationGroupCollection( this ); animData = gcnew Libx42::AnimationData( this ); infs = gcnew InfluenceCollection( this ); tags = gcnew TagCollection( this ); groups = gcnew GroupCollection( this, 0, m->header.numGroups ); lods = gcnew LodCollection( this ); indices = gcnew IndexCollection( this ); verts = gcnew VertexData( this ); } void Model::GetObjectData( Runtime::Serialization::SerializationInfo^ info, Runtime::Serialization::StreamingContext /* context */ ) { array< Byte > ^buf = gcnew array< Byte >( mBuf_size ); pin_ptr< Byte > pin_buf = &buf[0]; memcpy( pin_buf, m, mBuf_size ); pin_buf = nullptr; info->AddValue( "m", buf ); } Model::~Model( void ) { delete tmp; tmp = nullptr; delete opts; opts = nullptr; Model::!Model(); } Model::!Model( void ) { buf_helper::free( m ); } Pose^ Model::CreatePose( void ) { return gcnew Pose( this ); } AnimationBuffer^ Model::CreateAnimationBuffer( AnimationFlags flags ) { return gcnew AnimationBuffer( this, flags ); } TempMem^ Model::TmpMem::get( void ) { if( !tmp ) tmp = gcnew TempMem; return tmp; } OptimizationContext^ Model::Opts::get( void ) { if( !opts ) opts = gcnew OptimizationContext; return opts; } void Model::CheckDisposed( void ) { if( !m ) throw gcnew ObjectDisposedException( "Model" ); } void Model::Save( Stream ^stream ) { StreamAdapter adapter( stream ); Save( %adapter ); } void Model::Save( String ^filename ) { FileStream file( filename, FileMode::Create, FileAccess::Write, FileShare::None ); Save( %file ); } void Model::Save( StreamAdapter ^adapter ) { x42_WriteToStream( adapter->OutStream, X42_PERSIST_EVERYTHING, m ); } String^ Model::GetModelString( x42NameIndex_t string ) { return GetGcString( m->strings + string ); } };