Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
Imports System.Drawing
Public class DRend
    
Dim Dev as Device
    
Public TextureDirPath 
As String
    dim Mdl as AMesh
    dim Camera as Matrix
    
Dim sh 
As IntPtr
    
Dim pp 
As PresentParameters = 
New PresentParameters
    
Public Class PresentOptions
        
Public Fullscreen 
As Boolean
        Public SWidth 
As Integer
        Public SHeight 
As Integer
        Public FrameLimit 
As Boolean
        Public Sub New()
            Fullscreen = 
True
            SWidth = Screen.AllScreens(0).Bounds.Width
            SHeight = Screen.AllScreens(0).Bounds.Height
            FrameLimit = 
False
        End Sub
    End Class
    Public sub LoadModel(FileName as 
String)
        Mdl = 
New AMesh(FileName, dev, pp, TextureDirPath, 
Me)
    
End sub
    
Public Sub _3D_Init(
ByRef Handle 
As IntPtr, 
ByVal Args 
As PresentOptions)
        sh = Handle
        pp.SwapEffect = SwapEffect.Discard
        
If Args.FrameLimit 
Then pp.PresentationInterval = PresentInterval.Default 
Else pp.PresentationInterval = PresentInterval.Immediate
        
Dim current 
As Format = Manager.Adapters(0).CurrentDisplayMode.Format
        
If Manager.CheckDeviceType(0, DeviceType.Hardware, current, current, 
False) 
Then
            pp.BackBufferWidth = Args.SWidth
            pp.BackBufferHeight = Args.SHeight
            
If Args.Fullscreen 
Then
                pp.Windowed = 
False
                pp.BackBufferFormat = current
                pp.BackBufferCount = 1
            
Else
                pp.Windowed = 
True
            End If
            pp.AutoDepthStencilFormat = DepthFormat.D24S8
            pp.EnableAutoDepthStencil = 
True
        Else
            pp.Windowed = 
True
        End If
        Dim hardware 
As Caps = Manager.GetDeviceCaps(0, DeviceType.Hardware)
        
If hardware.MaxVertexBlendMatrices >= 4 
Then
            Dim fl 
As CreateFlags = CreateFlags.SoftwareVertexProcessing
            
If hardware.DeviceCaps.SupportsHardwareTransformAndLight 
Then fl = CreateFlags.HardwareVertexProcessing
            
If hardware.DeviceCaps.SupportsPureDevice 
Then fl = fl 
Or CreateFlags.PureDevice            
            dev = 
New Device(0, DeviceType.Hardware, sh, fl, pp)
        
Else
            dev = 
New Device(0, DeviceType.Reference, sh, CreateFlags.SoftwareVertexProcessing, pp)
        
End If
        dev.RenderState.CullMode = Cull.CounterClockwise
        dev.RenderState.Ambient = Color.White
        dev.RenderState.Lighting = 
False
        If pp.Windowed 
Then AddHandler dev.DeviceResizing, 
AddressOf DevResize
        
AddHandler dev.DeviceReset, 
AddressOf DevReset
        Utils.Timer(DirectXTimer.Start)
        dev.Transform.Projection = Matrix.PerspectiveFovLH(Math.Pi/4, dev.DisplayMode.Width / dev.DisplayMode.Height, 0.1, 10000)
        dev.Transform.View = Matrix.Identity
    
End Sub
    Public sub Represent
        TimeEnd = Utils.Timer(DirectXTimer.GetElapsedTime)
        dev.Transform.World = Matrix.Identity
        dev.Transform.View = Camera
        dev.Clear(ClearFlags.Target 
Or ClearFlags.ZBuffer, Color.Black, 1.0F, 1.0F)
        dev.BeginScene()
        Mdl.ProcessNextFrame(dev,TimeEnd,0,0,0,0,0,0)
        Mdl.DrawFrame(Mdl.rootFrame.FrameHierarchy, dev)
        dev.EndScene()
        dev.Present()
    
End sub
    
Private Sub DevReset(
ByVal sender 
As Object, 
ByVal e 
As EventArgs)
        
'
        ' дЕИЯРБХЪ ОПХ ЯАПНЯЕ СЯРПНИЯРБЮ
        '
    End Sub
    Private Sub DevResize(
ByVal sender 
As Object, 
ByVal e 
As System.ComponentModel.CancelEventArgs)
        e.Cancel = 
True
    End Sub
Class AMesh
        
Dim R 
As Single
        Dim modPath 
As String
        Public PD 
As Double
        Dim MDevice 
As Device
        
Public app 
As DRend
        
Public ReadOnly Property Radius() 
As Single
            Get
                Return R
            
