OSDN Git Service

DTXMania089リリースに際してのtag付け。
[dtxmania/dtxmania.git] / 110401(DTXMania089) / SlimDXc_Jun2010(VC++2008) / source / direct3d9 / Mesh.cpp
1 #include "stdafx.h"\r
2 /*\r
3 * Copyright (c) 2007-2010 SlimDX Group\r
4\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
11\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
14\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
21 * THE SOFTWARE.\r
22 */\r
23 #include <d3d9.h>\r
24 #include <d3dx9.h>\r
25 #include <vcclr.h>\r
26 \r
27 #include "../stack_array.h"\r
28 #include "../ComObject.h"\r
29 #include "../Utilities.h"\r
30 #include "../DataStream.h"\r
31 \r
32 #include "Direct3D9Exception.h"\r
33 \r
34 #include "Device.h"\r
35 #include "Texture.h"\r
36 #include "IndexBuffer.h"\r
37 #include "VertexBuffer.h"\r
38 #include "Mesh.h"\r
39 #include "SkinInfo.h"\r
40 \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
45 \r
46 namespace SlimDX\r
47 {\r
48 namespace Direct3D9\r
49 {\r
50         Mesh::Mesh( SlimDX::Direct3D9::Device^ device, int numFaces, int numVertices, MeshFlags options, array<VertexElement>^ vertexDeclaration )\r
51         {\r
52                 ID3DXMesh* mesh = NULL;\r
53                 pin_ptr<VertexElement> pinnedDecl = &vertexDeclaration[0];\r
54 \r
55                 HRESULT hr = D3DXCreateMesh( numFaces, numVertices, static_cast<DWORD>( options ),\r
56                         reinterpret_cast<D3DVERTEXELEMENT9*>( pinnedDecl ), device->InternalPointer, &mesh );\r
57 \r
58                 if( RECORD_D3D9( hr ).IsFailure )\r
59                         throw gcnew Direct3D9Exception( Result::Last );\r
60 \r
61                 Construct(mesh);\r
62         }\r
63 \r
64         Mesh::Mesh( SlimDX::Direct3D9::Device^ device, int numFaces, int numVertices, MeshFlags options, SlimDX::Direct3D9::VertexFormat fvf )\r
65         {\r
66                 ID3DXMesh* mesh = NULL;\r
67 \r
68                 HRESULT hr = D3DXCreateMeshFVF( numFaces, numVertices, static_cast<DWORD>( options ), \r
69                         static_cast<DWORD>( fvf ), device->InternalPointer, &mesh );\r
70 \r
71                 if( RECORD_D3D9( hr ).IsFailure )\r
72                         throw gcnew Direct3D9Exception( Result::Last );\r
73 \r
74                 Construct(mesh);\r
75         }\r
76 \r
77         Mesh^ Mesh::FromMemory_Internal( SlimDX::Direct3D9::Device^ device, const void* memory, DWORD size, MeshFlags flags )\r
78         {\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
84                 \r
85                 HRESULT hr = D3DXLoadMeshFromXInMemory( memory, size, static_cast<DWORD>( flags ), device->InternalPointer,\r
86                         &adjacencyBuffer, &materialBuffer, &instanceBuffer, &materialCount, &mesh );\r
87                 \r
88                 if( RECORD_D3D9( hr ).IsFailure )\r
89                         return nullptr;\r
90 \r
91                 Mesh^ result = Mesh::FromPointer( mesh );\r
92 \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
96 \r
97                 materialBuffer->Release();\r
98                 instanceBuffer->Release();\r
99 \r
100                 return result;\r
101         }\r
102 \r
103         Mesh^ Mesh::FromMemory( SlimDX::Direct3D9::Device^ device, array<Byte>^ memory, MeshFlags flags )\r
104         {\r
105                 pin_ptr<unsigned char> pinnedMemory = &memory[0];\r
106                 return Mesh::FromMemory_Internal( device, pinnedMemory, static_cast<DWORD>( memory->Length ), flags );\r
107         }\r
108 \r
109         Mesh^ Mesh::FromStream( SlimDX::Direct3D9::Device^ device, Stream^ stream, MeshFlags flags )\r
110         {\r
111                 DataStream^ ds = nullptr;\r
112                 array<Byte>^ data = Utilities::ReadStream( stream, &ds );\r
113 \r
114                 if( data == nullptr )\r
115                 {\r
116                         DWORD size = static_cast<DWORD>( ds->RemainingLength );\r
117                         return Mesh::FromMemory_Internal( device, ds->SeekToEnd(), size, flags );\r
118                 }\r
119 \r
120                 return Mesh::FromMemory( device, data, flags );\r
121         }\r
122 \r
123         Mesh^ Mesh::FromFile( SlimDX::Direct3D9::Device^ device, String^ fileName, MeshFlags flags )\r
124         {\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
131                 \r
132                 HRESULT hr = D3DXLoadMeshFromX( pinnedFileName, static_cast<DWORD>( flags ), device->InternalPointer,\r
133                         &adjacencyBuffer, &materialBuffer, &instanceBuffer, &materialCount, &mesh );\r
134                 \r
135                 if( RECORD_D3D9( hr ).IsFailure )\r
136                         return nullptr;\r
137 \r
138                 Mesh^ result = Mesh::FromPointer( mesh );\r
139 \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
143 \r
144                 materialBuffer->Release();\r
145                 instanceBuffer->Release();\r
146 \r
147                 return result;\r
148         }\r
149 \r
150         Mesh^ Mesh::FromXFile( SlimDX::Direct3D9::Device^ device, XFileData^ xfile, MeshFlags flags )\r
151         {\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
158                 \r
159                 HRESULT hr = D3DXLoadSkinMeshFromXof( xfile->InternalPointer, static_cast<DWORD>( flags ), device->InternalPointer,\r
160                         &adjacencyBuffer, &materialBuffer, &instanceBuffer, &materialCount, &skin, &mesh );\r
161                 \r
162                 if( RECORD_D3D9( hr ).IsFailure )\r
163                         return nullptr;\r
164 \r
165                 Mesh^ result = Mesh::FromPointer( mesh );\r
166 \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
170 \r
171                 materialBuffer->Release();\r
172                 instanceBuffer->Release();\r
173 \r
174                 result->SkinInfo = SlimDX::Direct3D9::SkinInfo::FromPointer( skin );\r
175 \r
176                 return result;\r
177         }\r
178 \r
179         Result Mesh::ComputeTangentFrame( TangentOptions options )\r
180         {\r
181                 HRESULT hr = D3DXComputeTangentFrame( InternalPointer, static_cast<DWORD>( options ) );\r
182                 return RECORD_D3D9( hr );\r
183         }\r
184 \r
185         Mesh^ Mesh::CreateBox( SlimDX::Direct3D9::Device^ device, float width, float height, float depth )\r
186         {\r
187                 ID3DXMesh *result = NULL;\r
188                 ID3DXBuffer *adj = NULL;\r
189 \r
190                 HRESULT hr = D3DXCreateBox( device->InternalPointer, width, height, depth, &result, &adj );\r
191                 \r
192                 if( RECORD_D3D9( hr ).IsFailure )\r
193                         return nullptr;\r
194 \r
195                 Mesh^ mesh = Mesh::FromPointer( result );\r
196 \r
197                 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );\r
198                 return mesh;\r
199         }\r
200 \r
201         Mesh^ Mesh::CreateCylinder( SlimDX::Direct3D9::Device^ device, float radius1, float radius2, float length, int slices, int stacks )\r
202         {\r
203                 ID3DXMesh *result = NULL;\r
204                 ID3DXBuffer *adj = NULL;\r
205 \r
206                 HRESULT hr = D3DXCreateCylinder( device->InternalPointer, radius1, radius2, length, slices, stacks, &result, &adj );\r
207                 \r
208                 if( RECORD_D3D9( hr ).IsFailure )\r
209                         return nullptr;\r
210 \r
211                 Mesh^ mesh = Mesh::FromPointer( result );\r
212 \r
213                 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );\r
214                 return mesh;\r
215         }\r
216 \r
217         Mesh^ Mesh::CreateSphere( SlimDX::Direct3D9::Device^ device, float radius, int slices, int stacks )\r
218         {\r
219                 ID3DXMesh *result = NULL;\r
220                 ID3DXBuffer *adj = NULL;\r
221 \r
222                 HRESULT hr = D3DXCreateSphere( device->InternalPointer, radius, slices, stacks, &result, &adj );\r
223                 \r
224                 if( RECORD_D3D9( hr ).IsFailure )\r
225                         return nullptr;\r
226 \r
227                 Mesh^ mesh = Mesh::FromPointer( result );\r
228 \r
229                 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );\r
230                 return mesh;\r
231         }\r
232 \r
233         Mesh^ Mesh::CreateTeapot( SlimDX::Direct3D9::Device^ device )\r
234         {\r
235                 ID3DXMesh *result = NULL;\r
236                 ID3DXBuffer *adj = NULL;\r
237 \r
238                 HRESULT hr = D3DXCreateTeapot( device->InternalPointer, &result, &adj );\r
239                 \r
240                 if( RECORD_D3D9( hr ).IsFailure )\r
241                         return nullptr;\r
242 \r
243                 Mesh^ mesh = Mesh::FromPointer( result );\r
244 \r
245                 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );\r
246                 return mesh;\r
247         }\r
248 \r
249         Mesh^ Mesh::CreateTorus( SlimDX::Direct3D9::Device^ device, float innerRadius, float outerRadius, int sides, int rings )\r
250         {\r
251                 ID3DXMesh *result = NULL;\r
252                 ID3DXBuffer *adj = NULL;\r
253 \r
254                 HRESULT hr = D3DXCreateTorus( device->InternalPointer, innerRadius, outerRadius, sides, rings, &result, &adj );\r
255                 \r
256                 if( RECORD_D3D9( hr ).IsFailure )\r
257                         return nullptr;\r
258 \r
259                 Mesh^ mesh = Mesh::FromPointer( result );\r
260 \r
261                 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );\r
262                 return mesh;\r
263         }\r
264 \r
265         Mesh^ Mesh::CreateText( SlimDX::Direct3D9::Device^ device, Font^ font, String^ text, float deviation, float extrusion, [Out] array<GlyphMetricsFloat>^% glyphMetrics )\r
266         {\r
267                 ID3DXMesh *result = NULL;\r
268                 ID3DXBuffer *adj = NULL;\r
269 \r
270                 glyphMetrics = gcnew array<GlyphMetricsFloat>( text->Length );\r
271 \r
272                 pin_ptr<const wchar_t> pinnedText = PtrToStringChars( text );\r
273                 pin_ptr<GlyphMetricsFloat> pinnedMetrics = &glyphMetrics[0];\r
274 \r
275                 HDC hdc = CreateCompatibleDC( NULL );\r
276                 HFONT newFont;\r
277                 HFONT oldFont;\r
278                 if( hdc == NULL )\r
279                         throw gcnew OutOfMemoryException();\r
280 \r
281                 newFont = static_cast<HFONT>( font->ToHfont().ToPointer() );\r
282                 oldFont = static_cast<HFONT>( SelectObject( hdc, newFont ) );           \r
283 \r
284                 HRESULT hr = D3DXCreateText( device->InternalPointer, hdc, reinterpret_cast<LPCWSTR>( pinnedText ),\r
285                         deviation, extrusion, &result, &adj, reinterpret_cast<LPGLYPHMETRICSFLOAT>( pinnedMetrics ) );\r
286 \r
287                 SelectObject( hdc, oldFont );\r
288                 DeleteObject( newFont );\r
289                 DeleteDC( hdc );\r
290 \r
291                 if( RECORD_D3D9( hr ).IsFailure )\r
292                 {\r
293                         glyphMetrics = nullptr;\r
294                         return nullptr;\r
295                 }\r
296 \r
297                 Mesh^ mesh = Mesh::FromPointer( result );\r
298 \r
299                 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );\r
300                 return mesh;\r
301         }\r
302 \r
303         Mesh^ Mesh::CreateText( SlimDX::Direct3D9::Device^ device, Font^ font, String^ text, float deviation, float extrusion )\r
304         {\r
305                 ID3DXMesh *result = NULL;\r
306                 ID3DXBuffer *adj = NULL;\r
307 \r
308                 pin_ptr<const wchar_t> pinnedText = PtrToStringChars( text );\r
309 \r
310                 HDC hdc = CreateCompatibleDC( NULL );\r
311                 HFONT newFont;\r
312                 HFONT oldFont;\r
313                 if( hdc == NULL )\r
314                         throw gcnew OutOfMemoryException();\r
315 \r
316                 newFont = static_cast<HFONT>( font->ToHfont().ToPointer() );\r
317                 oldFont = static_cast<HFONT>( SelectObject( hdc, newFont ) );           \r
318 \r
319                 HRESULT hr = D3DXCreateText( device->InternalPointer, hdc, reinterpret_cast<LPCWSTR>( pinnedText ),\r
320                         deviation, extrusion, &result, &adj, NULL );\r
321 \r
322                 SelectObject( hdc, oldFont );\r
323                 DeleteObject( newFont );\r
324                 DeleteDC( hdc );\r
325 \r
326                 if( RECORD_D3D9( hr ).IsFailure )\r
327                         return nullptr;\r
328 \r
329                 Mesh^ mesh = Mesh::FromPointer( result );\r
330 \r
331                 mesh->SetAdjacency( Utilities::ReadRange<int>( adj, result->GetNumFaces() * 3 ) );\r
332                 return mesh;\r
333         }\r
334 \r
335         DataStream^ Mesh::LockAttributeBuffer( LockFlags flags )\r
336         {\r
337                 DWORD *data = NULL;\r
338                 int faceCount = InternalPointer->GetNumFaces();\r
339                 \r
340                 HRESULT hr = InternalPointer->LockAttributeBuffer( static_cast<DWORD>( flags ), &data );\r
341                 \r
342                 if( RECORD_D3D9( hr ).IsFailure )\r
343                         return nullptr;\r
344 \r
345                 bool readOnly = (flags & LockFlags::ReadOnly) == LockFlags::ReadOnly;\r
346                 return gcnew DataStream( data, faceCount * sizeof( DWORD ), true, !readOnly, false );\r
347         }\r
348 \r
349         Result Mesh::UnlockAttributeBuffer()\r
350         {\r
351                 HRESULT hr = InternalPointer->UnlockAttributeBuffer();\r
352                 return RECORD_D3D9( hr );\r
353         }\r
354 \r
355         Result Mesh::SetAttributeTable( array<AttributeRange>^ table )\r
356         {\r
357                 pin_ptr<AttributeRange> pinnedTable = &table[0];\r
358 \r
359                 HRESULT hr = InternalPointer->SetAttributeTable( reinterpret_cast<const D3DXATTRIBUTERANGE*>( pinnedTable ), table->Length );\r
360                 return RECORD_D3D9( hr );\r
361         }\r
362 \r
363         Result Mesh::OptimizeInPlace( MeshOptimizeFlags flags, [Out] array<int>^% faceRemap, [Out] array<int>^% vertexRemap )\r
364         {\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
369 \r
370                 array<int>^ adjacency = GetAdjacency();\r
371                 pin_ptr<int> pinnedAdjIn;\r
372 \r
373                 faceRemap = gcnew array<int>( FaceCount );\r
374                 pin_ptr<int> pinnedFR = &faceRemap[0];\r
375 \r
376                 if( adjacency != nullptr )\r
377                 {\r
378                         pinnedAdjIn = &adjacency[0];\r
379                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
380                         adjacencyOutPtr = &adjacencyOut[0];\r
381                 }               \r
382 \r
383                 HRESULT hr = InternalPointer->OptimizeInplace( static_cast<DWORD>( flags ), adjacencyIn,\r
384                         adjacencyOutPtr, reinterpret_cast<DWORD*>( pinnedFR ), &buffer );\r
385 \r
386                 if( RECORD_D3D9( hr ).IsFailure )\r
387                 {\r
388                         faceRemap = nullptr;\r
389                         vertexRemap = nullptr;\r
390                         SetAdjacency( NULL );\r
391                 }\r
392                 else\r
393                 {\r
394                         vertexRemap = Utilities::ReadRange<int>( buffer, VertexCount );\r
395                         if( adjacencyOutPtr != NULL )\r
396                                 SetAdjacency( &adjacencyOut[0] );\r
397                         else\r
398                                 SetAdjacency( NULL );\r
399                 }\r
400 \r
401                 return Result::Last;\r
402         }\r
403 \r
404         Result Mesh::OptimizeInPlace( MeshOptimizeFlags flags )\r
405         {\r
406                 DWORD *adjacencyIn = NULL;\r
407                 DWORD *adjacencyOutPtr = NULL;\r
408                 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );\r
409 \r
410                 array<int>^ adjacency = GetAdjacency();\r
411                 pin_ptr<int> pinnedAdjIn;\r
412                 if( adjacency != nullptr )\r
413                 {\r
414                         pinnedAdjIn = &adjacency[0];\r
415                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
416                         adjacencyOutPtr = &adjacencyOut[0];\r
417                 }\r
418 \r
419                 HRESULT hr = InternalPointer->OptimizeInplace( static_cast<DWORD>( flags ), adjacencyIn,\r
420                         adjacencyOutPtr, NULL, NULL );\r
421                 RECORD_D3D9( hr );\r
422 \r
423                 if( FAILED( hr ) )\r
424                         SetAdjacency( NULL );\r
425                 else\r
426                 {\r
427                         if( adjacencyOutPtr != NULL )\r
428                                 SetAdjacency( &adjacencyOut[0] );\r
429                         else\r
430                                 SetAdjacency( NULL );\r
431                 }\r
432 \r
433                 return Result::Last;\r
434         }\r
435 \r
436         Mesh^ Mesh::Optimize( MeshOptimizeFlags flags, [Out] array<int>^% faceRemap, [Out] array<int>^% vertexRemap )\r
437         {\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
443 \r
444                 array<int>^ adjacency = GetAdjacency();\r
445                 pin_ptr<int> pinnedAdjIn;\r
446 \r
447                 faceRemap = gcnew array<int>( FaceCount );\r
448                 pin_ptr<int> pinnedFR = &faceRemap[0];\r
449 \r
450                 if( adjacency != nullptr )\r
451                 {\r
452                         pinnedAdjIn = &adjacency[0];\r
453                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
454                         adjacencyOutPtr = &adjacencyOut[0];\r
455                 }               \r
456 \r
457                 HRESULT hr = InternalPointer->Optimize( static_cast<DWORD>( flags ), adjacencyIn,\r
458                         adjacencyOutPtr, reinterpret_cast<DWORD*>( pinnedFR ), &buffer, &result );\r
459 \r
460                 if( RECORD_D3D9( hr ).IsFailure )\r
461                 {\r
462                         faceRemap = nullptr;\r
463                         vertexRemap = nullptr;\r
464                         return nullptr;\r
465                 }\r
466 \r
467                 Mesh^ mesh = Mesh::FromPointer( result );\r
468 \r
469                 vertexRemap = Utilities::ReadRange<int>( buffer, VertexCount );\r
470 \r
471                 if( adjacencyOutPtr != NULL )\r
472                         mesh->SetAdjacency( &adjacencyOut[0] );\r
473 \r
474                 return mesh;\r
475         }\r
476 \r
477         Mesh^ Mesh::Optimize( MeshOptimizeFlags flags )\r
478         {\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
483 \r
484                 array<int>^ adjacency = GetAdjacency();\r
485                 pin_ptr<int> pinnedAdjIn;\r
486 \r
487                 if( adjacency != nullptr )\r
488                 {\r
489                         pinnedAdjIn = &adjacency[0];\r
490                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
491                         adjacencyOutPtr = &adjacencyOut[0];\r
492                 }\r
493 \r
494                 HRESULT hr = InternalPointer->Optimize( static_cast<DWORD>( flags ), adjacencyIn,\r
495                         adjacencyOutPtr, NULL, NULL, &result );\r
496 \r
497                 if( RECORD_D3D9( hr ).IsFailure )\r
498                         return nullptr;\r
499 \r
500                 Mesh^ mesh = Mesh::FromPointer( result );\r
501 \r
502                 if( adjacencyOutPtr != NULL )\r
503                         mesh->SetAdjacency( &adjacencyOut[0] );\r
504 \r
505                 return mesh;\r
506         }\r
507 \r
508         Mesh^ Mesh::Clean( CleanType type, [Out] String^% errorsAndWarnings )\r
509         {\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
515 \r
516                 array<int>^ adjacency = GetAdjacency();\r
517                 pin_ptr<int> pinnedAdjIn;\r
518 \r
519                 if( adjacency != nullptr )\r
520                 {\r
521                         pinnedAdjIn = &adjacency[0];\r
522                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
523                         adjacencyOutPtr = &adjacencyOut[0];\r
524                 }\r
525 \r
526                 HRESULT hr = D3DXCleanMesh( static_cast<D3DXCLEANTYPE>( type ), InternalPointer, \r
527                         adjacencyIn, &result, adjacencyOutPtr, &errors );\r
528 \r
529                 if( RECORD_D3D9( hr ).IsFailure )\r
530                 {\r
531                         errorsAndWarnings = nullptr;\r
532                         return nullptr;\r
533                 }\r
534 \r
535                 errorsAndWarnings = Utilities::BufferToString( errors );\r
536 \r
537                 Mesh^ mesh = Mesh::FromPointer( result );\r
538 \r
539                 if( adjacencyOutPtr != NULL )\r
540                         mesh->SetAdjacency( &adjacencyOut[0] );\r
541 \r
542                 return mesh;\r
543         }\r
544 \r
545         Mesh^ Mesh::Clean( CleanType type )\r
546         {\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
551 \r
552                 array<int>^ adjacency = GetAdjacency();\r
553                 pin_ptr<int> pinnedAdjIn;\r
554 \r
555                 if( adjacency != nullptr )\r
556                 {\r
557                         pinnedAdjIn = &adjacency[0];\r
558                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
559                         adjacencyOutPtr = &adjacencyOut[0];\r
560                 }\r
561 \r
562                 HRESULT hr = D3DXCleanMesh( static_cast<D3DXCLEANTYPE>( type ), InternalPointer, \r
563                         &adjacencyIn[0], &result, adjacencyOutPtr, NULL );\r
564 \r
565                 if( RECORD_D3D9( hr ).IsFailure )\r
566                         return nullptr;\r
567 \r
568                 Mesh^ mesh = Mesh::FromPointer( result );\r
569 \r
570                 if( adjacencyOutPtr != NULL )\r
571                         mesh->SetAdjacency( &adjacencyOut[0] );\r
572 \r
573                 return mesh;\r
574         }\r
575 \r
576         void Mesh::GenerateAdjacency( float epsilon )\r
577         {\r
578                 array<int>^ adj = BaseMesh::GenerateAdjacency( epsilon );\r
579                 SetAdjacency( adj );\r
580         }\r
581 \r
582         String^ Mesh::Validate()\r
583         {\r
584                 ID3DXBuffer *errorBuffer = NULL;\r
585                 DWORD *adjacencyIn = NULL;\r
586                 pin_ptr<int> pinnedAdj;\r
587                 String^ errors = nullptr;\r
588 \r
589                 array<int>^ adjacency = GetAdjacency();\r
590                 if( adjacency != nullptr )\r
591                 {\r
592                         pinnedAdj = &adjacency[0];\r
593                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );\r
594                 }\r
595 \r
596                 D3DXValidMesh( InternalPointer, adjacencyIn, &errorBuffer );\r
597                 errors = Utilities::BufferToString( errorBuffer );\r
598 \r
599                 return errors;\r
600         }\r
601 \r
602         void Mesh::SetAdjacency( DWORD *adj )\r
603         {\r
604                 if( adj == NULL )\r
605                         adjacency = nullptr;\r
606                 else\r
607                 {\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
611                 }\r
612         }\r
613 \r
614         Result Mesh::ComputeNormals()\r
615         {\r
616                 DWORD *adjacencyIn = NULL;\r
617                 pin_ptr<int> pinnedAdj;\r
618 \r
619                 array<int>^ adjacency = GetAdjacency();\r
620                 if( adjacency != nullptr )\r
621                 {\r
622                         pinnedAdj = &adjacency[0];\r
623                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );\r
624                 }\r
625 \r
626                 HRESULT hr = D3DXComputeNormals( InternalPointer, adjacencyIn );\r
627                 return RECORD_D3D9( hr );\r
628         }\r
629 \r
630         Result Mesh::ComputeTangent( int textureStage, int tangentIndex, int binormalIndex, bool wrap )\r
631         {\r
632                 array<int>^ adjacency = GetAdjacency();\r
633                 DWORD *adjacencyIn = NULL;\r
634                 pin_ptr<int> pinnedAdj;\r
635 \r
636                 if( adjacency != nullptr )\r
637                 {\r
638                         pinnedAdj = &adjacency[0];\r
639                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );\r
640                 }\r
641 \r
642                 HRESULT hr = D3DXComputeTangent( InternalPointer, textureStage, tangentIndex, binormalIndex, wrap, adjacencyIn );\r
643                 return RECORD_D3D9( hr );\r
644         }\r
645 \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
650         {\r
651                 ID3DXMesh *result = NULL;\r
652                 ID3DXBuffer *vertex = NULL;\r
653 \r
654                 array<int>^ adjacency = GetAdjacency();\r
655                 DWORD *adjacencyIn = NULL;\r
656                 pin_ptr<int> pinnedAdj;\r
657 \r
658                 if( adjacency != nullptr )\r
659                 {\r
660                         pinnedAdj = &adjacency[0];\r
661                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );\r
662                 }\r
663 \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
668 \r
669                 if( RECORD_D3D9( hr ).IsFailure )\r
670                 {\r
671                         vertexMapping = nullptr;\r
672                         return nullptr;\r
673                 }\r
674 \r
675                 vertexMapping = Utilities::ReadRange<int>( vertex, result->GetNumVertices() );\r
676 \r
677                 if( (options & TangentOptions::GenerateInPlace) == TangentOptions::GenerateInPlace )\r
678                         return this;\r
679 \r
680                 return Mesh::FromPointer( result );\r
681         }\r
682 \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
687         {\r
688                 ID3DXMesh *result = NULL;\r
689 \r
690                 array<int>^ adjacency = GetAdjacency();\r
691                 DWORD *adjacencyIn = NULL;\r
692                 pin_ptr<int> pinnedAdj;\r
693 \r
694                 if( adjacency != nullptr )\r
695                 {\r
696                         pinnedAdj = &adjacency[0];\r
697                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );\r
698                 }\r
699 \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
704 \r
705                 if( RECORD_D3D9( hr ).IsFailure )\r
706                         return nullptr;\r
707 \r
708                 if( (options & TangentOptions::GenerateInPlace) == TangentOptions::GenerateInPlace )\r
709                         return this;\r
710 \r
711                 return Mesh::FromPointer( result );\r
712         }\r
713 \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
716         {\r
717                 ID3DXMesh *result = NULL;\r
718                 D3DXMATRIX *geoXForms = NULL;\r
719                 D3DXMATRIX *textureXForms = NULL;\r
720                 D3DVERTEXELEMENT9 *decl = NULL;\r
721 \r
722                 pin_ptr<Matrix> pinnedGeo = nullptr;\r
723                 pin_ptr<Matrix> pinnedTexture = nullptr;\r
724                 pin_ptr<VertexElement> pinnedDecl = nullptr;\r
725 \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
729 \r
730                 if( geometryTransforms != nullptr )\r
731                 {\r
732                         pinnedGeo = &geometryTransforms[0];\r
733                         geoXForms = reinterpret_cast<D3DXMATRIX*>( pinnedGeo );\r
734                 }\r
735 \r
736                 if( textureTransforms != nullptr )\r
737                 {\r
738                         pinnedTexture = &textureTransforms[0];\r
739                         textureXForms = reinterpret_cast<D3DXMATRIX*>( pinnedTexture );\r
740                 }\r
741 \r
742                 if( vertexDeclaration != nullptr )\r
743                 {\r
744                         pinnedDecl = &vertexDeclaration[0];\r
745                         decl = reinterpret_cast<D3DVERTEXELEMENT9*>( pinnedDecl );\r
746                 }\r
747 \r
748                 HRESULT hr = D3DXConcatenateMeshes( &input[0], meshes->Length, static_cast<DWORD>( options ), geoXForms,\r
749                         textureXForms, decl, device->InternalPointer, &result );\r
750 \r
751                 if( RECORD_D3D9( hr ).IsFailure )\r
752                         return nullptr;\r
753 \r
754                 return Mesh::FromPointer( result );\r
755         }\r
756 \r
757         Mesh^ Mesh::Concatenate( SlimDX::Direct3D9::Device^ device, array<Mesh^>^ meshes, MeshFlags options, array<Matrix>^ geometryTransforms,\r
758                 array<Matrix>^ textureTransforms )\r
759         {\r
760                 ID3DXMesh *result = NULL;\r
761                 D3DXMATRIX *geoXForms = NULL;\r
762                 D3DXMATRIX *textureXForms = NULL;\r
763 \r
764                 pin_ptr<Matrix> pinnedGeo = nullptr;\r
765                 pin_ptr<Matrix> pinnedTexture = nullptr;\r
766 \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
770 \r
771                 if( geometryTransforms != nullptr )\r
772                 {\r
773                         pinnedGeo = &geometryTransforms[0];\r
774                         geoXForms = reinterpret_cast<D3DXMATRIX*>( pinnedGeo );\r
775                 }\r
776 \r
777                 if( textureTransforms != nullptr )\r
778                 {\r
779                         pinnedTexture = &textureTransforms[0];\r
780                         textureXForms = reinterpret_cast<D3DXMATRIX*>( pinnedTexture );\r
781                 }\r
782 \r
783                 HRESULT hr = D3DXConcatenateMeshes( &input[0], meshes->Length, static_cast<DWORD>( options ), geoXForms,\r
784                         textureXForms, NULL, device->InternalPointer, &result );\r
785 \r
786                 if( RECORD_D3D9( hr ).IsFailure )\r
787                         return nullptr;\r
788 \r
789                 return Mesh::FromPointer( result );\r
790         }\r
791 \r
792         Mesh^ Mesh::Concatenate( SlimDX::Direct3D9::Device^ device, array<Mesh^>^ meshes, MeshFlags options )\r
793         {\r
794                 ID3DXMesh *result = NULL;\r
795 \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
799 \r
800                 HRESULT hr = D3DXConcatenateMeshes( &input[0], meshes->Length, static_cast<DWORD>( options ), NULL,\r
801                         NULL, NULL, device->InternalPointer, &result );\r
802 \r
803                 if( RECORD_D3D9( hr ).IsFailure )\r
804                         return nullptr;\r
805 \r
806                 return Mesh::FromPointer( result );\r
807         }\r
808 \r
809         Result Mesh::ToXFile( Mesh^ mesh, String^ fileName, XFileFormat format, CharSet charSet )\r
810         {\r
811                 pin_ptr<const wchar_t> pinnedName = PtrToStringChars( fileName );\r
812                 \r
813                 array<int>^ adjacency = mesh->GetAdjacency();\r
814                 array<ExtendedMaterial>^ materials = mesh->GetMaterials();\r
815                 array<EffectInstance>^ effects = mesh->GetEffects();\r
816 \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
823                 int length = 0;\r
824 \r
825                 if( adjacency != nullptr )\r
826                 {\r
827                         pinnedAdj = &adjacency[0];\r
828                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );\r
829                 }\r
830 \r
831                 if( materials != nullptr )\r
832                 {\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
837 \r
838                         materialPtr = &nativeMaterials[0];\r
839                 }\r
840 \r
841                 if( effects != nullptr )\r
842                 {\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
846 \r
847                         effectPtr = &nativeEffects[0];\r
848                 }\r
849 \r
850                 DWORD f = static_cast<DWORD>( format );\r
851                 if( charSet == CharSet::Unicode )\r
852                         f |= D3DXF_FILESAVE_TOWFILE;\r
853                 else\r
854                         f |= D3DXF_FILESAVE_TOFILE;\r
855 \r
856                 HRESULT hr = D3DXSaveMeshToX( reinterpret_cast<LPCWSTR>( pinnedName ), mesh->InternalPointer, \r
857                         adjacencyIn, materialPtr, effectPtr, length, f );\r
858 \r
859                 if( materials != nullptr )\r
860                 {\r
861                         for( int i = 0; i < length; i++ )\r
862                                 Utilities::FreeNativeString( nativeMaterials[i].pTextureFilename );\r
863                 }\r
864 \r
865                 if( effects != nullptr )\r
866                 {\r
867                         for( int i = 0; i < effects->Length; i++ )\r
868                         {\r
869                                 for( UINT j = 0; j < nativeEffects[i].NumDefaults; j++ )\r
870                                         Utilities::FreeNativeString( nativeEffects[i].pDefaults[j].pParamName );\r
871 \r
872                                 delete[] nativeEffects[i].pDefaults;\r
873                         }\r
874                 }\r
875 \r
876                 return RECORD_D3D9( hr );\r
877         }\r
878 \r
879         Result Mesh::ToXFile( Mesh^ mesh, String^ fileName, XFileFormat format )\r
880         {\r
881                 return ToXFile( mesh, fileName, format, CharSet::Auto );\r
882         }\r
883 \r
884         Mesh^ Mesh::Simplify( Mesh^ mesh, array<AttributeWeights>^ attributeWeights,\r
885                 array<float>^ vertexWeights, int minimumValue, MeshSimplification options )\r
886         {\r
887                 ID3DXMesh *result = NULL;\r
888 \r
889                 DWORD *adjacencyIn = NULL;\r
890                 pin_ptr<int> pinnedAdj;\r
891                 array<int>^ adjacency = mesh->GetAdjacency();\r
892 \r
893                 if( adjacency != nullptr )\r
894                 {\r
895                         pinnedAdj = &adjacency[0];\r
896                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );\r
897                 }\r
898 \r
899                 pin_ptr<float> pinnedVW = &vertexWeights[0];\r
900                 pin_ptr<AttributeWeights> pinnedAW = &attributeWeights[0];\r
901 \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
905 \r
906                 if( RECORD_D3D9( hr ).IsFailure )\r
907                         return nullptr;\r
908 \r
909                 return Mesh::FromPointer( result );\r
910         }\r
911 \r
912         Mesh^ Mesh::Simplify( Mesh^ mesh, array<AttributeWeights>^ attributeWeights,\r
913                 int minimumValue, MeshSimplification options )\r
914         {\r
915                 ID3DXMesh *result = NULL;\r
916 \r
917                 DWORD *adjacencyIn = NULL;\r
918                 pin_ptr<int> pinnedAdj;\r
919                 array<int>^ adjacency = mesh->GetAdjacency();\r
920 \r
921                 if( adjacency != nullptr )\r
922                 {\r
923                         pinnedAdj = &adjacency[0];\r
924                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );\r
925                 }\r
926 \r
927                 pin_ptr<AttributeWeights> pinnedAW = &attributeWeights[0];\r
928 \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
932 \r
933                 if( RECORD_D3D9( hr ).IsFailure )\r
934                         return nullptr;\r
935 \r
936                 return Mesh::FromPointer( result );\r
937         }\r
938 \r
939         Mesh^ Mesh::Simplify( Mesh^ mesh, int minimumValue, MeshSimplification options )\r
940         {\r
941                 ID3DXMesh *result = NULL;\r
942 \r
943                 DWORD *adjacencyIn = NULL;\r
944                 array<int>^ adjacency = mesh->GetAdjacency();\r
945                 pin_ptr<int> pinnedAdj;\r
946 \r
947                 if( adjacency != nullptr )\r
948                 {\r
949                         pinnedAdj = &adjacency[0];\r
950                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );\r
951                 }\r
952 \r
953                 HRESULT hr = D3DXSimplifyMesh( mesh->InternalPointer, adjacencyIn,\r
954                         NULL, NULL, minimumValue, static_cast<DWORD>( options ), &result );\r
955 \r
956                 if( RECORD_D3D9( hr ).IsFailure )\r
957                         return nullptr;\r
958 \r
959                 return Mesh::FromPointer( result );\r
960         }\r
961 \r
962         Mesh^ Mesh::TessellateNPatches( Mesh^ mesh, float segmentCount, bool quadraticInterpolation )\r
963         {\r
964                 ID3DXMesh *result = NULL;\r
965                 ID3DXBuffer *adjacencyOut = NULL;\r
966 \r
967                 DWORD *adjacencyIn = NULL;\r
968                 array<int>^ adjacency = mesh->GetAdjacency();\r
969                 pin_ptr<int> pinnedAdj;\r
970 \r
971                 if( adjacency != nullptr )\r
972                 {\r
973                         pinnedAdj = &adjacency[0];\r
974                         adjacencyIn = reinterpret_cast<DWORD*>( pinnedAdj );\r
975                 }\r
976 \r
977                 HRESULT hr = D3DXTessellateNPatches( mesh->InternalPointer, adjacencyIn, segmentCount,\r
978                         quadraticInterpolation, &result, &adjacencyOut );\r
979 \r
980                 if( RECORD_D3D9( hr ).IsFailure )\r
981                         return nullptr;\r
982 \r
983                 Mesh^ newMesh = Mesh::FromPointer( result );\r
984                 newMesh->SetAdjacency( Utilities::ReadRange<int>( adjacencyOut, result->GetNumFaces() * 3 ) );\r
985 \r
986                 return newMesh;\r
987         }\r
988 \r
989         Result Mesh::TessellateRectanglePatch( SlimDX::Direct3D9::VertexBuffer^ vertexBuffer, array<float>^ segmentCounts,\r
990                 array<VertexElement>^ vertexDeclaration, RectanglePatchInfo rectanglePatchInfo )\r
991         {\r
992                 pin_ptr<float> pinnedSegments = &segmentCounts[0];\r
993                 pin_ptr<VertexElement> pinnedDeclaration = &vertexDeclaration[0];\r
994 \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
997                         InternalPointer );\r
998 \r
999                 return RECORD_D3D9( hr );\r
1000         }\r
1001 \r
1002         Result Mesh::TessellateTrianglePatch( SlimDX::Direct3D9::VertexBuffer^ vertexBuffer, array<float>^ segmentCounts,\r
1003                 array<VertexElement>^ vertexDeclaration, TrianglePatchInfo trianglePatchInfo )\r
1004         {\r
1005                 pin_ptr<float> pinnedSegments = &segmentCounts[0];\r
1006                 pin_ptr<VertexElement> pinnedDeclaration = &vertexDeclaration[0];\r
1007 \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
1011 \r
1012                 return RECORD_D3D9( hr );\r
1013         }\r
1014 \r
1015         Result Mesh::WeldVertices( WeldFlags flags, WeldEpsilons epsilons, [Out] array<int>^% faceRemap, [Out] array<int>^% vertexRemap )\r
1016         {\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
1021 \r
1022                 array<int>^ adjacency = GetAdjacency();\r
1023                 pin_ptr<int> pinnedAdjIn;\r
1024 \r
1025                 faceRemap = gcnew array<int>( FaceCount );\r
1026                 pin_ptr<int> pinnedFR = &faceRemap[0];\r
1027 \r
1028                 if( adjacency != nullptr )\r
1029                 {\r
1030                         pinnedAdjIn = &adjacency[0];\r
1031                         adjIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
1032                         adjOut = &adjacencyOut[0];\r
1033                 }\r
1034 \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
1038 \r
1039                 if( RECORD_D3D9( hr ).IsFailure )\r
1040                 {\r
1041                         faceRemap = nullptr;\r
1042                         vertexRemap = nullptr;\r
1043                         return Result::Last;\r
1044                 }\r
1045 \r
1046                 vertexRemap = Utilities::ReadRange<int>( buffer, VertexCount );\r
1047 \r
1048                 if( adjOut != NULL )\r
1049                         SetAdjacency( &adjacencyOut[0] );\r
1050 \r
1051                 return Result::Last;\r
1052         }\r
1053 \r
1054         Result Mesh::WeldVertices( WeldFlags flags, [Out] array<int>^% faceRemap, [Out] array<int>^% vertexRemap )\r
1055         {\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
1060 \r
1061                 array<int>^ adjacency = GetAdjacency();\r
1062                 pin_ptr<int> pinnedAdjIn;\r
1063 \r
1064                 faceRemap = gcnew array<int>( FaceCount );\r
1065                 pin_ptr<int> pinnedFR = &faceRemap[0];\r
1066 \r
1067                 if( adjacency != nullptr )\r
1068                 {\r
1069                         pinnedAdjIn = &adjacency[0];\r
1070                         adjIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
1071                         adjOut = &adjacencyOut[0];\r
1072                 }\r
1073 \r
1074                 HRESULT hr = D3DXWeldVertices( InternalPointer, static_cast<DWORD>( flags ), NULL, adjIn, adjOut, \r
1075                         reinterpret_cast<DWORD*>( pinnedFR ), &buffer );\r
1076 \r
1077                 if( RECORD_D3D9( hr ).IsFailure )\r
1078                 {\r
1079                         faceRemap = nullptr;\r
1080                         vertexRemap = nullptr;\r
1081                         return Result::Last;\r
1082                 }\r
1083 \r
1084                 vertexRemap = Utilities::ReadRange<int>( buffer, VertexCount );\r
1085 \r
1086                 if( adjOut != NULL )\r
1087                         SetAdjacency( &adjacencyOut[0] );\r
1088 \r
1089                 return Result::Last;\r
1090         }\r
1091 \r
1092         Result Mesh::WeldVertices( WeldFlags flags, WeldEpsilons epsilons )\r
1093         {\r
1094                 DWORD *adjIn = NULL;\r
1095                 DWORD *adjOut = NULL;\r
1096                 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );\r
1097 \r
1098                 array<int>^ adjacency = GetAdjacency();\r
1099                 pin_ptr<int> pinnedAdjIn;\r
1100 \r
1101                 if( adjacency != nullptr )\r
1102                 {\r
1103                         pinnedAdjIn = &adjacency[0];\r
1104                         adjIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
1105                         adjOut = &adjacencyOut[0];\r
1106                 }\r
1107 \r
1108                 HRESULT hr = D3DXWeldVertices( InternalPointer, static_cast<DWORD>( flags ), \r
1109                         reinterpret_cast<const D3DXWELDEPSILONS*>( &epsilons ), adjIn, adjOut, NULL, NULL );\r
1110 \r
1111                 if( RECORD_D3D9( hr ).IsFailure )\r
1112                         return Result::Last;\r
1113 \r
1114                 if( adjOut != NULL )\r
1115                         SetAdjacency( &adjacencyOut[0] );\r
1116 \r
1117                 return Result::Last;\r
1118         }\r
1119 \r
1120         Result Mesh::WeldVertices( WeldFlags flags )\r
1121         {\r
1122                 DWORD *adjIn = NULL;\r
1123                 DWORD *adjOut = NULL;\r
1124                 stack_array<DWORD> adjacencyOut = stackalloc( DWORD, FaceCount * 3 );\r
1125 \r
1126                 array<int>^ adjacency = GetAdjacency();\r
1127                 pin_ptr<int> pinnedAdjIn;\r
1128 \r
1129                 if( adjacency != nullptr )\r
1130                 {\r
1131                         pinnedAdjIn = &adjacency[0];\r
1132                         adjIn = reinterpret_cast<DWORD*>( pinnedAdjIn );\r
1133                         adjOut = &adjacencyOut[0];\r
1134                 }\r
1135 \r
1136                 HRESULT hr = D3DXWeldVertices( InternalPointer, static_cast<DWORD>( flags ), NULL, adjIn, adjOut, NULL, NULL );\r
1137 \r
1138                 if( RECORD_D3D9( hr ).IsFailure )\r
1139                         return Result::Last;\r
1140 \r
1141                 if( adjOut != NULL )\r
1142                         SetAdjacency( &adjacencyOut[0] );\r
1143 \r
1144                 return Result::Last;\r
1145         }\r
1146 }\r
1147 }\r