Imports System.IO
Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
Imports Direct3D = Microsoft.DirectX.Direct3D
Namespace Animation
Public Class AnimationClass
Implements IDisposable
Private Device As Device = Nothing
Public FileName As String = Nothing
Private WorldPosition As WorldPosition
' Fields
'Private camera As ModelViewerCamera = New ModelViewerCamera
Private Const ChangeDevice As Integer = 4
Private Shared ReadOnly Color2 As ColorValue = New ColorValue(0.25!, 0.25!, 0.25!, 1.0!)
Private effect As effect = Nothing
'Private hud As Dialog = Nothing
Private isHelpShowing As Boolean = False
Private objectCenter As Vector3
Private objectRadius As Single = 0.0F
Private rootFrame As AnimationRootFrame
'Private sampleFramework As Framework = Nothing
Private statsFont As Font = Nothing
Private textSprite As Sprite = Nothing
Private Const ToggleFullscreen As Integer = 1
Private Const ToggleReference As Integer = 3
Private Shared ReadOnly WhiteColor As ColorValue = New ColorValue(1.0!, 1.0!, 1.0!, 1.0!)
Private SystemMemoryMesh As Mesh = Nothing ' SysMem Mesh, Lives Through Resize
Private LocalMemoryMesh As Mesh = Nothing ' Local Mesh, Rebuilt On Resize
Private IsUsingMeshMaterials As Boolean = True
Private SystemMemoryVertexBuffer As VertexBuffer = Nothing
Private LocalMemoryVertexBuffer As VertexBuffer = Nothing
Private SystemMemoryIndexBuffer As IndexBuffer = Nothing
Private LocalMemoryIndexBuffer As IndexBuffer = Nothing
Private LocalBoundingSphere As Sphere
Private Materials As Direct3D.Material() = Nothing
Public Textures As Texture() = Nothing
Public Property Position() As WorldPosition
Get
Return WorldPosition
End Get
Set(ByVal Value As WorldPosition)
WorldPosition = Value
End Set
End Property
Private ActualVelocity As Single
Public Property Velocity() As Single
Get
Return ActualVelocity
End Get
Set(ByVal Value As Single)
ActualVelocity = Value
End Set
End Property
'/ <Summary>
'/ The System Memory Mesh
'/ </Summary>
Public ReadOnly Property SystemMesh() As Mesh
Get
Return SystemMemoryMesh
End Get
End Property
'/ <Summary>
'/ The Local Memory Mesh
'/ </Summary>
Public ReadOnly Property LocalMesh() As Mesh
Get
Return LocalMemoryMesh
End Get
End Property
'/ <Summary>
'/ Should We Use The Mesh Materials
'/ </Summary>
Public WriteOnly Property IsUsingMaterials() As Boolean
Set(ByVal Value As Boolean)
IsUsingMeshMaterials = Value
End Set
End Property
'/<Summary>
'/The Bounding Sphere
'/</Summary>
Public ReadOnly Property BoundingSphere() As Sphere
Get
Return LocalBoundingSphere
End Get
End Property
Public Sub New(ByVal Filename As String)
Filename = Filename
End Sub 'New
Public Sub New()
MyClass.New("AnimPositonedMesh")
End Sub 'New
Public Sub New(ByVal Device As Device, ByVal Filename As String)
CreateAnim(Device, Filename)
End Sub 'New
Private Sub DrawFrame(ByVal frame As AnimationFrame)
Dim container As AnimationMeshContainer = CType(frame.MeshContainer, AnimationMeshContainer)
Do While (Not container Is Nothing)
Me.DrawMeshContainer(container, frame)
container = CType(container.NextContainer, AnimationMeshContainer)
Loop
If (Not frame.FrameSibling Is Nothing) Then
Me.DrawFrame(CType(frame.FrameSibling, AnimationFrame))
End If
If (Not frame.FrameFirstChild Is Nothing) Then
Me.DrawFrame(CType(frame.FrameFirstChild, AnimationFrame))
End If
End Sub
Private Sub DrawMeshContainer(ByVal mesh As AnimationMeshContainer, ByVal parent As AnimationFrame)
Dim device As Device = Me.Device
If (Not mesh.SkinInformation Is Nothing) Then
If (mesh.NumberInfluences = 1) Then
device.RenderState.VertexBlend = VertexBlend.ZeroWeights
Else
device.RenderState.VertexBlend = CType((mesh.NumberInfluences - 1), VertexBlend)
End If
If (mesh.NumberInfluences > 0) Then
device.RenderState.IndexedVertexBlendEnable = True
End If
Dim bones As BoneCombination() = mesh.GetBones
Dim i As Integer
For i = 0 To mesh.NumberAttributes - 1
Dim j As Integer
For j = 0 To mesh.NumberPaletteEntries - 1
Dim index As Integer = bones(i).BoneId(j)
If (index <> -1) Then
device.Transform.SetWorldMatrixByIndex(j, Matrix.Multiply(mesh.GetOffsetMatrices(index), mesh.GetFrames(index).CombinedTransformationMatrix))
End If
Next j
device.Material = mesh.GetMaterials(bones(i).AttributeId).Material3D
device.SetTexture(0, mesh.GetTextures(bones(i).AttributeId))
mesh.MeshData.Mesh.DrawSubset(i)
Next i
Else
device.RenderState.VertexBlend = VertexBlend.Disable
device.Transform.World = parent.CombinedTransformationMatrix
Dim materials As ExtendedMaterial() = mesh.GetMaterials
Dim k As Integer
For k = 0 To materials.Length - 1
device.Material = materials(k).Material3D
device.SetTexture(0, mesh.GetTextures(k))
mesh.MeshData.Mesh.DrawSubset(k)
Next k
End If
End Sub
Public Sub GenerateSkinnedMesh(ByVal mesh As AnimationMeshContainer)
Dim maxFaceInfluences As Integer
If (mesh.SkinInformation Is Nothing) Then
Throw New ArgumentException
End If
Dim optimizeVertexCache As MeshFlags = MeshFlags.OptimizeVertexCache
Dim deviceCaps As Caps '= Me.sampleFramework.DeviceCaps
If deviceCaps.VertexShaderVersion.CompareTo(New Version(1, 1)) >= 0 Then
optimizeVertexCache = (optimizeVertexCache Or MeshFlags.Managed)
Else
optimizeVertexCache = (optimizeVertexCache Or MeshFlags.SystemMemory)
End If
Dim buffer As IndexBuffer = mesh.MeshData.Mesh.IndexBuffer
Try
maxFaceInfluences = mesh.SkinInformation.GetMaxFaceInfluences(buffer, mesh.MeshData.Mesh.NumberFaces)
Finally
CType(buffer, IDisposable).Dispose()
End Try
maxFaceInfluences = Math.Min(maxFaceInfluences, 12)
If ((deviceCaps.MaxVertexBlendMatrixIndex + 1) >= maxFaceInfluences) Then
mesh.NumberPaletteEntries = Math.Min(((deviceCaps.MaxVertexBlendMatrixIndex + 1) / 2), mesh.SkinInformation.NumberBones)
optimizeVertexCache = (optimizeVertexCache Or MeshFlags.Managed)
End If
Dim maxFaceInfluence As Integer = 0
Dim boneCombinationTable As BoneCombination() = Nothing
Dim meshData As MeshData = mesh.MeshData
meshData.Mesh = mesh.SkinInformation.ConvertToIndexedBlendedMesh(meshData.Mesh, optimizeVertexCache, mesh.GetAdjacencyStream, mesh.NumberPaletteEntries, maxFaceInfluence, boneCombinationTable)
mesh.NumberInfluences = maxFaceInfluence
mesh.SetBones(boneCombinationTable)
mesh.NumberAttributes = boneCombinationTable.Length
mesh.MeshData = meshData
End Sub
Public Sub CreateAnim(ByVal Device As Device, ByVal Filename As String)
WorldPosition = New WorldPosition
Dim AdjacencyBuffer As GraphicsStream
Dim Mat() As ExtendedMaterial
Me.Device = Device
If Not (Device Is Nothing) Then
AddHandler Device.DeviceLost, AddressOf Me.InvalidateDeviceObjects
AddHandler Device.Disposing, AddressOf Me.InvalidateDeviceObjects
AddHandler Device.DeviceReset, AddressOf Me.RestoreDeviceObjects
End If
Dim alloc As New AnimationAllocation(Me)
Filename = MediaUtilities.FindFile(Filename)
'SystemMemoryMesh = Mesh.FromFile(Filename, MeshFlags.SystemMemory, Device, AdjacencyBuffer, Mat)
rootFrame = Mesh.LoadHierarchyFromFile(Filename, MeshFlags.SystemMemory, Device, alloc, Nothing)
Dim TempMesh As Mesh = Nothing
Dim ErrorString As String
TempMesh = Mesh.Clean(CleanType.Optimization, SystemMemoryMesh, AdjacencyBuffer, AdjacencyBuffer, ErrorString)
If Not TempMesh.Equals(SystemMemoryMesh) Then
SystemMemoryMesh.Dispose()
SystemMemoryMesh = TempMesh
End If
' Optimize The Mesh For Performance
Dim Flags As MeshFlags = MeshFlags.OptimizeCompact Or MeshFlags.OptimizeAttributeSort Or MeshFlags.OptimizeVertexCache
SystemMemoryMesh.OptimizeInPlace(Flags, AdjacencyBuffer)
AdjacencyBuffer.Close()
AdjacencyBuffer = Nothing
' Setup Bounding Volumes
Dim Vb As VertexBuffer = SystemMemoryMesh.VertexBuffer
Dim VertexData As GraphicsStream = Vb.Lock(0, 0, LockFlags.ReadOnly)
LocalBoundingSphere.Radius = Geometry.ComputeBoundingSphere(VertexData, SystemMemoryMesh.NumberVertices, SystemMemoryMesh.VertexFormat, BoundingSphere.CenterPoint)
Vb.Unlock()
Vb.Dispose()
Textures = New Texture(Mat.Length) {}
Materials = New Direct3D.Material(Mat.Length) {}
Dim I As Integer
For I = 0 To Mat.Length - 1
Materials(I) = Mat(I).Material3D
' Set The Ambient Color For The Material (D3DX Does Not Do This)
Materials(I).Ambient = Materials(I).Diffuse
If Not (Mat(I).TextureFilename Is Nothing) Then
' Create The Texture
Textures(I) = TextureLoader.FromFile(Device, MediaUtilities.FindFile(Mat(I).TextureFilename))
End If
Next I
'' rootFrame = SystemMemoryMesh.LoadHierarchyFromFile(Filename, MeshFlags.Managed, Device, alloc, Nothing)
' Restore the folder
' Calculate the center and radius of a bounding sphere
objectRadius = Frame.CalculateBoundingSphere(rootFrame.FrameHierarchy, objectCenter)
' Setup the matrices for animation
SetupBoneMatrices(CType(rootFrame.FrameHierarchy, AnimationFrame))
RestoreDeviceObjects(Device, Nothing)
End Sub
Public Sub SetVertexFormat(ByVal Device As Device, ByVal Format As VertexFormats)
Dim PTempSysMemMesh As Mesh = Nothing
Dim PTempLocalMesh As Mesh = Nothing
If Not (SystemMemoryMesh Is Nothing) Then
PTempSysMemMesh = SystemMemoryMesh.Clone(MeshFlags.SystemMemory, Format, Device)
End If
If Not (LocalMemoryMesh Is Nothing) Then
Try
PTempLocalMesh = LocalMemoryMesh.Clone(0, Format, Device)
Catch E As Exception
PTempSysMemMesh.Dispose()
PTempSysMemMesh = Nothing
Throw E
End Try
End If
If Not (SystemMemoryMesh Is Nothing) Then
SystemMemoryMesh.Dispose()
End If
SystemMemoryMesh = Nothing
If Not (LocalMemoryMesh Is Nothing) Then
LocalMemoryMesh.Dispose()
End If
LocalMemoryMesh = Nothing
' Clean Up Any Vertex/Index Buffers
DisposeLocalBuffers(True, True)
If Not (PTempSysMemMesh Is Nothing) Then
SystemMemoryMesh = PTempSysMemMesh
End If
If Not (PTempLocalMesh Is Nothing) Then
LocalMemoryMesh = PTempLocalMesh
End If
' Compute Normals In Case The Meshes Have Them
If Not (SystemMemoryMesh Is Nothing) Then
SystemMemoryMesh.ComputeNormals()
End If
If Not (LocalMemoryMesh Is Nothing) Then
LocalMemoryMesh.ComputeNormals()
End If
End Sub 'SetVertexFormat
Public Sub RestoreDeviceObjects(ByVal Sender As Object, ByVal E As EventArgs)
If SystemMemoryMesh.Equals(Nothing) Then
Throw New ArgumentException
End If
Dim Device As Device = CType(Sender, Device)
' Make A Local Memory Version Of The Mesh.
LocalMemoryMesh = SystemMemoryMesh.Clone(MeshFlags.VbWriteOnly Or MeshFlags.IbWriteOnly, SystemMemoryMesh.VertexFormat, Device)
' Clean Up Any Vertex/Index Buffers
DisposeLocalBuffers(False, True)
End Sub 'RestoreDeviceObjects
Public Sub InvalidateDeviceObjects(ByVal Sender As Object, ByVal E As EventArgs)
If Not (LocalMemoryMesh Is Nothing) Then
LocalMemoryMesh.Dispose()
End If
LocalMemoryMesh = Nothing
' Clean Up Any Vertex/Index Buffers
DisposeLocalBuffers(False, True)
End Sub 'InvalidateDeviceObjects
Public Sub OnFrameMove(ByVal device As Device, ByVal appTime As Double, ByVal elapsedTime As Single)
'Me.camera.FrameMove(elapsedTime)
Dim parentMatrix As Matrix ' = (Matrix.Translation(Vector3.op_UnaryNegation(Me.objectCenter)) * Me.camera.WorldMatrix)
device.Transform.World = parentMatrix
If (elapsedTime > 0.0!) Then
If (Not Me.rootFrame.AnimationController Is Nothing) Then
Me.rootFrame.AnimationController.AdvanceTime(CDbl(elapsedTime))
End If
Me.UpdateFrameMatrices(CType(Me.rootFrame.FrameHierarchy, AnimationFrame), parentMatrix)
End If
End Sub
Public ReadOnly Property SystemVertexBuffer() As VertexBuffer
Get
If Not (SystemMemoryVertexBuffer Is Nothing) Then
Return SystemMemoryVertexBuffer
End If
If SystemMemoryMesh Is Nothing Then
Return Nothing
End If
SystemMemoryVertexBuffer = SystemMemoryMesh.VertexBuffer
Return SystemMemoryVertexBuffer
End Get
End Property
'/ <Summary>
'/ Get The Vertex Buffer Assigned To The Local Mesh
'/ </Summary>
Public ReadOnly Property LocalVertexBuffer() As VertexBuffer
Get
If Not (LocalMemoryVertexBuffer Is Nothing) Then
Return LocalMemoryVertexBuffer
End If
If LocalMemoryMesh Is Nothing Then
Return Nothing
End If
LocalMemoryVertexBuffer = LocalMemoryMesh.VertexBuffer
Return LocalMemoryVertexBuffer
End Get
End Property
'/ <Summary>
'/ Get The Index Buffer Assigned To The System Mesh
'/ </Summary>
Public ReadOnly Property SystemIndexBuffer() As IndexBuffer
Get
If Not (SystemMemoryIndexBuffer Is Nothing) Then
Return SystemMemoryIndexBuffer
End If
If SystemMemoryMesh Is Nothing Then
Return Nothing
End If
SystemMemoryIndexBuffer = SystemMemoryMesh.IndexBuffer
Return SystemMemoryIndexBuffer
End Get
End Property
'/ <Summary>
'/ Get The Index Buffer Assigned To The Local Mesh
'/ </Summary>
Public ReadOnly Property LocalIndexBuffer() As IndexBuffer
Get
If Not (LocalMemoryIndexBuffer Is Nothing) Then
Return LocalMemoryIndexBuffer
End If
If LocalMemoryMesh Is Nothing Then
Return Nothing
End If
LocalMemoryIndexBuffer = LocalMemoryMesh.IndexBuffer
Return LocalMemoryIndexBuffer
End Get
End Property
'/ <Summary>
'/ Clean Up Any Resources
'/ </Summary>
Public Overloads Sub Dispose() Implements IDisposable.Dispose
If Not (Textures Is Nothing) Then
Dim I As Integer
For I = 0 To Textures.Length - 1
If Not (Textures(I) Is Nothing) Then
Textures(I) = Nothing
End If
Next I
Textures = Nothing
End If
' Clean Up Any Vertex/Index Buffers
DisposeLocalBuffers(True, True)
' Clean Up Any Memory
If Not (SystemMemoryMesh Is Nothing) Then
SystemMemoryMesh.Dispose()
End If
SystemMemoryMesh = Nothing
' In Case The Finalizer Hasn'T Been Called Yet.
GC.SuppressFinalize(Me)
End Sub 'Dispose
Public Overloads Sub Render(ByVal CanDrawOpaque As Boolean, ByVal CanDrawAlpha As Boolean)
If LocalMemoryMesh Is Nothing Then
Throw New ArgumentException
End If
' Set The World Transform
Device.Transform.World = WorldPosition.WorldMatrix
Dim Rs As RenderStateManager = Device.RenderState
' Frist, Draw The Subsets Without Alpha
If CanDrawOpaque Then
Dim I As Integer
For I = 0 To Materials.Length - 1
If IsUsingMeshMaterials Then
If CanDrawAlpha Then
If Materials(I).Diffuse.A < &HFF Then
Exit For
End If
End If
Device.Material = Materials(I)
If Not (Textures(I) Is Nothing) Then
Device.SetTexture(0, Textures(I))
Else
Device.SetTexture(0, Nothing)
End If
End If
LocalMemoryMesh.DrawSubset(I)
Next I
End If
' Then, Draw The Subsets With Alpha
If CanDrawAlpha And IsUsingMeshMaterials Then
' Enable Alpha Blending
Rs.AlphaBlendEnable = True
Rs.SourceBlend = Blend.SourceAlpha
Rs.DestinationBlend = Blend.InvSourceAlpha
Dim I As Integer
For I = 0 To Materials.Length - 1
If Materials(I).Diffuse.A = &HFF Then
Exit For
End If
' Set The Material And Texture
Device.Material = Materials(I)
If Not (Textures(I) Is Nothing) Then
Device.SetTexture(0, Textures(I))
Else
Device.SetTexture(0, Nothing)
End If
LocalMemoryMesh.DrawSubset(I)
Next I
' Restore State
Rs.AlphaBlendEnable = False
End If
'' DrawFrame(CType(rootFrame.FrameHierarchy, AnimationFrame))
End Sub 'Render
Public Overloads Sub Render()
Render(True, True)
End Sub 'Render
Private Sub DisposeLocalBuffers(ByVal SystemBuffers As Boolean, ByVal LocalBuffers As Boolean)
If SystemBuffers Then
If Not (SystemMemoryIndexBuffer Is Nothing) Then
SystemMemoryIndexBuffer.Dispose()
End If
SystemMemoryIndexBuffer = Nothing
If Not (SystemMemoryVertexBuffer Is Nothing) Then
SystemMemoryVertexBuffer.Dispose()
End If
SystemMemoryVertexBuffer = Nothing
End If
If LocalBuffers Then
If Not (LocalMemoryIndexBuffer Is Nothing) Then
LocalMemoryIndexBuffer.Dispose()
End If
LocalMemoryIndexBuffer = Nothing
If Not (LocalMemoryVertexBuffer Is Nothing) Then
LocalMemoryVertexBuffer.Dispose()
End If
LocalMemoryVertexBuffer = Nothing
End If
End Sub 'DisposeLocalBuffers
Private Sub SetupBoneMatrices(ByVal frame As AnimationFrame)
If (Not frame.MeshContainer Is Nothing) Then
Me.SetupBoneMatrices(CType(frame.MeshContainer, AnimationMeshContainer))
End If
If (Not frame.FrameSibling Is Nothing) Then
Me.SetupBoneMatrices(CType(frame.FrameSibling, AnimationFrame))
End If
If (Not frame.FrameFirstChild Is Nothing) Then
Me.SetupBoneMatrices(CType(frame.FrameFirstChild, AnimationFrame))
End If
End Sub
Private Sub SetupBoneMatrices(ByVal mesh As AnimationMeshContainer)
If (Not mesh.SkinInformation Is Nothing) Then
Dim numberBones As Integer = mesh.SkinInformation.NumberBones
Dim frames As AnimationFrame() = New AnimationFrame(numberBones - 1) {}
Dim i As Integer
For i = 0 To numberBones - 1
Dim frame As AnimationFrame = CType(frame.Find(Me.rootFrame.FrameHierarchy, mesh.SkinInformation.GetBoneName(i)), AnimationFrame)
If (frame Is Nothing) Then
Throw New InvalidOperationException("Could not find valid bone.")
End If
frames(i) = frame
Next i
mesh.SetFrames(frames)
End If
End Sub
Private Sub UpdateFrameMatrices(ByVal frame As AnimationFrame, ByVal parentMatrix As Matrix)
frame.CombinedTransformationMatrix = Matrix.Multiply(frame.TransformationMatrix, parentMatrix)
If (Not frame.FrameSibling Is Nothing) Then
Me.UpdateFrameMatrices(CType(frame.FrameSibling, AnimationFrame), parentMatrix)
End If
If (Not frame.FrameFirstChild Is Nothing) Then
Me.UpdateFrameMatrices(CType(frame.FrameFirstChild, AnimationFrame), frame.CombinedTransformationMatrix)
End If
End Sub
End Class
Public Class AnimationAllocation
Inherits AllocateHierarchy
Private parent As AnimationClass = Nothing
''' <summary>Create new instance of this class</summary>
Public Sub New(ByVal p As AnimationClass)
parent = p
End Sub
''' <summary>Create a new frame</summary>
Public Overrides Function CreateFrame(ByVal name As String) As Direct3D.Frame
Dim frame As New AnimationFrame
frame.Name = name
frame.TransformationMatrix = Matrix.Identity
frame.CombinedTransformationMatrix = Matrix.Identity
Return frame
End Function
Public Overrides Function CreateMeshContainer(ByVal name As String, ByVal meshData As MeshData, ByVal materials As ExtendedMaterial(), ByVal effectInstances As EffectInstance(), ByVal adjacency As GraphicsStream, ByVal skinInfo As SkinInformation) As MeshContainer
If (meshData.Mesh Is Nothing) Then
Throw New ArgumentException
End If
If (meshData.Mesh.VertexFormat = VertexFormats.Texture0) Then
Throw New ArgumentException
End If
Dim container As New AnimationMeshContainer
container.Name = name
Dim numberFaces As Integer = meshData.Mesh.NumberFaces
Dim device As Device = meshData.Mesh.Device
If ((meshData.Mesh.VertexFormat And VertexFormats.Normal) = VertexFormats.Texture0) Then
Dim mesh As Mesh = meshData.Mesh.Clone(meshData.Mesh.Options.Value, (meshData.Mesh.VertexFormat Or VertexFormats.Normal), device)
meshData.Mesh.Dispose()
meshData.Mesh = mesh
meshData.Mesh.ComputeNormals()
End If
container.SetMaterials(materials)
container.SetAdjacency(adjacency)
Dim textures As Texture() = New Texture(materials.Length - 1) {}
Dim i As Integer
For i = 0 To materials.Length - 1
If (Not materials(i).TextureFilename Is Nothing) Then
''textures(i) = ResourceCache.GetGlobalInstance.CreateTextureFromFile(device, materials(i).TextureFilename)
textures(i) = TextureLoader.FromFile(device, MediaUtilities.FindFile(materials(i).TextureFilename))
End If
Next i
container.SetTextures(textures)
container.MeshData = meshData
If (Not skinInfo Is Nothing) Then
container.SkinInformation = skinInfo
Dim numberBones As Integer = skinInfo.NumberBones
Dim matrices As Matrix() = New Matrix(numberBones - 1) {}
Dim j As Integer
For j = 0 To numberBones - 1
matrices(j) = skinInfo.GetBoneOffsetMatrix(j)
Next j
container.SetOffsetMatrices(matrices)
parent.GenerateSkinnedMesh(container)
End If
Return container
End Function
End Class
Public Class AnimationFrame
Inherits Frame
' Store the combined transformation matrix
Private combined As Matrix = Matrix.Identity
''' <summary>The combined transformation matrix</summary>
Public Property CombinedTransformationMatrix() As Matrix
Get
Return combined
End Get
Set(ByVal value As Matrix)
combined = value
End Set
End Property
End Class
Public Class AnimationMeshContainer
Inherits MeshContainer
' Methods
Public Function GetBones() As BoneCombination()
Return Me.bones
End Function
Public Function GetFrames() As AnimationFrame()
Return Me.frameMatrices
End Function
Public Function GetOffsetMatrices() As Matrix()
Return Me.offsetMatrices
End Function
Public Function GetTextures() As Texture()
Return Me.meshTextures
End Function
Public Sub SetBones(ByVal b As BoneCombination())
Me.bones = b
End Sub
Public Sub SetFrames(ByVal frames As AnimationFrame())
Me.frameMatrices = frames
End Sub
Public Sub SetOffsetMatrices(ByVal matrices As Matrix())
Me.offsetMatrices = matrices
End Sub
Public Sub SetTextures(ByVal textures As Texture())
Me.meshTextures = textures
End Sub
' Properties
Public Property NumberAttributes() As Integer
Get
Return Me.numAttributes
End Get
Set(ByVal value As Integer)
Me.numAttributes = value
End Set
End Property
Public Property NumberInfluences() As Integer
Get
Return Me.numInfluences
End Get
Set(ByVal value As Integer)
Me.numInfluences = value
End Set
End Property
Public Property NumberPaletteEntries() As Integer
Get
Return Me.numPalette
End Get
Set(ByVal value As Integer)
Me.numPalette = value
End Set
End Property
' Fields
Private bones As BoneCombination()
Private frameMatrices As AnimationFrame()
Private meshTextures As Texture() = Nothing
Private numAttributes As Integer = 0
Private numInfluences As Integer = 0
Private numPalette As Integer = 0
Private offsetMatrices As Matrix()
End Class
End Namespace
Animation (ConvertToIndexedBlendedMesh)
I have been trying for weeks to get animation going
and I'm going crazy.
I'm using vb.net 2003 with Dec 2004 Update.
I'm using the tiny.x model
In the code below if I use SystemMemoryMesh I can load and
display the model fine no problem, in fact I put the code to run
the static model in to make sure my paths were ok. And they are.
The problem I'm having now is with the ConvertToIndexedBlendedMesh
function. The NumberPaletteEntries and maxFaceInfluence are coming up
as 0
Now maxFaceInfluences Is showing 6841 or around there,so I'm reading
something out of the model.
The bottom line is that I can't get past ConvertToIndexedBlendedMesh
because it's catching an exception. Maybe someone who has been through this can help.
Thanks
Steve
H there, this is one way Ive done it but it's in cpp
I'll post the code you may be able to work some thing out from it
I'll post the code you may be able to work some thing out from it
BuildSkinnedMesh(LPDIRECT3DDEVICE9 Device, ID3DXMesh* mesh){ //---------------------------------------------------------------------- // First add a normal component and 2D texture coordinates component. D3DVERTEXELEMENT9 elements[64]; UINT numElements = 0; VertexPNT::Decl->GetDeclaration(elements, &numElements); ID3DXMesh* tempMesh = 0; HRESULT hr = mesh->CloneMesh(D3DXMESH_SYSTEMMEM, elements, Device, &tempMesh); if(FAILED(hr)) { MessageBox(NULL,"Failed To Clone Mesh", "SkinnedMesh::BuildSkinnedMesh()", MB_OK); } if(!HasNormals(tempMesh)) { hr = D3DXComputeNormals(tempMesh, 0); if(FAILED(hr)) { MessageBox(NULL,"Failed To ComputeNormals", "SkinnedMesh::BuildSkinnedMesh()", MB_OK); } } //---------------------------------------------------------------- // Optimize the mesh; in particular, the vertex cache. DWORD* adj = new DWORD[tempMesh->GetNumFaces()*3]; ID3DXBuffer* remap = 0; hr = tempMesh->GenerateAdjacency(EPSILON, adj); if(FAILED(hr)) { MessageBox(NULL,"Failed To Generate Adjacency", "SkinnedMesh::BuildSkinnedMesh()", MB_OK); } ID3DXMesh* optimizedTempMesh = 0; hr = tempMesh->Optimize(D3DXMESH_SYSTEMMEM | D3DXMESHOPT_VERTEXCACHE | D3DXMESHOPT_ATTRSORT, adj, 0, 0, &remap, &optimizedTempMesh); if(FAILED(hr)) { MessageBox(NULL,"Failed To Optimize Mesh", "SkinnedMesh::BuildSkinnedMesh()", MB_OK); } SAFE_RELEASE(tempMesh); // Done w/ this mesh. delete[] adj; // Done with buffer. // In the .X file (specifically the array DWORD vertexIndices[nWeights] // data member of the SkinWeights template) each bone has an array of // indices which identify the vertices of the mesh that the bone influences. // Because we have just rearranged the vertices (from optimizing), the vertex // indices of a bone are obviously incorrect (i.e., they index to vertices the bone // does not influence since we moved vertices around). In order to update a bone's // vertex indices to the vertices the bone _does_ influence, we simply need to specify // where we remapped the vertices to, so that the vertex indices can be updated to // match. This is done with the ID3DXSkinInfo::Remap method. hr = m_SkinInfo->Remap(optimizedTempMesh->GetNumVertices(), (DWORD*)remap->GetBufferPointer()); if(FAILED(hr)) { MessageBox(NULL,"Failed To Remap", "SkinnedMesh::BuildSkinnedMesh()", MB_OK); } SAFE_RELEASE(remap); // Done with remap info. //----------------------------------------------------------------------------- // The vertex format of the source mesh does not include vertex weights // nor bone index data, which are both needed for vertex blending. // Therefore, we must convert the source mesh to an "indexed-blended-mesh," // which does have the necessary data. DWORD numBoneComboEntries = 0; ID3DXBuffer* boneComboTable = 0; hr = m_SkinInfo->ConvertToIndexedBlendedMesh(optimizedTempMesh, D3DXMESH_MANAGED | D3DXMESH_WRITEONLY, MAX_NUM_BONES_SUPPORTED, 0, 0, 0, 0, &m_MaxVertInfluences, &numBoneComboEntries, &boneComboTable, &m_SkinnedMesh); if(FAILED(hr)) { MessageBox(NULL,"Failed To ConvertToIndexedBlendedMesh", "SkinnedMesh::BuildSkinnedMesh()", MB_OK); } SAFE_RELEASE(optimizedTempMesh); // Done with tempMesh. SAFE_RELEASE(boneComboTable); // Don't need bone table.#if defined(DEBUG) | defined(_DEBUG) // Output to the debug output the vertex declaration of the mesh at this point. // This is for insight only to see what exactly ConvertToIndexedBlendedMesh // does to the vertex declaration. D3DVERTEXELEMENT9 elems[MAX_FVF_DECL_SIZE]; hr = m_SkinnedMesh->GetDeclaration(elems); if(FAILED(hr)) { MessageBox(NULL,"Failed To GetDeclaraction 2", "SkinnedMesh::BuildSkinnedMesh()", MB_OK); } OutputDebugString("\nVertex Format After ConvertToIndexedBlendedMesh\n"); int i = 0; while( elems.Stream != 0xff ) // While not D3DDECL_END() { if( elems.Type == D3DDECLTYPE_FLOAT1) OutputDebugString("Type = D3DDECLTYPE_FLOAT1; "); if( elems.Type == D3DDECLTYPE_FLOAT2) OutputDebugString("Type = D3DDECLTYPE_FLOAT2; "); if( elems.Type == D3DDECLTYPE_FLOAT3) OutputDebugString("Type = D3DDECLTYPE_FLOAT3; "); if( elems.Type == D3DDECLTYPE_UBYTE4) OutputDebugString("Type = D3DDECLTYPE_UBYTE4; "); if( elems.Usage == D3DDECLUSAGE_POSITION) OutputDebugString("Usage = D3DDECLUSAGE_POSITION\n"); if( elems.Usage == D3DDECLUSAGE_BLENDWEIGHT) OutputDebugString("Usage = D3DDECLUSAGE_BLENDWEIGHT\n"); if( elems.Usage == D3DDECLUSAGE_BLENDINDICES) OutputDebugString("Usage = D3DDECLUSAGE_BLENDINDICES\n"); if( elems.Usage == D3DDECLUSAGE_NORMAL) OutputDebugString("Usage = D3DDECLUSAGE_NORMAL\n"); if( elems.Usage == D3DDECLUSAGE_TEXCOORD) OutputDebugString("Usage = D3DDECLUSAGE_TEXCOORD\n"); ++i; } #endif}
you may need to make the mesh a system mesh first. and read this bit
// In the .X file (specifically the array DWORD vertexIndices[nWeights]
// data member of the SkinWeights template) each bone has an array of
// indices which identify the vertices of the mesh that the bone influences.
This bit looks like what is wrong in your code
// Because we have just rearranged the vertices (from optimizing), the vertex
// indices of a bone are obviously incorrect (i.e., they index to vertices the bone
// does not influence since we moved vertices around). In order to update a bone's
// vertex indices to the vertices the bone _does_ influence, we simply need to specify
// where we remapped the vertices to, so that the vertex indices can be updated to
// match. This is done with the ID3DXSkinInfo::Remap method.
// In the .X file (specifically the array DWORD vertexIndices[nWeights]
// data member of the SkinWeights template) each bone has an array of
// indices which identify the vertices of the mesh that the bone influences.
This bit looks like what is wrong in your code
// Because we have just rearranged the vertices (from optimizing), the vertex
// indices of a bone are obviously incorrect (i.e., they index to vertices the bone
// does not influence since we moved vertices around). In order to update a bone's
// vertex indices to the vertices the bone _does_ influence, we simply need to specify
// where we remapped the vertices to, so that the vertex indices can be updated to
// match. This is done with the ID3DXSkinInfo::Remap method.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement