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 "../ComObject.h"
\r
28 #include "../Utilities.h"
\r
29 #include "../DataStream.h"
\r
31 #include "Direct3D9Exception.h"
\r
34 #include "Texture.h"
\r
35 #include "IndexBuffer.h"
\r
36 #include "VertexBuffer.h"
\r
38 #include "BaseMesh.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^ BaseMesh::Clone( SlimDX::Direct3D9::Device^ device, MeshFlags flags, array<VertexElement>^ elements )
\r
53 pin_ptr<VertexElement> pinned_elements = &elements[0];
\r
55 HRESULT hr = InternalPointer->CloneMesh( static_cast<DWORD>( flags ), reinterpret_cast<const D3DVERTEXELEMENT9*>( pinned_elements ),
\r
56 device->InternalPointer, &mesh );
\r
58 if( RECORD_D3D9( hr ).IsFailure )
\r
61 return Mesh::FromPointer( mesh );
\r
64 Mesh^ BaseMesh::Clone( SlimDX::Direct3D9::Device^ device, MeshFlags flags, SlimDX::Direct3D9::VertexFormat fvf )
\r
68 HRESULT hr = InternalPointer->CloneMeshFVF( static_cast<DWORD>( flags ), static_cast<DWORD>( fvf ),
\r
69 device->InternalPointer, &mesh );
\r
71 if( RECORD_D3D9( hr ).IsFailure )
\r
74 return Mesh::FromPointer( mesh );
\r
77 Result BaseMesh::DrawSubset( int subset )
\r
79 HRESULT hr = InternalPointer->DrawSubset( subset );
\r
80 return RECORD_D3D9( hr );
\r
83 SlimDX::Direct3D9::Device^ BaseMesh::Device::get()
\r
85 IDirect3DDevice9* device;
\r
86 HRESULT hr = InternalPointer->GetDevice( &device );
\r
88 if( RECORD_D3D9( hr ).IsFailure )
\r
91 return SlimDX::Direct3D9::Device::FromPointer( device );
\r
94 IndexBuffer^ BaseMesh::IndexBuffer::get()
\r
96 IDirect3DIndexBuffer9* ib;
\r
97 HRESULT hr = InternalPointer->GetIndexBuffer( &ib );
\r
99 if( RECORD_D3D9( hr ).IsFailure )
\r
102 return SlimDX::Direct3D9::IndexBuffer::FromPointer( ib );
\r
105 VertexBuffer^ BaseMesh::VertexBuffer::get()
\r
107 IDirect3DVertexBuffer9* vb;
\r
108 HRESULT hr = InternalPointer->GetVertexBuffer( &vb );
\r
110 if( RECORD_D3D9( hr ).IsFailure )
\r
113 return SlimDX::Direct3D9::VertexBuffer::FromPointer( vb );
\r
116 array<VertexElement>^ BaseMesh::GetDeclaration()
\r
118 D3DVERTEXELEMENT9 elementBuffer[MAX_FVF_DECL_SIZE];
\r
119 HRESULT hr = InternalPointer->GetDeclaration( elementBuffer );
\r
121 if( RECORD_D3D9( hr ).IsFailure )
\r
124 // Apparently the returned decl does not include an End element. This is bizarre and confusing,
\r
125 // not to mention completely unexpected. We patch it up here.
\r
126 int count = D3DXGetDeclLength( elementBuffer ) + 1;
\r
127 array<VertexElement>^ elements = gcnew array<VertexElement>( count );
\r
128 pin_ptr<VertexElement> pinnedElements = &elements[0];
\r
129 memcpy( pinnedElements, elementBuffer, count * sizeof(D3DVERTEXELEMENT9) );
\r
130 elements[count - 1] = VertexElement::VertexDeclarationEnd;
\r
135 array<AttributeRange>^ BaseMesh::GetAttributeTable()
\r
138 HRESULT hr = InternalPointer->GetAttributeTable( NULL, &count );
\r
140 if( RECORD_D3D9( hr ).IsFailure || count == 0 )
\r
143 array<AttributeRange>^ attribTable = gcnew array<AttributeRange>( count );
\r
144 pin_ptr<AttributeRange> pinnedTable = &attribTable[0];
\r
145 hr = InternalPointer->GetAttributeTable( reinterpret_cast<D3DXATTRIBUTERANGE*>( pinnedTable ), &count );
\r
147 if( RECORD_D3D9( hr ).IsFailure )
\r
150 return attribTable;
\r
153 DataStream^ BaseMesh::LockIndexBuffer( LockFlags flags )
\r
156 HRESULT hr = InternalPointer->LockIndexBuffer( static_cast<DWORD>( flags ), &data );
\r
158 if( RECORD_D3D9( hr ).IsFailure )
\r
161 // determine the size of the buffer
\r
162 int size = 6 * FaceCount;
\r
163 if( (CreationOptions & MeshFlags::Use32Bit) == MeshFlags::Use32Bit )
\r
166 bool readOnly = (flags & LockFlags::ReadOnly) == LockFlags::ReadOnly;
\r
167 return gcnew DataStream( data, size, true, !readOnly, false );
\r
170 Result BaseMesh::UnlockIndexBuffer()
\r
172 HRESULT hr = InternalPointer->UnlockIndexBuffer();
\r
173 return RECORD_D3D9( hr );
\r
176 DataStream^ BaseMesh::LockVertexBuffer( LockFlags flags )
\r
179 HRESULT hr = InternalPointer->LockVertexBuffer( static_cast<DWORD>( flags ), &data );
\r
181 if( RECORD_D3D9( hr ).IsFailure )
\r
184 // determine the size of the buffer
\r
185 int size = BytesPerVertex * VertexCount;
\r
187 bool readOnly = (flags & LockFlags::ReadOnly) == LockFlags::ReadOnly;
\r
188 return gcnew DataStream( data, size, true, !readOnly, false );
\r
191 Result BaseMesh::UnlockVertexBuffer()
\r
193 HRESULT hr = InternalPointer->UnlockVertexBuffer();
\r
194 return RECORD_D3D9( hr );
\r
197 array<int>^ BaseMesh::GenerateAdjacency( float epsilon )
\r
199 // allocate the array to write the adjacency into
\r
200 array<int>^ adjacency = gcnew array<int>( 3 * FaceCount );
\r
201 pin_ptr<int> pinnedAdj = &adjacency[0];
\r
203 HRESULT hr = InternalPointer->GenerateAdjacency( epsilon, reinterpret_cast<DWORD*>( pinnedAdj ) );
\r
205 if( RECORD_D3D9( hr ).IsFailure )
\r
211 array<int>^ BaseMesh::ConvertAdjacencyToPointReps( array<int>^ adjacency )
\r
213 array<int>^ points = gcnew array<int>( VertexCount );
\r
214 pin_ptr<int> pinnedAdj = &adjacency[0];
\r
215 pin_ptr<int> pinnedPoints = &points[0];
\r
217 HRESULT hr = InternalPointer->ConvertAdjacencyToPointReps( reinterpret_cast<const DWORD*>( pinnedAdj ),
\r
218 reinterpret_cast<DWORD*>( pinnedPoints ) );
\r
220 if( RECORD_D3D9( hr ).IsFailure )
\r
226 array<int>^ BaseMesh::ConvertPointRepsToAdjacency( array<int>^ points )
\r
228 array<int>^ adjacency = gcnew array<int>( 3 * FaceCount );
\r
229 pin_ptr<int> pinnedAdj = &adjacency[0];
\r
230 pin_ptr<int> pinnedPoints = &points[0];
\r
232 HRESULT hr = InternalPointer->ConvertPointRepsToAdjacency( reinterpret_cast<const DWORD*>( pinnedPoints ),
\r
233 reinterpret_cast<DWORD*>( pinnedAdj ) );
\r
235 if( RECORD_D3D9( hr ).IsFailure )
\r
241 Result BaseMesh::UpdateSemantics( array<VertexElement>^ elements )
\r
243 pin_ptr<VertexElement> pinnedElements = &elements[0];
\r
245 HRESULT hr = InternalPointer->UpdateSemantics( reinterpret_cast<D3DVERTEXELEMENT9*>( pinnedElements ) );
\r
246 return RECORD_D3D9( hr );
\r
249 IndexBuffer^ BaseMesh::ConvertSubsetToSingleStrip( int attributeId, MeshFlags options, [Out] int% indexCount )
\r
251 IDirect3DIndexBuffer9 *result;
\r
254 HRESULT hr = D3DXConvertMeshSubsetToSingleStrip( InternalPointer, attributeId, static_cast<DWORD>( options ),
\r
257 if( RECORD_D3D9( hr ).IsFailure )
\r
263 indexCount = count;
\r
264 return SlimDX::Direct3D9::IndexBuffer::FromPointer( result );
\r
267 IndexBuffer^ BaseMesh::ConvertSubsetToStrips( int attributeId, MeshFlags options, [Out] int% indexCount,
\r
268 [Out] array<int>^% stripLengths )
\r
270 IDirect3DIndexBuffer9 *result;
\r
271 ID3DXBuffer *buffer;
\r
275 HRESULT hr = D3DXConvertMeshSubsetToStrips( InternalPointer, attributeId, static_cast<DWORD>( options ),
\r
276 &result, &numIndices, &buffer, &numStrips );
\r
278 if( RECORD_D3D9( hr ).IsFailure )
\r
281 stripLengths = nullptr;
\r
285 indexCount = numIndices;
\r
286 stripLengths = Utilities::ReadRange<int>( buffer, numStrips );
\r
287 return SlimDX::Direct3D9::IndexBuffer::FromPointer( result );
\r
290 bool BaseMesh::Intersects( Ray ray, [Out] float% distance, [Out] int% faceIndex, [Out] array<IntersectInformation>^% hits )
\r
292 ID3DXBuffer *allHits;
\r
298 HRESULT hr = D3DXIntersect( InternalPointer, reinterpret_cast<const D3DXVECTOR3*>( &ray.Position ),
\r
299 reinterpret_cast<const D3DXVECTOR3*>( &ray.Direction ), &result, &face, NULL, NULL, &dist, &allHits, &count );
\r
301 if( RECORD_D3D9( hr ).IsFailure )
\r
312 if( allHits == NULL )
\r
315 hits = Utilities::ReadRange<IntersectInformation>( allHits, count );
\r
323 bool BaseMesh::Intersects( Ray ray, [Out] float% distance )
\r
328 HRESULT hr = D3DXIntersect( InternalPointer, reinterpret_cast<const D3DXVECTOR3*>( &ray.Position ),
\r
329 reinterpret_cast<const D3DXVECTOR3*>( &ray.Direction ), &result, NULL, NULL, NULL, &dist, NULL, NULL );
\r
331 if( RECORD_D3D9( hr ).IsFailure )
\r
344 bool BaseMesh::Intersects( Ray ray )
\r
348 HRESULT hr = D3DXIntersect( InternalPointer, reinterpret_cast<const D3DXVECTOR3*>( &ray.Position ),
\r
349 reinterpret_cast<const D3DXVECTOR3*>( &ray.Direction ), &result, NULL, NULL, NULL, NULL, NULL, NULL );
\r
351 if( RECORD_D3D9( hr ).IsFailure || !result )
\r
357 bool BaseMesh::IntersectsSubset( Ray ray, int attributeId, [Out] float% distance, [Out] int% faceIndex, [Out] array<IntersectInformation>^% hits )
\r
359 ID3DXBuffer *allHits;
\r
365 HRESULT hr = D3DXIntersectSubset( InternalPointer, attributeId, reinterpret_cast<const D3DXVECTOR3*>( &ray.Position ),
\r
366 reinterpret_cast<const D3DXVECTOR3*>( &ray.Direction ), &result, &face, NULL, NULL, &dist, &allHits, &count );
\r
368 if( RECORD_D3D9( hr ).IsFailure )
\r
378 hits = Utilities::ReadRange<IntersectInformation>( allHits, count );
\r
386 bool BaseMesh::IntersectsSubset( Ray ray, int attributeId, [Out] float% distance )
\r
391 HRESULT hr = D3DXIntersectSubset( InternalPointer, attributeId, reinterpret_cast<const D3DXVECTOR3*>( &ray.Position ),
\r
392 reinterpret_cast<const D3DXVECTOR3*>( &ray.Direction ), &result, NULL, NULL, NULL, &dist, NULL, NULL );
\r
394 if( RECORD_D3D9( hr ).IsFailure )
\r
407 bool BaseMesh::IntersectsSubset( Ray ray, int attributeId )
\r
411 HRESULT hr = D3DXIntersectSubset( InternalPointer, attributeId, reinterpret_cast<const D3DXVECTOR3*>( &ray.Position ),
\r
412 reinterpret_cast<const D3DXVECTOR3*>( &ray.Direction ), &result, NULL, NULL, NULL, NULL, NULL, NULL );
\r
414 if( RECORD_D3D9( hr ).IsFailure || !result )
\r
420 int BaseMesh::FaceCount::get()
\r
422 return InternalPointer->GetNumFaces();
\r
425 int BaseMesh::VertexCount::get()
\r
427 return InternalPointer->GetNumVertices();
\r
430 SlimDX::Direct3D9::VertexFormat BaseMesh::VertexFormat::get()
\r
432 return static_cast<SlimDX::Direct3D9::VertexFormat>( InternalPointer->GetFVF() );
\r
435 int BaseMesh::BytesPerVertex::get()
\r
437 return InternalPointer->GetNumBytesPerVertex();
\r
440 MeshFlags BaseMesh::CreationOptions::get()
\r
442 return static_cast<MeshFlags>( InternalPointer->GetOptions() );
\r