End Get
        End Property
        Public Sub New(
ByVal File 
As String, 
ByRef MyDevice 
As Device, 
ByVal presentParams 
As PresentParameters, 
ByVal texPath 
As String, 
ByRef par 
As DRend)
            modPath = texPath
            app = par
            MDevice = MyDevice
            CreateAnimation(File, presentParams, MyDevice)
            PD = rootFrame.AnimationController.GetTrackAnimationSet(0).Period
        
End Sub
        Public Sub ProcessNextFrame(
ByRef dev 
As Device, 
ByVal ETime 
As Single, 
ByVal XAng 
As Single, 
ByVal YAng 
As Single, 
ByVal ZAng 
As Single, 
ByVal XLoc 
As Single, 
ByVal YLoc 
As Single, 
ByVal ZLoc 
As Single)
            dev.Transform.World = Matrix.Multiply(Matrix.RotationYawPitchRoll(XAng, YAng, ZAng), Matrix.Translation(
New Vector3(XLoc, YLoc, ZLoc)))
            
If Not (rootFrame.AnimationController 
Is Nothing) 
Then
                rootFrame.AnimationController.AdvanceTime(ETime, 
Nothing)
                UpdateFrameMatrices(rootFrame.FrameHierarchy, dev.Transform.World)
            
End If
        End Sub
        Public Sub ProcessUpdate(
ByRef dev 
As Device, 
ByVal XAng 
As Single, 
ByVal YAng 
As Single, 
ByVal ZAng 
As Single, 
ByVal XLoc 
As Single, 
ByVal YLoc 
As Single, 
ByVal ZLoc 
As Single)
            dev.Transform.World = Matrix.Multiply(Matrix.RotationYawPitchRoll(XAng, YAng, ZAng), Matrix.Translation(
New Vector3(XLoc, YLoc, ZLoc)))
            UpdateFrameMatrices(rootFrame.FrameHierarchy, dev.Transform.World)
        
End Sub
        Public Function GetPosition() 
As Double
            Return rootFrame.AnimationController.GetTrackDescription(0).Position
        
End Function
        Public Sub ProcessZeroFrame()
            rootFrame.AnimationController.SetTrackPosition(0, 0)
        
End Sub
        Public Sub ProcessUserFrame(
ByVal ATime 
As Double)
            rootFrame.AnimationController.SetTrackPosition(0, PD * ATime)
        
End Sub
        Public Sub ProcessAbsoluteFrame(
ByVal ATime 
As Double)
            rootFrame.AnimationController.SetTrackPosition(0, ATime)
        
End Sub
        Public Sub DrawFrame(
ByVal frame 
As FrameDerived, 
ByRef dev 
As Device)
            
Dim mesh 
As MeshContainerDerived = frame.MeshContainer
            
While Not (mesh 
Is Nothing)
                

rawMeshContainer(mesh, frame, dev)
                mesh = mesh.NextContainer
            
End While
            If Not (frame.FrameSibling 
Is Nothing) 
Then
                

rawFrame(frame.FrameSibling, dev)
            
End If
            If Not (frame.FrameFirstChild 
Is Nothing) 
Then
                

rawFrame(frame.FrameFirstChild, dev)
            
End If
        End Sub
        Private Sub DrawMeshContainer(
ByVal mesh 
As MeshContainerDerived, 
ByVal frame 
As FrameDerived, 
ByRef dev 
As Device)
            
If Not (mesh.SkinInformation 
Is Nothing) 
Then
                If mesh.NumberInfluences = 1 
Then
                    dev.RenderState.VertexBlend = VertexBlend.ZeroWeights
                
Else
                    dev.RenderState.VertexBlend = CType(mesh.NumberInfluences - 1, VertexBlend)
                
End If
                If mesh.NumberInfluences > 0 
Then
                    dev.RenderState.IndexedVertexBlendEnable = 
True
                End If
                Dim bones 
As BoneCombination() = mesh.GetBones()
                
Dim iAttrib 
As Integer
                Dim t 
As Integer
                For iAttrib = 0 
To mesh.NumberAttributes - 1
                    
Dim iPaletteEntry 
As Integer
                    For iPaletteEntry = 0 
To mesh.NumberPaletteEntries - 1
                        
Dim iMatrixIndex 
As Integer = bones(iAttrib).BoneId(iPaletteEntry)
                        
If iMatrixIndex <> -1 
Then
                            dev.Transform.SetWorldMatrixByIndex(iPaletteEntry, objectMatrix)
                        
End If
                    Next iPaletteEntry
                    
For t = 0 
To numPasses - 1
                        dev.Material = mesh.GetMaterials()(bones(iAttrib).AttribId).Material3D
                        dev.SetTexture(0, mesh.GetTextures()(bones(iAttrib).AttribId))
                        mesh.MeshData.Mesh.DrawSubset(iAttrib)
                    
Next
                Next iAttrib
            
