3 * Copyright (c) 2007-2010 SlimDX Group
\r
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
\r
6 * of this software and associated documentation files (the "Software"), to deal
\r
7 * in the Software without restriction, including without limitation the rights
\r
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
\r
9 * copies of the Software, and to permit persons to whom the Software is
\r
10 * furnished to do so, subject to the following conditions:
\r
12 * The above copyright notice and this permission notice shall be included in
\r
13 * all copies or substantial portions of the Software.
\r
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
\r
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
\r
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
\r
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
\r
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
\r
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
\r
27 #include "../stack_array.h"
\r
28 #include "../ComObject.h"
\r
29 #include "../Utilities.h"
\r
30 #include "../DataStream.h"
\r
32 #include "Direct3D9Exception.h"
\r
35 #include "Texture.h"
\r
36 #include "IndexBuffer.h"
\r
37 #include "VertexBuffer.h"
\r
39 #include "SkinInfo.h"
\r
41 using namespace System;
\r
42 using namespace System::IO;
\r
43 using namespace System::Drawing;
\r
44 using namespace System::Runtime::InteropServices;
\r
50 Mesh::Mesh( SlimDX::Direct3D9::Device^ device, int numFaces, int numVertices, MeshFlags options, array<VertexElement>^ vertexDeclaration )
\r
52 ID3DXMesh* mesh = NULL;
\r
53 pin_ptr<VertexElement> pinnedDecl = &vertexDeclaration[0];
\r
55 HRESULT hr = D3DXCreateMesh( numFaces, numVertices, static_cast<DWORD>( options ),
\r
56 reinterpret_cast<D3DVERTEXELEMENT9*>( pinnedDecl ), device->InternalPointer, &mesh );
\r
58 if( RECORD_D3D9( hr ).IsFailure )
\r
59 throw gcnew Direct3D9Exception( Result::Last );
\r
64 Mesh::Mesh( SlimDX::Direct3D9::Device^ device, int numFaces, int numVertices, MeshFlags options, SlimDX::Direct3D9::VertexFormat fvf )
\r
66 ID3DXMesh* mesh = NULL;
\r
68 HRESULT hr = D3DXCreateMeshFVF( numFaces, numVertices, static_cast<DWORD>( options ),
\r
69 static_cast<DWORD>( fvf ), device->InternalPointer, &mesh );
\r
71 if( RECORD_D3D9( hr ).IsFailure )
\r
72 throw gcnew Direct3D9Exception( Result::Last );
\r
77 Mesh^ Mesh::FromMemory_Internal( SlimDX::Direct3D9::Device^ device, const void* memory, DWORD size, MeshFlags flags )
\r
79 ID3DXMesh* mesh = NULL;
\r
80 ID3DXBuffer* adjacencyBuffer = NULL;
\r
81 ID3DXBuffer* materialBuffer = NULL;
\r
82 ID3DXBuffer* instanceBuffer = NULL;
\r
83 DWORD materialCount = 0;
\r
85 HRESULT hr = D3DXLoadMeshFromXInMemory( memory, size, static_cast<DWORD>( flags ), device->InternalPointer,
\r
86 &adjacencyBuffer, &materialBuffer, &instanceBuffer, &materialCount, &mesh );
\r
88 if( RECORD_D3D9( hr ).IsFailure )
\r
91 Mesh^ result = Mesh::FromPointer( mesh );
\r
93 result->SetAdjacency( Utilities::ReadRange<int>( adjacencyBuffer, mesh->GetNumFaces() * 3 ) );
\r
94 result->SetMaterials( ExtendedMaterial::FromBuffer( materialBuffer, materialCount ) );
\r
95 result->SetEffects( EffectInstance::FromBuffer( instanceBuffer, materialCount ) );
\r
97 materialBuffer->Release();
\r
98 instanceBuffer->Release();
\r
103 Mesh^ Mesh::FromMemory( SlimDX::Direct3D9::Device^ device, array<Byte>^ memory, MeshFlags flags )
\r
105 pin_ptr<unsigned char> pinnedMemory = &memory[0];
\r
106 return Mesh::FromMemory_Internal( device, pinnedMemory, static_cast<DWORD>( memory->Length ), flags );
\r
109 Mesh^ Mesh::FromStream( SlimDX::Direct3D9::Device^ device, Stream^ stream, MeshFlags flags )
\r
111 DataStream^ ds = nullptr;
\r
112 array<Byte>^ data = Utilities::ReadStream( stream, &ds );
\r
114 if( data == nullptr )
\r
116 DWORD size = static_cast<DWORD>( ds->RemainingLength );
\r
117 return Mesh::FromMemory_Internal( device, ds->SeekToEnd(), size, flags );
\r
120 return Mesh::FromMemory( device, data, flags );
\r
123 Mesh^ Mesh::FromFile( SlimDX::Direct3D9::Device^ device, String^ fileName, MeshFlags flags )
\r
125 ID3DXMesh* mesh = NULL;
\r
126 ID3DXBuffer* adjacencyBuffer = NULL;
\r
127 ID3DXBuffer* materialBuffer = NULL;
\r
128 ID3DXBuffer* instanceBuffer = NULL;
\r
129 DWORD materialCount = 0;
\r
130 pin_ptr<const wchar_t> pinnedFileName = PtrToStringChars( fileName );
\r
132 HRESULT hr = D3DXLoadMeshFromX( pinnedFileName, static_cast<DWORD>( flags ), device->InternalPointer,
\r
133 &adjacencyBuffer, &materialBuffer, &instanceBuffer, &materialCount, &mesh );
\r
135 if( RECORD_D3D9( hr ).IsFailure )
\r
138 Mesh^ result = Mesh::FromPointer( mesh );
\r
140 result->SetAdjacency( Utilities::ReadRange<int>( adjacencyBuffer, mesh->GetNumFaces() * 3 ) );
\r
141 result->SetMaterials( ExtendedMaterial::FromBuffer( materialBuffer, materialCount ) );
\r
142 result->SetEffects( EffectInstance::FromBuffer( instanceBuffer, materialCount ) );
\r
144 materialBuffer->Release();
\r
145 instanceBuffer->Release();
\r
150 Mesh^ Mesh::FromXFile( SlimDX::Direct3D9::Device^ device, XFileData^ xfile, MeshFlags flags )
\r
152 ID3DXMesh* mesh = NULL;
\r
153 ID3DXSkinInfo* skin = NULL;
\r
154 ID3DXBuffer* adjacencyBuffer = NULL;
\r
155 ID3DXBuffer* materialBuffer = NULL;
\r
156 ID3DXBuffer* instanceBuffer = NULL;
\r
157 DWORD materialCount = 0;
\r
159 HRESULT hr = D3DXLoadSkinMeshFromXof( xfile->InternalPointer, static_cast<DWORD>( flags ), device->InternalPointer,
\r
160 &adjacencyBuffer, &materialBuffer, &instanceBuffer, &materialCount, &skin, &mesh );
\r
162 if( RECORD_D3D9( hr ).IsFailure )
\r
165 Mesh^ result = Mesh::FromPointer( mesh );
\r
167 result->SetAdjacency( Utilities::ReadRange<int>( adjacencyBuffer, mesh->GetNumFaces() * 3 ) );
\r
168 result->SetMaterials( ExtendedMaterial::FromBuffer( materialBuffer, materialCount ) );
\r
169 result->SetEffects( EffectInstance::FromBuffer( instanceBuffer, materialCount ) );
\r
171 materialBuffer->Release();
\r
172 instanceBuffer->Release();
\r
174 result->SkinInfo = SlimDX::Direct3D9::SkinInfo::FromPointer( skin );
\r
179 Result Mesh::ComputeTangentFrame( TangentOptions options )
\r
181 HRESULT hr = D3DXComputeTangentFrame( InternalPointer, static_cast<DWORD>( options ) );
\r
182 return RECORD_D3D9( hr );
\r
185 Mesh^ Mesh::CreateBox( SlimDX::Direct3D9::Device^ device, float width, float height, float depth )
\r
187 ID3DXMesh *result = NULL;
\r
188 ID3DXBuffer *adj = NULL;
\r
190 HRESULT hr = D3DXCreateBox( device->InternalPointer, width, height, depth, &result, &adj );
\r
192 if( RECORD_D3D9( hr ).IsFailure )
\r
195 Mesh^ mesh = Mesh::FromPointer( result );
\r
197 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );
\r
201 Mesh^ Mesh::CreateCylinder( SlimDX::Direct3D9::Device^ device, float radius1, float radius2, float length, int slices, int stacks )
\r
203 ID3DXMesh *result = NULL;
\r
204 ID3DXBuffer *adj = NULL;
\r
206 HRESULT hr = D3DXCreateCylinder( device->InternalPointer, radius1, radius2, length, slices, stacks, &result, &adj );
\r
208 if( RECORD_D3D9( hr ).IsFailure )
\r
211 Mesh^ mesh = Mesh::FromPointer( result );
\r
213 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );
\r
217 Mesh^ Mesh::CreateSphere( SlimDX::Direct3D9::Device^ device, float radius, int slices, int stacks )
\r
219 ID3DXMesh *result = NULL;
\r
220 ID3DXBuffer *adj = NULL;
\r
222 HRESULT hr = D3DXCreateSphere( device->InternalPointer, radius, slices, stacks, &result, &adj );
\r
224 if( RECORD_D3D9( hr ).IsFailure )
\r
227 Mesh^ mesh = Mesh::FromPointer( result );
\r
229 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );
\r
233 Mesh^ Mesh::CreateTeapot( SlimDX::Direct3D9::Device^ device )
\r
235 ID3DXMesh *result = NULL;
\r
236 ID3DXBuffer *adj = NULL;
\r
238 HRESULT hr = D3DXCreateTeapot( device->InternalPointer, &result, &adj );
\r
240 if( RECORD_D3D9( hr ).IsFailure )
\r
243 Mesh^ mesh = Mesh::FromPointer( result );
\r
245 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );
\r
249 Mesh^ Mesh::CreateTorus( SlimDX::Direct3D9::Device^ device, float innerRadius, float outerRadius, int sides, int rings )
\r
251 ID3DXMesh *result = NULL;
\r
252 ID3DXBuffer *adj = NULL;
\r
254 HRESULT hr = D3DXCreateTorus( device->InternalPointer, innerRadius, outerRadius, sides, rings, &result, &adj );
\r
256 if( RECORD_D3D9( hr ).IsFailure )
\r
259 Mesh^ mesh = Mesh::FromPointer( result );
\r
261 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );
\r
265 Mesh^ Mesh::CreateText( SlimDX::Direct3D9::Device^ device, Font^ font, String^ text, float deviation, float extrusion, [Out] array<GlyphMetricsFloat>^% glyphMetrics )
\r
267 ID3DXMesh *result = NULL;
\r
268 ID3DXBuffer *adj = NULL;
\r
270 glyphMetrics = gcnew array<GlyphMetricsFloat>( text->Length );
\r
272 pin_ptr<const wchar_t> pinnedText = PtrToStringChars( text );
\r
273 pin_ptr<GlyphMetricsFloat> pinnedMetrics = &glyphMetrics[0];
\r
275 HDC hdc = CreateCompatibleDC( NULL );
\r
279 throw gcnew OutOfMemoryException();
\r
281 newFont = static_cast<HFONT>( font->ToHfont().ToPointer() );
\r
282 oldFont = static_cast<HFONT>( SelectObject( hdc, newFont ) );
\r
284 HRESULT hr = D3DXCreateText( device->InternalPointer, hdc, reinterpret_cast<LPCWSTR>( pinnedText ),
\r
285 deviation, extrusion, &result, &adj, reinterpret_cast<LPGLYPHMETRICSFLOAT>( pinnedMetrics ) );
\r
287 SelectObject( hdc, oldFont );
\r
288 DeleteObject( newFont );
\r
291 if( RECORD_D3D9( hr ).IsFailure )
\r
293 glyphMetrics = nullptr;
\r
297 Mesh^ mesh = Mesh::FromPointer( result );
\r
299 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );
\r
303 Mesh^ Mesh::CreateText( SlimDX::Direct3D9::Device^ device, Font^ font, String^ text, float deviation, float extrusion )
\r
305 ID3DXMesh *result = NULL;
\r
306 ID3DXBuffer *adj = NULL;
\r
308 pin_ptr<const wchar_t> pinnedText = PtrToStringChars( text );
\r
310 HDC hdc = CreateCompatibleDC( NULL );
\r
314 throw gcnew OutOfMemoryException();
\r
316 newFont = static_cast<HFONT>( font->ToHfont().ToPointer() );
\r
317 oldFont = static_cast<HFONT>( SelectObject( hdc, newFont ) );
\r
319 HRESULT hr = D3DXCreateText( device->InternalPointer, hdc, reinterpret_cast<LPCWSTR>( pinnedText ),
\r
320 deviation, extrusion, &result, &adj, NULL );
\r
322 SelectObject( hdc, oldFont );
\r
323 DeleteObject( newFont );
\r
326 if( RECORD_D3D9( hr ).IsFailure )
\r
329 Mesh^ mesh = Mesh::FromPointer( result );
\r
331 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );
\r
335 DataStream^ Mesh::LockAttributeBuffer( LockFlags flags )
\r
337 DWORD *data = NULL;
\r
338 int faceCount = InternalPointer->GetNumFaces();
\r
340 HRESULT hr = InternalPointer->LockAttributeBuffer( static_cast<DWORD>( flags ), &data );
\r
342 if( RECORD_D3D9( hr ).IsFailure )
\r
345 bool readOnly = (flags & LockFlags::ReadOnly) == LockFlags::ReadOnly;
\r
346 return gcnew DataStream( data, faceCount * sizeof( DWORD ), true, !readOnly, false );
\r
349 Result Mesh::UnlockAttributeBuffer()
\r
351 HRESULT hr = InternalPointer->UnlockAttributeBuffer();
\r
352 return RECORD_D3D9( hr );
\r
355 Result Mesh::SetAttributeTable( array<AttributeRange>^ table )
\r
357 pin_ptr<AttributeRange> pinnedTable = &table[0];
\r
359 HRESULT hr = InternalPointer->SetAttributeTable( reinterpret_cast<const D3DXATTRIBUTERANGE*>( pinnedTable ), table->Length );
\r
360 return RECORD_D3D9( hr );
\r
363 Result Mesh::OptimizeInPlace( MeshOptimizeFlags flags, [Out] array<int>^% faceRemap, [Out] array<int>^% vertexRemap )
\r
365 ID3DXBuffer *buffer = NULL;
\r
366 DWORD *adjacencyIn = NULL;
\r
367 DWORD *adjacencyOutPtr = NULL;
\r
368 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );
\r
370 array<int>^ adjacency = GetAdjacency();
\r
371 pin_ptr<int> pinnedAdjIn;
\r
373 faceRemap = gcnew array<int>( FaceCount );
\r
374 pin_ptr<int> pinnedFR = &faceRemap[0];
\r
376 if( adjacency != nullptr )
\r
378 pinnedAdjIn = &adjacency[0];
\r
379 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );
\r
380 adjacencyOutPtr = &adjacencyOut[0];
\r
383 HRESULT hr = InternalPointer->OptimizeInplace( static_cast<DWORD>( flags ), adjacencyIn,
\r
384 adjacencyOutPtr, reinterpret_cast<DWORD*>( pinnedFR ), &buffer );
\r
386 if( RECORD_D3D9( hr ).IsFailure )
\r
388 faceRemap = nullptr;
\r
389 vertexRemap = nullptr;
\r
390 SetAdjacency( NULL );
\r
394 vertexRemap = Utilities::ReadRange<int>( buffer, VertexCount );
\r
395 if( adjacencyOutPtr != NULL )
\r
396 SetAdjacency( &adjacencyOut[0] );
\r
398 SetAdjacency( NULL );
\r
401 return Result::Last;
\r
404 Result Mesh::OptimizeInPlace( MeshOptimizeFlags flags )
\r
406 DWORD *adjacencyIn = NULL;
\r
407 DWORD *adjacencyOutPtr = NULL;
\r
408 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );
\r
410 array<int>^ adjacency = GetAdjacency();
\r
411 pin_ptr<int> pinnedAdjIn;
\r
412 if( adjacency != nullptr )
\r
414 pinnedAdjIn = &adjacency[0];
\r
415 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );
\r
416 adjacencyOutPtr = &adjacencyOut[0];
\r
419 HRESULT hr = InternalPointer->OptimizeInplace( static_cast<DWORD>( flags ), adjacencyIn,
\r
420 adjacencyOutPtr, NULL, NULL );
\r
424 SetAdjacency( NULL );
\r
427 if( adjacencyOutPtr != NULL )
\r
428 SetAdjacency( &adjacencyOut[0] );
\r
430 SetAdjacency( NULL );
\r
433 return Result::Last;
\r
436 Mesh^ Mesh::Optimize( MeshOptimizeFlags flags, [Out] array<int>^% faceRemap, [Out] array<int>^% vertexRemap )
\r
438 ID3DXMesh *result = NULL;
\r
439 ID3DXBuffer *buffer = NULL;
\r
440 DWORD *adjacencyIn = NULL;
\r
441 DWORD *adjacencyOutPtr = NULL;
\r
442 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );
\r
444 array<int>^ adjacency = GetAdjacency();
\r
445 pin_ptr<int> pinnedAdjIn;
\r
447 faceRemap = gcnew array<int>( FaceCount );
\r
448 pin_ptr<int> pinnedFR = &faceRemap[0];
\r
450 if( adjacency != nullptr )
\r
452 pinnedAdjIn = &adjacency[0];
\r
453 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );
\r
454 adjacencyOutPtr = &adjacencyOut[0];
\r
457 HRESULT hr = InternalPointer->Optimize( static_cast<DWORD>( flags ), adjacencyIn,
\r
458 adjacencyOutPtr, reinterpret_cast<DWORD*>( pinnedFR ), &buffer, &result );
\r
460 if( RECORD_D3D9( hr ).IsFailure )
\r
462 faceRemap = nullptr;
\r
463 vertexRemap = nullptr;
\r
467 Mesh^ mesh = Mesh::FromPointer( result );
\r
469 vertexRemap = Utilities::ReadRange<int>( buffer, VertexCount );
\r
471 if( adjacencyOutPtr != NULL )
\r
472 mesh->SetAdjacency( &adjacencyOut[0] );
\r
477 Mesh^ Mesh::Optimize( MeshOptimizeFlags flags )
\r
479 ID3DXMesh *result = NULL;
\r
480 DWORD *adjacencyIn = NULL;
\r
481 DWORD *adjacencyOutPtr = NULL;
\r
482 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );
\r
484 array<int>^ adjacency = GetAdjacency();
\r
485 pin_ptr<int> pinnedAdjIn;
\r
487 if( adjacency != nullptr )
\r
489 pinnedAdjIn = &adjacency[0];
\r
490 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );
\r
491 adjacencyOutPtr = &adjacencyOut[0];
\r
494 HRESULT hr = InternalPointer->Optimize( static_cast<DWORD>( flags ), adjacencyIn,
\r
495 adjacencyOutPtr, NULL, NULL, &result );
\r
497 if( RECORD_D3D9( hr ).IsFailure )
\r
500 Mesh^ mesh = Mesh::FromPointer( result );
\r
502 if( adjacencyOutPtr != NULL )
\r
503 mesh->SetAdjacency( &adjacencyOut[0] );
\r
508 Mesh^ Mesh::Clean( CleanType type, [Out] String^% errorsAndWarnings )
\r
510 ID3DXMesh *result = NULL;
\r
511 ID3DXBuffer *errors = NULL;
\r
512 DWORD *adjacencyIn = NULL;
\r
513 DWORD *adjacencyOutPtr = NULL;
\r
514 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );
\r
516 array<int>^ adjacency = GetAdjacency();
\r
517 pin_ptr<int> pinnedAdjIn;
\r
519 if( adjacency != nullptr )
\r
521 pinnedAdjIn = &adjacency[0];
\r
522 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );
\r
523 adjacencyOutPtr = &adjacencyOut[0];
\r
526 HRESULT hr = D3DXCleanMesh( static_cast<D3DXCLEANTYPE>( type ), InternalPointer,
\r
527 adjacencyIn, &result, adjacencyOutPtr, &errors );
\r
529 if( RECORD_D3D9( hr ).IsFailure )
\r
531 errorsAndWarnings = nullptr;
\r
535 errorsAndWarnings = Utilities::BufferToString( errors );
\r
537 Mesh^ mesh = Mesh::FromPointer( result );
\r
539 if( adjacencyOutPtr != NULL )
\r
540 mesh->SetAdjacency( &adjacencyOut[0] );
\r
545 Mesh^ Mesh::Clean( CleanType type )
\r
547 ID3DXMesh *result = NULL;
\r
548 DWORD *adjacencyIn = NULL;
\r
549 DWORD *adjacencyOutPtr = NULL;
\r
550 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );
\r
552 array<int>^ adjacency = GetAdjacency();
\r
553 pin_ptr<int> pinnedAdjIn;
\r
555 if( adjacency != nullptr )
\r
557 pinnedAdjIn = &adjacency[0];
\r
558 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );
\r
559 adjacencyOutPtr = &adjacencyOut[0];
\r
562 HRESULT hr = D3DXCleanMesh( static_cast<D3DXCLEANTYPE>( type ), InternalPointer,
\r
563 &adjacencyIn[0], &result, adjacencyOutPtr, NULL );
\r
565 if( RECORD_D3D9( hr ).IsFailure )
\r
568 Mesh^ mesh = Mesh::FromPointer( result );
\r
570 if( adjacencyOutPtr != NULL )
\r
571 mesh->SetAdjacency( &adjacencyOut[0] );
\r
576 void Mesh::GenerateAdjacency( float epsilon )
\r
578 array<int>^ adj = BaseMesh::GenerateAdjacency( epsilon );
\r
579 SetAdjacency( adj );
\r
582 String^ Mesh::Validate()
\r
584 ID3DXBuffer *errorBuffer = NULL;
\r
585 DWORD *adjacencyIn = NULL;
\r
586 pin_ptr<int> pinnedAdj;
\r
587 String^ errors = nullptr;
\r
589 array<int>^ adjacency = GetAdjacency();
\r
590 if( adjacency != nullptr )
\r
592 pinnedAdj = &adjacency[0];
\r
593 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );
\r
596 D3DXValidMesh( InternalPointer, adjacencyIn, &errorBuffer );
\r
597 errors = Utilities::BufferToString( errorBuffer );
\r
602 void Mesh::SetAdjacency( DWORD *adj )
\r
605 adjacency = nullptr;
\r
608 adjacency = gcnew array<int>( FaceCount * 3 );
\r
609 for( int i = 0; i < FaceCount * 3; i++ )
\r
610 adjacency[i] = adj[i];
\r
614 Result Mesh::ComputeNormals()
\r
616 DWORD *adjacencyIn = NULL;
\r
617 pin_ptr<int> pinnedAdj;
\r
619 array<int>^ adjacency = GetAdjacency();
\r
620 if( adjacency != nullptr )
\r
622 pinnedAdj = &adjacency[0];
\r
623 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );
\r
626 HRESULT hr = D3DXComputeNormals( InternalPointer, adjacencyIn );
\r
627 return RECORD_D3D9( hr );
\r
630 Result Mesh::ComputeTangent( int textureStage, int tangentIndex, int binormalIndex, bool wrap )
\r
632 array<int>^ adjacency = GetAdjacency();
\r
633 DWORD *adjacencyIn = NULL;
\r
634 pin_ptr<int> pinnedAdj;
\r
636 if( adjacency != nullptr )
\r
638 pinnedAdj = &adjacency[0];
\r
639 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );
\r
642 HRESULT hr = D3DXComputeTangent( InternalPointer, textureStage, tangentIndex, binormalIndex, wrap, adjacencyIn );
\r
643 return RECORD_D3D9( hr );
\r
646 Mesh^ Mesh::ComputeTangentFrame( int textureInSemantic, int textureInIndex, int partialOutSemanticU,
\r
647 int partialOutIndexU, int partialOutSemanticV, int partialOutIndexV, int normalOutSemantic,
\r
648 int normalOutIndex, TangentOptions options, float partialEdgeThreshold,
\r
649 float singularPointThreshold, float normalEdgeThreshold, [Out] array<int>^% vertexMapping )
\r
651 ID3DXMesh *result = NULL;
\r
652 ID3DXBuffer *vertex = NULL;
\r
654 array<int>^ adjacency = GetAdjacency();
\r
655 DWORD *adjacencyIn = NULL;
\r
656 pin_ptr<int> pinnedAdj;
\r
658 if( adjacency != nullptr )
\r
660 pinnedAdj = &adjacency[0];
\r
661 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );
\r
664 HRESULT hr = D3DXComputeTangentFrameEx( InternalPointer, textureInSemantic, textureInIndex,
\r
665 partialOutSemanticU, partialOutIndexU, partialOutSemanticV, partialOutIndexV, normalOutSemantic,
\r
666 normalOutIndex, static_cast<DWORD>( options ), adjacencyIn,
\r
667 partialEdgeThreshold, singularPointThreshold, normalEdgeThreshold, &result, &vertex );
\r
669 if( RECORD_D3D9( hr ).IsFailure )
\r
671 vertexMapping = nullptr;
\r
675 vertexMapping = Utilities::ReadRange<int>( vertex, result->GetNumVertices() );
\r
677 if( (options & TangentOptions::GenerateInPlace) == TangentOptions::GenerateInPlace )
\r
680 return Mesh::FromPointer( result );
\r
683 Mesh^ Mesh::ComputeTangentFrame( int textureInSemantic, int textureInIndex, int partialOutSemanticU,
\r
684 int partialOutIndexU, int partialOutSemanticV, int partialOutIndexV, int normalOutSemantic,
\r
685 int normalOutIndex, TangentOptions options, float partialEdgeThreshold,
\r
686 float singularPointThreshold, float normalEdgeThreshold )
\r
688 ID3DXMesh *result = NULL;
\r
690 array<int>^ adjacency = GetAdjacency();
\r
691 DWORD *adjacencyIn = NULL;
\r
692 pin_ptr<int> pinnedAdj;
\r
694 if( adjacency != nullptr )
\r
696 pinnedAdj = &adjacency[0];
\r
697 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );
\r
700 HRESULT hr = D3DXComputeTangentFrameEx( InternalPointer, textureInSemantic, textureInIndex,
\r
701 partialOutSemanticU, partialOutIndexU, partialOutSemanticV, partialOutIndexV, normalOutSemantic,
\r
702 normalOutIndex, static_cast<DWORD>( options ), adjacencyIn,
\r
703 partialEdgeThreshold, singularPointThreshold, normalEdgeThreshold, &result, NULL );
\r
705 if( RECORD_D3D9( hr ).IsFailure )
\r
708 if( (options & TangentOptions::GenerateInPlace) == TangentOptions::GenerateInPlace )
\r
711 return Mesh::FromPointer( result );
\r
714 Mesh^ Mesh::Concatenate( SlimDX::Direct3D9::Device^ device, array<Mesh^>^ meshes, MeshFlags options, array<Matrix>^ geometryTransforms,
\r
715 array<Matrix>^ textureTransforms, array<VertexElement>^ vertexDeclaration )
\r
717 ID3DXMesh *result = NULL;
\r
718 D3DXMATRIX *geoXForms = NULL;
\r
719 D3DXMATRIX *textureXForms = NULL;
\r
720 D3DVERTEXELEMENT9 *decl = NULL;
\r
722 pin_ptr<Matrix> pinnedGeo = nullptr;
\r
723 pin_ptr<Matrix> pinnedTexture = nullptr;
\r
724 pin_ptr<VertexElement> pinnedDecl = nullptr;
\r
726 stack_array<ID3DXMesh*> input = stackalloc( ID3DXMesh*, meshes->Length );
\r
727 for( int i = 0; i < meshes->Length; i++ )
\r
728 input[i] = meshes[i]->InternalPointer;
\r
730 if( geometryTransforms != nullptr )
\r
732 pinnedGeo = &geometryTransforms[0];
\r
733 geoXForms = reinterpret_cast<D3DXMATRIX*>( pinnedGeo );
\r
736 if( textureTransforms != nullptr )
\r
738 pinnedTexture = &textureTransforms[0];
\r
739 textureXForms = reinterpret_cast<D3DXMATRIX*>( pinnedTexture );
\r
742 if( vertexDeclaration != nullptr )
\r
744 pinnedDecl = &vertexDeclaration[0];
\r
745 decl = reinterpret_cast<D3DVERTEXELEMENT9*>( pinnedDecl );
\r
748 HRESULT hr = D3DXConcatenateMeshes( &input[0], meshes->Length, static_cast<DWORD>( options ), geoXForms,
\r
749 textureXForms, decl, device->InternalPointer, &result );
\r
751 if( RECORD_D3D9( hr ).IsFailure )
\r
754 return Mesh::FromPointer( result );
\r
757 Mesh^ Mesh::Concatenate( SlimDX::Direct3D9::Device^ device, array<Mesh^>^ meshes, MeshFlags options, array<Matrix>^ geometryTransforms,
\r
758 array<Matrix>^ textureTransforms )
\r
760 ID3DXMesh *result = NULL;
\r
761 D3DXMATRIX *geoXForms = NULL;
\r
762 D3DXMATRIX *textureXForms = NULL;
\r
764 pin_ptr<Matrix> pinnedGeo = nullptr;
\r
765 pin_ptr<Matrix> pinnedTexture = nullptr;
\r
767 stack_array<ID3DXMesh*> input = stackalloc( ID3DXMesh*, meshes->Length );
\r
768 for( int i = 0; i < meshes->Length; i++ )
\r
769 input[i] = meshes[i]->InternalPointer;
\r
771 if( geometryTransforms != nullptr )
\r
773 pinnedGeo = &geometryTransforms[0];
\r
774 geoXForms = reinterpret_cast<D3DXMATRIX*>( pinnedGeo );
\r
777 if( textureTransforms != nullptr )
\r
779 pinnedTexture = &textureTransforms[0];
\r
780 textureXForms = reinterpret_cast<D3DXMATRIX*>( pinnedTexture );
\r
783 HRESULT hr = D3DXConcatenateMeshes( &input[0], meshes->Length, static_cast<DWORD>( options ), geoXForms,
\r
784 textureXForms, NULL, device->InternalPointer, &result );
\r
786 if( RECORD_D3D9( hr ).IsFailure )
\r
789 return Mesh::FromPointer( result );
\r
792 Mesh^ Mesh::Concatenate( SlimDX::Direct3D9::Device^ device, array<Mesh^>^ meshes, MeshFlags options )
\r
794 ID3DXMesh *result = NULL;
\r
796 stack_array<ID3DXMesh*> input = stackalloc( ID3DXMesh*, meshes->Length );
\r
797 for( int i = 0; i < meshes->Length; i++ )
\r
798 input[i] = meshes[i]->InternalPointer;
\r
800 HRESULT hr = D3DXConcatenateMeshes( &input[0], meshes->Length, static_cast<DWORD>( options ), NULL,
\r
801 NULL, NULL, device->InternalPointer, &result );
\r
803 if( RECORD_D3D9( hr ).IsFailure )
\r
806 return Mesh::FromPointer( result );
\r
809 Result Mesh::ToXFile( Mesh^ mesh, String^ fileName, XFileFormat format, CharSet charSet )
\r
811 pin_ptr<const wchar_t> pinnedName = PtrToStringChars( fileName );
\r
813 array<int>^ adjacency = mesh->GetAdjacency();
\r
814 array<ExtendedMaterial>^ materials = mesh->GetMaterials();
\r
815 array<EffectInstance>^ effects = mesh->GetEffects();
\r
817 DWORD *adjacencyIn = NULL;
\r
818 D3DXMATERIAL *materialPtr = NULL;
\r
819 D3DXEFFECTINSTANCE *effectPtr = NULL;
\r
820 stack_array<D3DXMATERIAL> nativeMaterials;
\r
821 stack_array<D3DXEFFECTINSTANCE> nativeEffects;
\r
822 pin_ptr<int> pinnedAdj;
\r
825 if( adjacency != nullptr )
\r
827 pinnedAdj = &adjacency[0];
\r
828 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );
\r
831 if( materials != nullptr )
\r
833 length = materials->Length;
\r
834 nativeMaterials = stack_array<D3DXMATERIAL>( length );
\r
835 for( int i = 0; i < length; i++ )
\r
836 nativeMaterials[i] = ExtendedMaterial::ToUnmanaged( materials[i] );
\r
838 materialPtr = &nativeMaterials[0];
\r
841 if( effects != nullptr )
\r
843 nativeEffects = stack_array<D3DXEFFECTINSTANCE>( effects->Length );
\r
844 for( int i = 0; i < effects->Length; i++ )
\r
845 nativeEffects[i] = EffectInstance::ToUnmanaged( effects[i] );
\r
847 effectPtr = &nativeEffects[0];
\r
850 DWORD f = static_cast<DWORD>( format );
\r
851 if( charSet == CharSet::Unicode )
\r
852 f |= D3DXF_FILESAVE_TOWFILE;
\r
854 f |= D3DXF_FILESAVE_TOFILE;
\r
856 HRESULT hr = D3DXSaveMeshToX( reinterpret_cast<LPCWSTR>( pinnedName ), mesh->InternalPointer,
\r
857 adjacencyIn, materialPtr, effectPtr, length, f );
\r
859 if( materials != nullptr )
\r
861 for( int i = 0; i < length; i++ )
\r
862 Utilities::FreeNativeString( nativeMaterials[i].pTextureFilename );
\r
865 if( effects != nullptr )
\r
867 for( int i = 0; i < effects->Length; i++ )
\r
869 for( UINT j = 0; j < nativeEffects[i].NumDefaults; j++ )
\r
870 Utilities::FreeNativeString( nativeEffects[i].pDefaults[j].pParamName );
\r
872 delete[] nativeEffects[i].pDefaults;
\r
876 return RECORD_D3D9( hr );
\r
879 Result Mesh::ToXFile( Mesh^ mesh, String^ fileName, XFileFormat format )
\r
881 return ToXFile( mesh, fileName, format, CharSet::Auto );
\r
884 Mesh^ Mesh::Simplify( Mesh^ mesh, array<AttributeWeights>^ attributeWeights,
\r
885 array<float>^ vertexWeights, int minimumValue, MeshSimplification options )
\r
887 ID3DXMesh *result = NULL;
\r
889 DWORD *adjacencyIn = NULL;
\r
890 pin_ptr<int> pinnedAdj;
\r
891 array<int>^ adjacency = mesh->GetAdjacency();
\r
893 if( adjacency != nullptr )
\r
895 pinnedAdj = &adjacency[0];
\r
896 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );
\r
899 pin_ptr<float> pinnedVW = &vertexWeights[0];
\r
900 pin_ptr<AttributeWeights> pinnedAW = &attributeWeights[0];
\r
902 HRESULT hr = D3DXSimplifyMesh( mesh->InternalPointer, adjacencyIn,
\r
903 reinterpret_cast<const D3DXATTRIBUTEWEIGHTS*>( pinnedAW ), reinterpret_cast<const FLOAT*>( pinnedVW ),
\r
904 minimumValue, static_cast<DWORD>( options ), &result );
\r
906 if( RECORD_D3D9( hr ).IsFailure )
\r
909 return Mesh::FromPointer( result );
\r
912 Mesh^ Mesh::Simplify( Mesh^ mesh, array<AttributeWeights>^ attributeWeights,
\r
913 int minimumValue, MeshSimplification options )
\r
915 ID3DXMesh *result = NULL;
\r
917 DWORD *adjacencyIn = NULL;
\r
918 pin_ptr<int> pinnedAdj;
\r
919 array<int>^ adjacency = mesh->GetAdjacency();
\r
921 if( adjacency != nullptr )
\r
923 pinnedAdj = &adjacency[0];
\r
924 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );
\r
927 pin_ptr<AttributeWeights> pinnedAW = &attributeWeights[0];
\r
929 HRESULT hr = D3DXSimplifyMesh( mesh->InternalPointer, adjacencyIn,
\r
930 reinterpret_cast<const D3DXATTRIBUTEWEIGHTS*>( pinnedAW ), NULL,
\r
931 minimumValue, static_cast<DWORD>( options ), &result );
\r
933 if( RECORD_D3D9( hr ).IsFailure )
\r
936 return Mesh::FromPointer( result );
\r
939 Mesh^ Mesh::Simplify( Mesh^ mesh, int minimumValue, MeshSimplification options )
\r
941 ID3DXMesh *result = NULL;
\r
943 DWORD *adjacencyIn = NULL;
\r
944 array<int>^ adjacency = mesh->GetAdjacency();
\r
945 pin_ptr<int> pinnedAdj;
\r
947 if( adjacency != nullptr )
\r
949 pinnedAdj = &adjacency[0];
\r
950 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );
\r
953 HRESULT hr = D3DXSimplifyMesh( mesh->InternalPointer, adjacencyIn,
\r
954 NULL, NULL, minimumValue, static_cast<DWORD>( options ), &result );
\r
956 if( RECORD_D3D9( hr ).IsFailure )
\r
959 return Mesh::FromPointer( result );
\r
962 Mesh^ Mesh::TessellateNPatches( Mesh^ mesh, float segmentCount, bool quadraticInterpolation )
\r
964 ID3DXMesh *result = NULL;
\r
965 ID3DXBuffer *adjacencyOut = NULL;
\r
967 DWORD *adjacencyIn = NULL;
\r
968 array<int>^ adjacency = mesh->GetAdjacency();
\r
969 pin_ptr<int> pinnedAdj;
\r
971 if( adjacency != nullptr )
\r
973 pinnedAdj = &adjacency[0];
\r
974 adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );
\r
977 HRESULT hr = D3DXTessellateNPatches( mesh->InternalPointer, adjacencyIn, segmentCount,
\r
978 quadraticInterpolation, &result, &adjacencyOut );
\r
980 if( RECORD_D3D9( hr ).IsFailure )
\r
983 Mesh^ newMesh = Mesh::FromPointer( result );
\r
984 newMesh->SetAdjacency( Utilities::ReadRange<int>( adjacencyOut, result->GetNumFaces() * 3 ) );
\r
989 Result Mesh::TessellateRectanglePatch( SlimDX::Direct3D9::VertexBuffer^ vertexBuffer, array<float>^ segmentCounts,
\r
990 array<VertexElement>^ vertexDeclaration, RectanglePatchInfo rectanglePatchInfo )
\r
992 pin_ptr<float> pinnedSegments = &segmentCounts[0];
\r
993 pin_ptr<VertexElement> pinnedDeclaration = &vertexDeclaration[0];
\r
995 HRESULT hr = D3DXTessellateRectPatch( vertexBuffer->InternalPointer, reinterpret_cast<const FLOAT*>( pinnedSegments ),
\r
996 reinterpret_cast<const D3DVERTEXELEMENT9*>( pinnedDeclaration ), reinterpret_cast<const D3DRECTPATCH_INFO*>( &rectanglePatchInfo ),
\r
999 return RECORD_D3D9( hr );
\r
1002 Result Mesh::TessellateTrianglePatch( SlimDX::Direct3D9::VertexBuffer^ vertexBuffer, array<float>^ segmentCounts,
\r
1003 array<VertexElement>^ vertexDeclaration, TrianglePatchInfo trianglePatchInfo )
\r
1005 pin_ptr<float> pinnedSegments = &segmentCounts[0];
\r
1006 pin_ptr<VertexElement> pinnedDeclaration = &vertexDeclaration[0];
\r
1008 HRESULT hr = D3DXTessellateTriPatch( vertexBuffer->InternalPointer, reinterpret_cast<const FLOAT*>( pinnedSegments ),
\r
1009 reinterpret_cast<const D3DVERTEXELEMENT9*>( pinnedDeclaration ), reinterpret_cast<const D3DTRIPATCH_INFO*>( &trianglePatchInfo ),
\r
1010 InternalPointer );
\r
1012 return RECORD_D3D9( hr );
\r
1015 Result Mesh::WeldVertices( WeldFlags flags, WeldEpsilons epsilons, [Out] array<int>^% faceRemap, [Out] array<int>^% vertexRemap )
\r
1017 ID3DXBuffer *buffer = NULL;
\r
1018 DWORD *adjIn = NULL;
\r
1019 DWORD *adjOut = NULL;
\r
1020 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );
\r
1022 array<int>^ adjacency = GetAdjacency();
\r
1023 pin_ptr<int> pinnedAdjIn;
\r
1025 faceRemap = gcnew array<int>( FaceCount );
\r
1026 pin_ptr<int> pinnedFR = &faceRemap[0];
\r
1028 if( adjacency != nullptr )
\r
1030 pinnedAdjIn = &adjacency[0];
\r
1031 adjIn = reinterpret_cast<DWORD*>( pinnedAdjIn );
\r
1032 adjOut = &adjacencyOut[0];
\r
1035 HRESULT hr = D3DXWeldVertices( InternalPointer, static_cast<DWORD>( flags ),
\r
1036 reinterpret_cast<const D3DXWELDEPSILONS*>( &epsilons ), adjIn, adjOut,
\r
1037 reinterpret_cast<DWORD*>( pinnedFR ), &buffer );
\r
1039 if( RECORD_D3D9( hr ).IsFailure )
\r
1041 faceRemap = nullptr;
\r
1042 vertexRemap = nullptr;
\r
1043 return Result::Last;
\r
1046 vertexRemap = Utilities::ReadRange<int>( buffer, VertexCount );
\r
1048 if( adjOut != NULL )
\r
1049 SetAdjacency( &adjacencyOut[0] );
\r
1051 return Result::Last;
\r
1054 Result Mesh::WeldVertices( WeldFlags flags, [Out] array<int>^% faceRemap, [Out] array<int>^% vertexRemap )
\r
1056 ID3DXBuffer *buffer = NULL;
\r
1057 DWORD *adjIn = NULL;
\r
1058 DWORD *adjOut = NULL;
\r
1059 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );
\r
1061 array<int>^ adjacency = GetAdjacency();
\r
1062 pin_ptr<int> pinnedAdjIn;
\r
1064 faceRemap = gcnew array<int>( FaceCount );
\r
1065 pin_ptr<int> pinnedFR = &faceRemap[0];
\r
1067 if( adjacency != nullptr )
\r
1069 pinnedAdjIn = &adjacency[0];
\r
1070 adjIn = reinterpret_cast<DWORD*>( pinnedAdjIn );
\r
1071 adjOut = &adjacencyOut[0];
\r
1074 HRESULT hr = D3DXWeldVertices( InternalPointer, static_cast<DWORD>( flags ), NULL, adjIn, adjOut,
\r
1075 reinterpret_cast<DWORD*>( pinnedFR ), &buffer );
\r
1077 if( RECORD_D3D9( hr ).IsFailure )
\r
1079 faceRemap = nullptr;
\r
1080 vertexRemap = nullptr;
\r
1081 return Result::Last;
\r
1084 vertexRemap = Utilities::ReadRange<int>( buffer, VertexCount );
\r
1086 if( adjOut != NULL )
\r
1087 SetAdjacency( &adjacencyOut[0] );
\r
1089 return Result::Last;
\r
1092 Result Mesh::WeldVertices( WeldFlags flags, WeldEpsilons epsilons )
\r
1094 DWORD *adjIn = NULL;
\r
1095 DWORD *adjOut = NULL;
\r
1096 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );
\r
1098 array<int>^ adjacency = GetAdjacency();
\r
1099 pin_ptr<int> pinnedAdjIn;
\r
1101 if( adjacency != nullptr )
\r
1103 pinnedAdjIn = &adjacency[0];
\r
1104 adjIn = reinterpret_cast<DWORD*>( pinnedAdjIn );
\r
1105 adjOut = &adjacencyOut[0];
\r
1108 HRESULT hr = D3DXWeldVertices( InternalPointer, static_cast<DWORD>( flags ),
\r
1109 reinterpret_cast<const D3DXWELDEPSILONS*>( &epsilons ), adjIn, adjOut, NULL, NULL );
\r
1111 if( RECORD_D3D9( hr ).IsFailure )
\r
1112 return Result::Last;
\r
1114 if( adjOut != NULL )
\r
1115 SetAdjacency( &adjacencyOut[0] );
\r
1117 return Result::Last;
\r
1120 Result Mesh::WeldVertices( WeldFlags flags )
\r
1122 DWORD *adjIn = NULL;
\r
1123 DWORD *adjOut = NULL;
\r
1124 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );
\r
1126 array<int>^ adjacency = GetAdjacency();
\r
1127 pin_ptr<int> pinnedAdjIn;
\r
1129 if( adjacency != nullptr )
\r
1131 pinnedAdjIn = &adjacency[0];
\r
1132 adjIn = reinterpret_cast<DWORD*>( pinnedAdjIn );
\r
1133 adjOut = &adjacencyOut[0];
\r
1136 HRESULT hr = D3DXWeldVertices( InternalPointer, static_cast<DWORD>( flags ), NULL, adjIn, adjOut, NULL, NULL );
\r
1138 if( RECORD_D3D9( hr ).IsFailure )
\r
1139 return Result::Last;
\r
1141 if( adjOut != NULL )
\r
1142 SetAdjacency( &adjacencyOut[0] );
\r
1144 return Result::Last;
\r