+++ /dev/null
-#include "stdafx.h"\r
-/*\r
-* Copyright (c) 2007-2010 SlimDX Group\r
-* \r
-* Permission is hereby granted, free of charge, to any person obtaining a copy\r
-* of this software and associated documentation files (the "Software"), to deal\r
-* in the Software without restriction, including without limitation the rights\r
-* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r
-* copies of the Software, and to permit persons to whom the Software is\r
-* furnished to do so, subject to the following conditions:\r
-* \r
-* The above copyright notice and this permission notice shall be included in\r
-* all copies or substantial portions of the Software.\r
-* \r
-* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
-* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
-* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
-* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
-* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r
-* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\r
-* THE SOFTWARE.\r
-*/\r
-#include <d3d9.h>\r
-#include <d3dx9.h>\r
-#include <vcclr.h>\r
-\r
-#include "../stack_array.h"\r
-#include "../DataStream.h"\r
-#include "../ComObject.h"\r
-\r
-#include "Device.h"\r
-#include "IndexBuffer.h"\r
-#include "Mesh.h"\r
-#include "SkinInfo.h"\r
-\r
-#include "Direct3D9Exception.h"\r
-\r
-using namespace System;\r
-\r
-namespace SlimDX\r
-{\r
-namespace Direct3D9\r
-{\r
- SkinInfo::SkinInfo( int vertexCount, array<VertexElement>^ vertexDeclaration, int boneCount )\r
- {\r
- ID3DXSkinInfo *result;\r
-\r
- pin_ptr<VertexElement> pinnedDecl = &vertexDeclaration[0];\r
-\r
- HRESULT hr = D3DXCreateSkinInfo( vertexCount, reinterpret_cast<const D3DVERTEXELEMENT9*>( pinnedDecl ),\r
- boneCount, &result );\r
- \r
- if( RECORD_D3D9( hr ).IsFailure )\r
- throw gcnew Direct3D9Exception( Result::Last );\r
-\r
- Construct( result );\r
- }\r
-\r
- SkinInfo::SkinInfo( BaseMesh^ mesh, int boneCount, array<BoneCombination^>^ boneCombinationTable )\r
- {\r
- ID3DXSkinInfo *result;\r
-\r
- int length = boneCombinationTable->Length;\r
- stack_array<D3DXBONECOMBINATION> bones = stackalloc( D3DXBONECOMBINATION, length );\r
- for( int i = 0; i < length; i++ )\r
- bones[i] = boneCombinationTable[i]->ToUnmanaged();\r
-\r
- HRESULT hr = D3DXCreateSkinInfoFromBlendedMesh( mesh->InternalPointer, boneCount, &bones[0], &result );\r
-\r
- for( int i = 0; i < length; i++ )\r
- delete[] bones[i].BoneId;\r
-\r
- if( RECORD_D3D9( hr ).IsFailure )\r
- throw gcnew Direct3D9Exception( Result::Last );\r
-\r
- Construct( result );\r
- }\r
-\r
- SkinInfo::SkinInfo( int vertexCount, SlimDX::Direct3D9::VertexFormat fvf, int boneCount )\r
- {\r
- ID3DXSkinInfo *result;\r
-\r
- HRESULT hr = D3DXCreateSkinInfoFVF( vertexCount, static_cast<DWORD>( fvf ),\r
- boneCount, &result );\r
- \r
- if( RECORD_D3D9( hr ).IsFailure )\r
- throw gcnew Direct3D9Exception( Result::Last );\r
-\r
- Construct( result );\r
- }\r
-\r
- SkinInfo^ SkinInfo::Clone()\r
- {\r
- ID3DXSkinInfo *result;\r
-\r
- HRESULT hr = InternalPointer->Clone( &result );\r
- \r
- if( RECORD_D3D9( hr ).IsFailure )\r
- return nullptr;\r
-\r
- return gcnew SkinInfo( result, nullptr );\r
- }\r
-\r
- Mesh^ SkinInfo::ConvertToBlendedMesh( Mesh^ mesh, array<int>^ adjacency,\r
- [Out] array<int>^% faceRemap, [Out] array<int>^% vertexRemap, [Out] int% maxVertexInfluence,\r
- [Out] array<BoneCombination^>^% boneCombinationTable )\r
- {\r
- ID3DXMesh *result;\r
- ID3DXBuffer *vr;\r
- ID3DXBuffer *bct;\r
- DWORD mvi;\r
- DWORD bcc;\r
- DWORD *adjacencyIn = NULL;\r
-\r
- faceRemap = gcnew array<int>( mesh->FaceCount );\r
-\r
- array<int>^ adjacencyOut = gcnew array<int>( mesh->FaceCount * 3 );\r
-\r
- pin_ptr<int> pinnedAdjIn;\r
- pin_ptr<int> pinnedAdjOut = &adjacencyOut[0];\r
- pin_ptr<int> pinnedFR = &faceRemap[0];\r
-\r
- if( adjacency != nullptr )\r
- {\r
- pinnedAdjIn = &adjacency[0];\r
- adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
- }\r
-\r
- HRESULT hr = InternalPointer->ConvertToBlendedMesh( mesh->InternalPointer, 0, adjacencyIn,\r
- reinterpret_cast<DWORD*>( pinnedAdjOut ), reinterpret_cast<DWORD*>( pinnedFR ), &vr, &mvi, &bcc, &bct, &result );\r
- \r
- if( RECORD_D3D9( hr ).IsFailure )\r
- {\r
- boneCombinationTable = nullptr;\r
- maxVertexInfluence = 0;\r
- vertexRemap = nullptr;\r
- faceRemap = nullptr;\r
- return nullptr;\r
- }\r
-\r
- boneCombinationTable = gcnew array<BoneCombination^>( bcc );\r
- LPD3DXBONECOMBINATION pointer = reinterpret_cast<LPD3DXBONECOMBINATION>( bct->GetBufferPointer() );\r
-\r
- for( DWORD i = 0; i < bcc; i++ )\r
- {\r
- boneCombinationTable[i] = BoneCombination::FromUnmanaged( pointer[i] );\r
- boneCombinationTable[i]->BoneIds = gcnew array<int>( mvi );\r
- for( DWORD j = 0; j < mvi; j++ )\r
- boneCombinationTable[i]->BoneIds[j] = pointer[i].BoneId[j]; \r
- }\r
-\r
- Mesh^ out = Mesh::FromPointer( result );\r
- if( adjacency != nullptr )\r
- out->SetAdjacency( adjacencyOut );\r
- else\r
- out->SetAdjacency( NULL );\r
-\r
- maxVertexInfluence = mvi;\r
- vertexRemap = Utilities::ReadRange<int>( vr, result->GetNumVertices() );\r
- return out;\r
- }\r
-\r
- Mesh^ SkinInfo::ConvertToBlendedMesh( Mesh^ mesh, array<int>^ adjacency,\r
- [Out] int% maxVertexInfluence, [Out] array<BoneCombination^>^% boneCombinationTable )\r
- {\r
- ID3DXMesh *result;\r
- ID3DXBuffer *bct;\r
- DWORD mvi;\r
- DWORD bcc;\r
- DWORD *adjacencyIn = NULL;\r
-\r
- array<int>^ adjacencyOut = gcnew array<int>( mesh->FaceCount * 3 );\r
-\r
- pin_ptr<int> pinnedAdjIn;\r
- pin_ptr<int> pinnedAdjOut = &adjacencyOut[0];\r
-\r
- if( adjacency != nullptr )\r
- {\r
- pinnedAdjIn = &adjacency[0];\r
- adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
- }\r
-\r
- HRESULT hr = InternalPointer->ConvertToBlendedMesh( mesh->InternalPointer, 0, adjacencyIn,\r
- reinterpret_cast<DWORD*>( pinnedAdjOut ), NULL, NULL, &mvi, &bcc, &bct, &result );\r
- \r
- if( RECORD_D3D9( hr ).IsFailure )\r
- {\r
- boneCombinationTable = nullptr;\r
- maxVertexInfluence = 0;\r
- return nullptr;\r
- }\r
-\r
- boneCombinationTable = gcnew array<BoneCombination^>( bcc );\r
- LPD3DXBONECOMBINATION pointer = reinterpret_cast<LPD3DXBONECOMBINATION>( bct->GetBufferPointer() );\r
-\r
- for( DWORD i = 0; i < bcc; i++ )\r
- {\r
- boneCombinationTable[i] = BoneCombination::FromUnmanaged( pointer[i] );\r
- boneCombinationTable[i]->BoneIds = gcnew array<int>( mvi );\r
- for( DWORD j = 0; j < mvi; j++ )\r
- boneCombinationTable[i]->BoneIds[j] = pointer[i].BoneId[j]; \r
- }\r
-\r
- Mesh^ out = Mesh::FromPointer( result );\r
- if( adjacency != nullptr )\r
- out->SetAdjacency( adjacencyOut );\r
- else\r
- out->SetAdjacency( NULL );\r
-\r
- maxVertexInfluence = mvi;\r
- return out;\r
- }\r
-\r
- Mesh^ SkinInfo::ConvertToIndexedBlendedMesh( Mesh^ mesh, int paletteSize, array<int>^ adjacency,\r
- [Out] array<int>^% faceRemap, [Out] array<int>^% vertexRemap, [Out] int% maxVertexInfluence,\r
- [Out] array<BoneCombination^>^% boneCombinationTable )\r
- {\r
- ID3DXMesh *result;\r
- ID3DXBuffer *vr;\r
- ID3DXBuffer *bct;\r
- DWORD mvi;\r
- DWORD bcc;\r
- DWORD *adjacencyIn = NULL;\r
-\r
- faceRemap = gcnew array<int>( mesh->FaceCount );\r
-\r
- array<int>^ adjacencyOut = gcnew array<int>( mesh->FaceCount * 3 );\r
-\r
- pin_ptr<int> pinnedAdjIn;\r
- pin_ptr<int> pinnedAdjOut = &adjacencyOut[0];\r
-\r
- if( adjacency != nullptr )\r
- {\r
- pinnedAdjIn = &adjacency[0];\r
- adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
- }\r
-\r
- pin_ptr<int> pinnedFR = &faceRemap[0];\r
-\r
- HRESULT hr = InternalPointer->ConvertToIndexedBlendedMesh( mesh->InternalPointer, 0, paletteSize, adjacencyIn,\r
- reinterpret_cast<DWORD*>( pinnedAdjOut ), reinterpret_cast<DWORD*>( pinnedFR ), &vr, &mvi, &bcc, &bct, &result );\r
- \r
- if( RECORD_D3D9( hr ).IsFailure )\r
- {\r
- boneCombinationTable = nullptr;\r
- maxVertexInfluence = 0;\r
- vertexRemap = nullptr;\r
- faceRemap = nullptr;\r
- return nullptr;\r
- }\r
-\r
- boneCombinationTable = gcnew array<BoneCombination^>( bcc );\r
- LPD3DXBONECOMBINATION pointer = reinterpret_cast<LPD3DXBONECOMBINATION>( bct->GetBufferPointer() );\r
-\r
- for( DWORD i = 0; i < bcc; i++ )\r
- {\r
- boneCombinationTable[i] = BoneCombination::FromUnmanaged( pointer[i] );\r
- boneCombinationTable[i]->BoneIds = gcnew array<int>( paletteSize );\r
- for( int j = 0; j < paletteSize; j++ )\r
- boneCombinationTable[i]->BoneIds[j] = pointer[i].BoneId[j]; \r
- }\r
-\r
- Mesh^ out = Mesh::FromPointer( result );\r
- if( adjacency != nullptr )\r
- out->SetAdjacency( adjacencyOut );\r
- else\r
- out->SetAdjacency( NULL );\r
-\r
- maxVertexInfluence = mvi;\r
- vertexRemap = Utilities::ReadRange<int>( vr, result->GetNumVertices() );\r
- return out;\r
- }\r
-\r
- Mesh^ SkinInfo::ConvertToIndexedBlendedMesh( Mesh^ mesh, int paletteSize, array<int>^ adjacency,\r
- [Out] int% maxVertexInfluence, [Out] array<BoneCombination^>^% boneCombinationTable )\r
- {\r
- ID3DXMesh *result;\r
- ID3DXBuffer *bct;\r
- DWORD mvi;\r
- DWORD bcc;\r
- DWORD *adjacencyIn = NULL;\r
-\r
- array<int>^ adjacencyOut = gcnew array<int>( mesh->FaceCount * 3 );\r
-\r
- pin_ptr<int> pinnedAdjIn;\r
- pin_ptr<int> pinnedAdjOut = &adjacencyOut[0];\r
-\r
- if( adjacency != nullptr )\r
- {\r
- pinnedAdjIn = &adjacency[0];\r
- adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
- }\r
-\r
- HRESULT hr = InternalPointer->ConvertToIndexedBlendedMesh( mesh->InternalPointer, 0, paletteSize, adjacencyIn,\r
- reinterpret_cast<DWORD*>( pinnedAdjOut ), NULL, NULL, &mvi, &bcc, &bct, &result );\r
- \r
- if( RECORD_D3D9( hr ).IsFailure )\r
- {\r
- boneCombinationTable = nullptr;\r
- maxVertexInfluence = 0;\r
- return nullptr;\r
- }\r
-\r
- boneCombinationTable = gcnew array<BoneCombination^>( bcc );\r
- LPD3DXBONECOMBINATION pointer = reinterpret_cast<LPD3DXBONECOMBINATION>( bct->GetBufferPointer() );\r
-\r
- for( DWORD i = 0; i < bcc; i++ )\r
- {\r
- boneCombinationTable[i] = BoneCombination::FromUnmanaged( pointer[i] );\r
- boneCombinationTable[i]->BoneIds = gcnew array<int>( paletteSize );\r
- for( int j = 0; j < paletteSize; j++ )\r
- boneCombinationTable[i]->BoneIds[j] = pointer[i].BoneId[j]; \r
- }\r
-\r
- Mesh^ out = Mesh::FromPointer( result );\r
- if( adjacency != nullptr )\r
- out->SetAdjacency( adjacencyOut );\r
- else\r
- out->SetAdjacency( NULL );\r
-\r
- maxVertexInfluence = mvi;\r
- return out;\r
- }\r
-\r
- int SkinInfo::FindBoneVertexInfluenceIndex( int bone, int vertex )\r
- {\r
- DWORD influence;\r
-\r
- HRESULT hr = InternalPointer->FindBoneVertexInfluenceIndex( bone, vertex, &influence );\r
- \r
- if( RECORD_D3D9( hr ).IsFailure )\r
- return 0;\r
-\r
- return influence;\r
- }\r
-\r
- Result SkinInfo::GetBoneInfluence( int bone, [Out] array<int>^% vertices, [Out] array<float>^% weights )\r
- {\r
- int count = GetBoneInfluenceCount( bone );\r
- vertices = gcnew array<int>( count );\r
- weights = gcnew array<float>( count );\r
-\r
- pin_ptr<int> pinnedVerts = &vertices[0];\r
- pin_ptr<float> pinnedWeights = &weights[0];\r
-\r
- HRESULT hr = InternalPointer->GetBoneInfluence( bone, reinterpret_cast<DWORD*>( pinnedVerts ),\r
- reinterpret_cast<float*>( pinnedWeights ) );\r
- \r
- if( RECORD_D3D9( hr ).IsFailure )\r
- {\r
- vertices = nullptr;\r
- weights = nullptr;\r
- }\r
-\r
- return Result::Last;\r
- }\r
-\r
- Result SkinInfo::SetBoneInfluence( int bone, array<int>^ vertices, array<float>^ weights )\r
- {\r
- pin_ptr<int> pinnedVerts = &vertices[0];\r
- pin_ptr<float> pinnedWeights = &weights[0];\r
-\r
- HRESULT hr = InternalPointer->SetBoneInfluence( bone, vertices->Length, reinterpret_cast<const DWORD*>( pinnedVerts ),\r
- reinterpret_cast<const float*>( pinnedWeights ) );\r
- \r
- return RECORD_D3D9( hr );\r
- }\r
-\r
- String^ SkinInfo::GetBoneName( int bone )\r
- {\r
- return gcnew String( InternalPointer->GetBoneName( bone ) );\r
- }\r
-\r
- Result SkinInfo::SetBoneName( int bone, String^ name )\r
- {\r
- array<unsigned char>^ nameBytes = System::Text::ASCIIEncoding::ASCII->GetBytes( name );\r
- pin_ptr<unsigned char> pinnedName = &nameBytes[0];\r
-\r
- HRESULT hr = InternalPointer->SetBoneName( bone, reinterpret_cast<LPCSTR>( pinnedName ) );\r
- return RECORD_D3D9( hr );\r
- }\r
-\r
- Result SkinInfo::GetBoneVertexInfluence( int bone, int influence, [Out] float% weight, [Out] int% vertex )\r
- {\r
- float w;\r
- DWORD v;\r
-\r
- HRESULT hr = InternalPointer->GetBoneVertexInfluence( bone, influence, &w, &v );\r
-\r
- if( RECORD_D3D9( hr ).IsFailure )\r
- {\r
- weight = 0;\r
- vertex = 0;\r
- }\r
- else\r
- {\r
- weight = w;\r
- vertex = v;\r
- }\r
-\r
- return Result::Last;\r
- }\r
-\r
- Result SkinInfo::SetBoneVertexInfluence( int bone, int influence, float weight )\r
- {\r
- HRESULT hr = InternalPointer->SetBoneVertexInfluence( bone, influence, weight );\r
- return RECORD_D3D9( hr );\r
- }\r
-\r
- Matrix SkinInfo::GetBoneOffsetMatrix( int bone )\r
- {\r
- return Matrix::FromD3DXMATRIX( *InternalPointer->GetBoneOffsetMatrix( bone ) );\r
- }\r
-\r
- Result SkinInfo::SetBoneOffsetMatrix( int bone, Matrix matrix )\r
- {\r
- HRESULT hr = InternalPointer->SetBoneOffsetMatrix( bone, reinterpret_cast<D3DXMATRIX*>( &matrix ) );\r
- return RECORD_D3D9( hr );\r
- }\r
-\r
- array<VertexElement>^ SkinInfo::GetDeclaration()\r
- {\r
- D3DVERTEXELEMENT9 elementBuffer[MAX_FVF_DECL_SIZE];\r
- HRESULT hr = InternalPointer->GetDeclaration( elementBuffer );\r
- \r
- if( RECORD_D3D9( hr ).IsFailure )\r
- return nullptr;\r
-\r
- // Apparently the returned decl does not include an End element. This is bizarre and confusing,\r
- // not to mention completely unexpected. We patch it up here.\r
- int count = D3DXGetDeclLength( elementBuffer ) + 1;\r
- array<VertexElement>^ elements = gcnew array<VertexElement>( count );\r
- pin_ptr<VertexElement> pinnedElements = &elements[0];\r
- memcpy( pinnedElements, elementBuffer, count * sizeof(D3DVERTEXELEMENT9) );\r
- elements[count - 1] = VertexElement::VertexDeclarationEnd;\r
-\r
- return elements;\r
- }\r
-\r
- Result SkinInfo::SetDeclaration( array<VertexElement>^ declaration )\r
- {\r
- pin_ptr<VertexElement> pinnedDecl = &declaration[0];\r
-\r
- HRESULT hr = InternalPointer->SetDeclaration( reinterpret_cast<D3DVERTEXELEMENT9*>( pinnedDecl ) );\r
- return RECORD_D3D9( hr );\r
- }\r
-\r
- int SkinInfo::GetMaxFaceInfluences( IndexBuffer^ indexBuffer, int faceCount )\r
- {\r
- DWORD ret;\r
-\r
- HRESULT hr = InternalPointer->GetMaxFaceInfluences( indexBuffer->InternalPointer, faceCount, &ret );\r
- \r
- if( RECORD_D3D9( hr ).IsFailure )\r
- return 0;\r
-\r
- return ret;\r
- }\r
-\r
- Result SkinInfo::Remap( array<int>^ remapData )\r
- {\r
- pin_ptr<int> pinnedData = &remapData[0];\r
-\r
- HRESULT hr = InternalPointer->Remap( remapData->Length, reinterpret_cast<DWORD*>( pinnedData ) );\r
- return RECORD_D3D9( hr );\r
- }\r
-\r
- Result SkinInfo::UpdateSkinnedMesh( array<Matrix>^ boneTransforms, array<Matrix>^ boneInvTransposeTransforms, DataStream^ source, DataStream^ destination )\r
- {\r
- pin_ptr<Matrix> pinnedTransforms = &boneTransforms[0];\r
- pin_ptr<Matrix> pinnedInvTransforms = &boneInvTransposeTransforms[0];\r
-\r
- HRESULT hr = InternalPointer->UpdateSkinnedMesh( reinterpret_cast<const D3DXMATRIX*>( pinnedTransforms ),\r
- reinterpret_cast<const D3DXMATRIX*>( pinnedInvTransforms ), source->PositionPointer, destination->PositionPointer );\r
- return RECORD_D3D9( hr );\r
- }\r
-\r
- int SkinInfo::GetBoneInfluenceCount( int bone )\r
- {\r
- return InternalPointer->GetNumBoneInfluences( bone );\r
- }\r
-\r
- int SkinInfo::MaximumVertexInfluences::get()\r
- {\r
- DWORD result;\r
-\r
- HRESULT hr = InternalPointer->GetMaxVertexInfluences( &result );\r
- \r
- if( RECORD_D3D9( hr ).IsFailure )\r
- return 0;\r
-\r
- return result;\r
- }\r
-\r
- int SkinInfo::BoneCount::get()\r
- {\r
- return InternalPointer->GetNumBones();\r
- }\r
-\r
- float SkinInfo::MinimumBoneInfluence::get()\r
- {\r
- return InternalPointer->GetMinBoneInfluence();\r
- }\r
-\r
- void SkinInfo::MinimumBoneInfluence::set( float value )\r
- {\r
- HRESULT hr = InternalPointer->SetMinBoneInfluence( value );\r
- RECORD_D3D9( hr );\r
- }\r
-\r
- SlimDX::Direct3D9::VertexFormat SkinInfo::VertexFormat::get()\r
- {\r
- return static_cast<SlimDX::Direct3D9::VertexFormat>( InternalPointer->GetFVF() );\r
- }\r
-\r
- void SkinInfo::VertexFormat::set( SlimDX::Direct3D9::VertexFormat value )\r
- {\r
- HRESULT hr = InternalPointer->SetFVF( static_cast<DWORD>( value ) );\r
- RECORD_D3D9( hr );\r
- }\r
-}\r
-}\r