Else
                dev.Transform.World = frame.CombinedTransformationMatrix
                
Dim t 
As Integer
                Dim mtrl 
As ExtendedMaterial() = mesh.GetMaterials()
                
Dim iMaterial 
As Integer
                    For iMaterial = 0 
To mtrl.Length - 1
                        dev.Material = mtrl(iMaterial).Material3D
                        dev.SetTexture(0, mesh.GetTextures()(iMaterial))
                        mesh.MeshData.Mesh.DrawSubset(iMaterial)
                    
Next iMaterial
            
End If
        End Sub
        Private Sub UpdateFrameMatrices(
ByVal frame 
As FrameDerived, 
ByVal parentMatrix 
As Matrix)
            frame.CombinedTransformationMatrix = Matrix.Multiply(frame.TransformationMatrix, parentMatrix)
            
If Not (frame.FrameSibling 
Is Nothing) 
Then
                UpdateFrameMatrices(frame.FrameSibling, parentMatrix)
            
End If
            If Not (frame.FrameFirstChild 
Is Nothing) 
Then
                UpdateFrameMatrices(frame.FrameFirstChild, frame.CombinedTransformationMatrix)
            
End If
        End Sub
        Public rootFrame 
As AnimationRootFrame
        
Private Overloads Sub SetupBoneMatrices(
ByVal frame 
As FrameDerived)
            
If Not (frame.MeshContainer 
Is Nothing) 
Then
                SetupBoneMatrices(CType(frame.MeshContainer, MeshContainerDerived))
            
End If
            If Not (frame.FrameSibling 
Is Nothing) 
Then
                SetupBoneMatrices(CType(frame.FrameSibling, FrameDerived))
            
End If
            If Not (frame.FrameFirstChild 
Is Nothing) 
Then
                SetupBoneMatrices(CType(frame.FrameFirstChild, FrameDerived))
            
End If
        End Sub
        Private Overloads Sub SetupBoneMatrices(
ByVal mesh 
As MeshContainerDerived)
            
If Not (mesh.SkinInformation 
Is Nothing) 
Then
                Dim numBones 
As Integer = mesh.SkinInformation.NumberBones
                
Dim frameMatrices(numBones) 
As FrameDerived
                
Dim i 
As Integer
                For i = 0 
To numBones - 1
                    
Dim frame 
As FrameDerived = CType(frame.Find(rootFrame.FrameHierarchy, mesh.SkinInformation.GetBoneName(i)), FrameDerived)
                    
If frame 
Is Nothing Then
                        Throw New ArgumentException
                    
End If
                    frameMatrices(i) = frame
                
Next i
                mesh.SetFrames(frameMatrices)
            
End If
        End Sub
        Private Sub CreateAnimation(
ByVal file 
As String, 
ByVal presentParams 
As PresentParameters, 
ByVal dev 
As Device)
            
Dim alloc 
As New AllocateHierarchyDerived(
Me, modPath)
            
Dim strm 
As New IO.FileStream(file, IO.FileMode.
Open)
            rootFrame = Mesh.LoadHierarchy(strm, strm.Length, MeshFlags.Managed, dev, alloc, 
Nothing)
            strm.Close()
            R = Frame.CalculateBoundingSphere(rootFrame.FrameHierarchy, 
New Vector3)
            SetupBoneMatrices(CType(rootFrame.FrameHierarchy, FrameDerived))
        
End Sub
        Public Sub GenerateSkinnedMesh(
ByVal mesh 
As MeshContainerDerived)
            
If mesh.SkinInformation 
Is Nothing Then
                Throw New ArgumentException
            
End If
            Dim numMaxFaceInfl 
As Integer
            Dim flags 
As MeshFlags = MeshFlags.OptimizeVertexCache
            
Dim m 
As MeshData = mesh.MeshData
            
Dim ib 
As IndexBuffer = m.Mesh.IndexBuffer
            
Try
                numMaxFaceInfl = mesh.SkinInformation.GetMaxFaceInfluences(ib, m.Mesh.NumberFaces)
            
Finally
                ib.Dispose()
            
End Try
            numMaxFaceInfl = Fix(Math.Min(numMaxFaceInfl, 12))
            
If MDevice.DeviceCaps.MaxVertexBlendMatrixIndex + 1 >= numMaxFaceInfl 
Then
                mesh.NumberPaletteEntries = Fix(Math.Min((MDevice.DeviceCaps.MaxVertexBlendMatrixIndex + 1) / 2, mesh.SkinInformation.NumberBones))
                flags = flags 
Or MeshFlags.Managed
            
End If
            Dim bones() 
As BoneCombination
            
Dim numInfl 
As Integer
            m.Mesh = mesh.SkinInformation.ConvertToIndexedBlendedMesh(m.Mesh, flags, mesh.GetAdjacencyStream(), mesh.NumberPaletteEntries, numInfl, bones)
            mesh.SetBones(bones)
            mesh.NumberInfluences = numInfl
            mesh.NumberAttributes = bones.Length
            mesh.MeshData = m
        
End Sub
        '
        ' бЯОНЛНЦЮРЕКЭМШЕ ЙКЮЯЯШ ДКЪ ЛНДЕКХПНБЮМХЪ ЮМХЛЮЖХХ
        '
        Public Class FrameDerived
            
Inherits Frame
            
Private combined 
As Matrix = Matrix.Identity
            
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 MeshContainerDerived
            
Inherits MeshContainer
            
Private meshTextures 
As Texture() = 
Nothing
            Private numAttr 
As Integer = 0
            
Private numInfl 
As Integer = 0
            
Private bones() 
As BoneCombination
            
Private frameMatrices() 
As FrameDerived
            
Private offsetMatrices() 
As Matrix
            
Private numPal 
As Integer = 0
            
Public Property NumberPaletteEntries() 
As Integer
                Get
                    Return numPal
                
End Get
                Set(
ByVal Value 
As Integer)
                    numPal = Value
                
End Set
            End Property
            Public Function GetTextures() 
As Texture()
                
Return meshTextures
            
End Function
            Public Sub SetTextures(
ByVal textures() 
As Texture)
                meshTextures = textures
            
End Sub
            Public Function GetBones() 
As BoneCombination()
                
Return bones
            
End Function
            Public Sub SetBones(
ByVal b() 
As BoneCombination)
                bones = b
            
End Sub
            Public Function GetFrames() 
As FrameDerived()
                
Return frameMatrices
            
End Function
            Public Sub SetFrames(
ByVal frames() 
As FrameDerived)
                frameMatrices = frames
            
End Sub
            Public Function GetOffsetMatrices() 
As Matrix()
                
Return offsetMatrices
            
End Function
            Public Sub SetOffsetMatrices(
ByVal matrices() 
As Matrix)
                offsetMatrices = matrices
            
End Sub
            Public Property NumberAttributes() 
As Integer
                Get
                    Return numAttr
                
End Get
                Set(
ByVal Value 
As Integer)
                    numAttr = Value
                
End Set
            End Property
            Public Property NumberInfluences() 
As Integer
                Get
                    Return numInfl
                
End Get
                Set(
ByVal Value 
As Integer)
                    numInfl = Value
                
End Set
            End Property
        End Class
        Public Class AllocateHierarchyDerived
            
Inherits AllocateHierarchy
            
Private app 
As AMesh = 
Nothing
            Dim MP 
As String
            Public Sub New(
ByVal parent 
As AMesh, 
ByVal mPath 
As String)
                
MyBase.
New()
                app = parent
                MP = mPath
            
End Sub
            Public Overrides Function CreateFrame(
ByVal name 
As String) 
As Frame
                
Dim frame 
As New FrameDerived
                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.None 
Then
                    Throw New ArgumentException
                
End If
                Dim mesh 
As New MeshContainerDerived
                mesh.
Name = name
                
Dim numFaces 
As Integer = meshData.Mesh.NumberFaces
                
Dim dev 
As Device = meshData.Mesh.Device
                
If (meshData.Mesh.VertexFormat 
And VertexFormats.Normal) = 0 
Then
                    Dim tempMesh 
As Mesh = meshData.Mesh.Clone(meshData.Mesh.Options.Value, meshData.Mesh.VertexFormat 
Or VertexFormats.Normal, dev)
                    meshData.Mesh = tempMesh
                    meshData.Mesh.ComputeNormals()
                
End If
                Dim i 
As Integer
                mesh.SetMaterials(materials)
                mesh.SetAdjacency(adjacency)
                
Dim meshTextures(materials.Length - 1) 
As Texture
                
For i = 0 
To materials.Length - 1
                    
If Not (materials(i).TextureFilename 
Is Nothing) 
Then
                        meshTextures(i) = TextureLoader.FromFile(dev, MP & "\" & IO.Path.GetFileName(materials(i).TextureFilename))
                    
End If
                Next i
                mesh.SetTextures(meshTextures)
                mesh.MeshData = meshData
                
If Not (skinInfo 
Is Nothing) 
Then
                    mesh.SkinInformation = skinInfo
                    
Dim numBones 
As Integer = skinInfo.NumberBones
                    
Dim offsetMatrices(numBones) 
As Matrix
                    
For i = 0 
To numBones - 1
                        offsetMatrices(i) = skinInfo.GetBoneOffsetMatrix(i)
                    
Next i
                    mesh.SetOffsetMatrices(offsetMatrices)
                    app.GenerateSkinnedMesh(mesh)
                
End If
                Return mesh
            
End Function
        End Class
    End Class
End class