Bien, una vez vista la teoría de cómo se implementa una animación y cuales son sus partes, que existe una jerarquía en los elementos que forman el esqueleto, que también existen unas uniones entre las distintas partes del esqueleto, y todo ello mezclado con las animaciones de cada parte del esqueleto; vamos a crear en nuestro motor una animación para lo cual emplearé un tanque que amablemente ha sido realizado por Alberto Durán Vaz.
Ahora pegamos este código en la clase creada y vamos viendo qué hace cada parte.
Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
Public Class MallaAnimada(Of TMaterial As {ContenedorDeMaterial, New})
Inherits BaseDeLaAnimacion(Of TMaterial, MallaAnimadaPersonalizada(Of TMaterial))
Public Sub New(ByVal dispositivo As Device, ByVal xRuta As String, ByVal texRuta As String)
MyBase.New(dispositivo, xRuta, texRuta)
End Sub
End Class
Public MustInherit Class BaseDeLaAnimacion(Of MaterialPersonalizado As {ContenedorDeMaterial, New}, MallaPersonalizada As {BaseDeLaMallaAnimada(Of MaterialPersonalizado), New})
Private fotogramaRaiz As AnimationRootFrame
Private materialExtra As New List(Of ExtendedMaterial)()
Private listaDeMaterial As New List(Of MaterialPersonalizado)()
Public Sub New(ByVal dispositivo As Device, ByVal fichero As String, ByVal rutaDeLaTextura As String)
Try
' Creamos un almacen que alojara del objeto X cargado, mallas y materiales
Dim almacen As New AlojadorJerarquicoPersonalizado(Of MaterialPersonalizado, MallaPersonalizada)(dispositivo, Me, rutaDeLaTextura)
' Le indicamos la estructua jerarquica de la animacion de nuestro objeto X
fotogramaRaiz = Mesh.LoadHierarchyFromFile(fichero, MeshFlags.Managed, dispositivo, almacen, Nothing)
' Personalizamos los fotogramas
ConfiguraMatrizDeHuesos(DirectCast(fotogramaRaiz.FrameHierarchy, Fotograma))
Catch ex As Exception
End Try
End Sub
Friend Function MeteMaterial(ByVal dispositivo As Device, ByVal material As ExtendedMaterial, ByVal rutaDeLaTextura As String) As MaterialPersonalizado
Try
Dim i As Integer = 0
For Each mate As ExtendedMaterial In materialExtra
If mate.Equals(material) Then
Return listaDeMaterial(System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1))
End If
Next
Dim nuevoMaterial As New MaterialPersonalizado()
nuevoMaterial.inicializa(dispositivo, material, rutaDeLaTextura)
listaDeMaterial.Add(nuevoMaterial)
materialExtra.Add(material)
Return nuevoMaterial
Catch ex As Exception
End Try
End Function
Private Sub ConfiguraMatrizDeHuesos(ByVal fotograma As Fotograma)
Try
' Recursamos todas las veces que sean necesarias hasta tener convertidos todos los fotogramas
If fotograma.MeshContainer IsNot Nothing Then ConfiguraMatrizDeHuesos(DirectCast(fotograma.MeshContainer, ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada)))
If fotograma.FrameSibling IsNot Nothing Then ConfiguraMatrizDeHuesos(DirectCast(fotograma.FrameSibling, Fotograma))
If fotograma.FrameFirstChild IsNot Nothing Then ConfiguraMatrizDeHuesos(DirectCast(fotograma.FrameFirstChild, Fotograma))
Catch ex As Exception
End Try
End Sub
Private Sub ConfiguraMatrizDeHuesos(ByVal contenedorPersonalizado As ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada))
Try
' si el contenedor de mallas personalizado tiene informacion de la animacion
If contenedorPersonalizado.SkinInformation IsNot Nothing Then
Dim numhuesos_ As Integer = contenedorPersonalizado.SkinInformation.NumberBones
' tomamos todos los fotogramas del contenedor
Dim MatrizDeFotogramas As Fotograma() = New Fotograma(numhuesos_ - 1) {}
For i As Integer = 0 To numhuesos_ - 1
' Convertimos los fotogramas (Frame) al tipo de nuestra clase Fotograma
Dim fotograma As Fotograma = DirectCast(Frame.Find(fotogramaRaiz.FrameHierarchy, contenedorPersonalizado.SkinInformation.GetBoneName(i)), Fotograma)
If fotograma Is Nothing Then Throw New ArgumentException()
MatrizDeFotogramas(i) = fotograma
Next
contenedorPersonalizado.PonFotogramas(MatrizDeFotogramas)
End If
Catch ex As Exception
End Try
End Sub
Private Sub ActualizaMatrizDelFotograma(ByVal fotograma As Fotograma, ByVal matrixPadre As Matrix)
Try
' Combinamos la matriz padre del fotograma actual y su propia matriz
fotograma.MatrizTransformadaYCombinada = fotograma.TransformationMatrix * matrixPadre
' Si el fotograma actual, tiene hijos o no tiene hermanos, actualizamos de nuevo
If fotograma.FrameSibling IsNot Nothing Then ActualizaMatrizDelFotograma(DirectCast(fotograma.FrameSibling, Fotograma), matrixPadre)
If fotograma.FrameFirstChild IsNot Nothing Then ActualizaMatrizDelFotograma(DirectCast(fotograma.FrameFirstChild, Fotograma), fotograma.MatrizTransformadaYCombinada)
Catch ex As Exception
End Try
End Sub
Private Sub DibujaFotograma(ByVal dispositivo As Device, ByVal fotograma As Fotograma)
Try
Dim contenedorPersonalizado As ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada) = DirectCast(fotograma.MeshContainer, ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada))
While contenedorPersonalizado IsNot Nothing
DibujaContenedorDeMallas(dispositivo, contenedorPersonalizado)
contenedorPersonalizado = DirectCast(contenedorPersonalizado.NextContainer, ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada))
End While
' Si el fotograma actual, tiene hijos o tiene hermanos, volvemos a dibujar
If fotograma.FrameSibling IsNot Nothing Then DibujaFotograma(dispositivo, DirectCast(fotograma.FrameSibling, Fotograma))
If fotograma.FrameFirstChild IsNot Nothing Then DibujaFotograma(dispositivo, DirectCast(fotograma.FrameFirstChild, Fotograma))
Catch ex As Exception
End Try
End Sub
Private Sub DibujaContenedorDeMallas(ByVal dispositivo As Device, ByVal contenedorPersonalizado As ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada))
If contenedorPersonalizado.MallaAnimada.tieneInformacionAnimada_ Then
contenedorPersonalizado.MallaAnimada.Dibuja(dispositivo, contenedorPersonalizado.CogeFotogramas(), contenedorPersonalizado.materiales)
End If
End Sub
Public Sub Anima(ByVal tiempo As Single, ByVal MatrixGlobal As Matrix)
Try
If fotogramaRaiz.AnimationController IsNot Nothing Then
fotogramaRaiz.AnimationController.AdvanceTime(tiempo, Nothing)
End If
ActualizaMatrizDelFotograma(DirectCast(fotogramaRaiz.FrameHierarchy, Fotograma), MatrixGlobal)
Catch ex As Exception
End Try
End Sub
Public Sub Dibuja(ByVal dispositivo As Device)
Try
DibujaFotograma(dispositivo, DirectCast(Me.fotogramaRaiz.FrameHierarchy, Fotograma))
Catch ex As Exception
End Try
End Sub
Public Sub Dispose()
End Sub
End Class
Public Class MallaAnimadaPersonalizada(Of MaterialPersonalizado As {ContenedorDeMaterial, New})
Inherits BaseDeLaMallaAnimada(Of MaterialPersonalizado)
Public Overrides Sub GeneraMallaAnimada(ByVal contenedorDeLaMalla As MeshContainer)
Try
' Si hay informacion de animacion en el contenedor de la malla
If contenedorDeLaMalla.SkinInformation IsNot Nothing Then
tieneInformacionAnimada = True
Dim numhuesos_ As Integer = contenedorDeLaMalla.SkinInformation.NumberBones
matrices = New Matrix(numhuesos_ - 1) {}
For i As Integer = 0 To numhuesos_ - 1
matrices(i) = contenedorDeLaMalla.SkinInformation.GetBoneOffsetMatrix(i)
Next
' Genera Adyacencia, trianguliza la malla
Dim datosDeLaMalla As MeshData = contenedorDeLaMalla.MeshData
adia = New Integer(miMalla.NumberFaces * 3 - 1) {}
miMalla.GenerateAdjacency(0.001F, adia)
miMalla = contenedorDeLaMalla.SkinInformation.ConvertToBlendedMesh(datosDeLaMalla.Mesh, MeshFlags.Managed Or MeshFlags.OptimizeVertexCache, adia, numeroDeInfluencias, huesos)
numeroDeAtributos = huesos.Length
contenedorDeLaMalla.MeshData = datosDeLaMalla
End If
Catch ex As Exception
End Try
End Sub
Public Overrides Sub Dibuja(ByVal dispositivo As Device, ByVal frameMatrices As Fotograma(), ByVal materiales As MaterialPersonalizado())
Try
Dim atributoIdAnterior As Integer = -1
' Dibuja o renderiza el fotograma actual de nuestro objeto X
For iatributo As Integer = 0 To numeroDeAtributos_ - 1
Dim numBlend As Integer = 0
For i As Integer = 0 To numeroDeInfluencias_ - 1
If huesos(iatributo).BoneId(i) <> -1 Then numBlend = i
Next
If dispositivo.DeviceCaps.MaxVertexBlendMatrices >= numBlend + 1 Then
Dim matrices As Matrix() = matrices_
For i As Integer = 0 To numeroDeInfluencias_ - 1
Dim iMatrix As Integer = huesos(iatributo).BoneId(i)
If iMatrix <> -1 Then
Dim tempMatrix As Matrix = matrices(iMatrix) * frameMatrices(iMatrix).MatrizTransformadaYCombinada
dispositivo.Transform.SetWorldMatrixByIndex(i, tempMatrix)
End If
Next
dispositivo.RenderState.VertexBlend = DirectCast(numBlend, VertexBlend)
If (atributoIdAnterior <> huesos(iatributo).AttributeId) OrElse (atributoIdAnterior = -1) Then
atributoIdAnterior = huesos(iatributo).AttributeId
End If
materiales(huesos(iatributo).AttributeId + 1).aplica(dispositivo)
' Dibujamos la Malla
miMalla.DrawSubset(iatributo)
End If
Next
Catch ex As Exception
End Try
End Sub
Public Overrides Sub Dispose()
Try
miMalla.Dispose()
Catch ex As Exception
End Try
End Sub
End Class
Public MustInherit Class BaseDeLaMallaAnimada(Of MaterialPersonalizado As {ContenedorDeMaterial, New})
Inherits Malla(Of MaterialPersonalizado)
Protected huesos As BoneCombination()
Protected matrices As Matrix()
Protected adia As Integer() ' Buffer que contiene información sobre los bordes, caras y caras adyacentes
Protected numeroDeInfluencias As Integer
Public ReadOnly Property numeroDeInfluencias_() As Integer
Get
Return numeroDeInfluencias
End Get
End Property
Protected numeroDeAtributos As Integer
Public ReadOnly Property numeroDeAtributos_() As Integer
Get
Return numeroDeAtributos
End Get
End Property
Public ReadOnly Property matrices_() As Matrix()
Get
Return matrices
End Get
End Property
Protected tieneInformacionAnimada As Boolean
Public ReadOnly Property tieneInformacionAnimada_() As Boolean
Get
Return tieneInformacionAnimada
End Get
End Property
Public Sub Inicializa(ByVal contenedor As MeshContainer)
miMalla = contenedor.MeshData.Mesh
GeneraMallaAnimada(contenedor)
listaDeMaterial = New MaterialPersonalizado(0) {}
listaDeMaterial(0) = New MaterialPersonalizado()
End Sub
Public MustOverride Sub GeneraMallaAnimada(ByVal malla As MeshContainer)
Public MustOverride Sub Dibuja(ByVal dispositivo As Device, ByVal frameMatrices As Fotograma(), ByVal materiales As MaterialPersonalizado())
Public MustOverride Sub Dispose()
End Class
' Personalizamos la clase AllocateHierarchy
Public Class AlojadorJerarquicoPersonalizado(Of MaterialPersonalizado As {ContenedorDeMaterial, New}, MallaPersonalizada As {BaseDeLaMallaAnimada(Of MaterialPersonalizado), New})
Inherits AllocateHierarchy
Private clasePadre As BaseDeLaAnimacion(Of MaterialPersonalizado, MallaPersonalizada)
Private texRuta As String = ""
Private miDispositivo As Device
Public Sub New(ByVal dispositivo As Device, ByVal padre As BaseDeLaAnimacion(Of MaterialPersonalizado, MallaPersonalizada), ByVal rutaDeLaTextura As String)
clasePadre = padre
texRuta = rutaDeLaTextura
miDispositivo = dispositivo
End Sub
Public Overrides Function CreateFrame(ByVal nombre As String) As Frame
Dim fotograma As New Fotograma(nombre)
Return fotograma
End Function
Public Overrides Function CreateMeshContainer(ByVal nombre As String, ByVal datosDeLaMalla As MeshData, ByVal materiales As ExtendedMaterial(), ByVal efectos As EffectInstance(), ByVal adyacencia As GraphicsStream, ByVal skinInfo As SkinInformation) As MeshContainer
Try
'Si no hay mallas o si no estan formateados los vertices no podemos crear un contenedor
If datosDeLaMalla.Mesh Is Nothing Then Throw New ArgumentException()
If datosDeLaMalla.Mesh.VertexFormat = VertexFormats.None Then Throw New ArgumentException()
' de lo contrario creamos un contenedor de mallas, de momento vacio
Dim contenedorDeMallas As New ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada)()
contenedorDeMallas.Name = nombre ' le damos nombre al contenedor
Dim dispositivo As Device = datosDeLaMalla.Mesh.Device
contenedorDeMallas.SetMaterials(materiales)
contenedorDeMallas.SetAdjacency(adyacencia)
' crea una coleccion de materiales y se los manda al nuevo contenedor
Dim mateList As MaterialPersonalizado() = New MaterialPersonalizado(materiales.Length) {}
Dim i As Integer = 0
For Each material As ExtendedMaterial In materiales
mateList(System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)) = clasePadre.MeteMaterial(miDispositivo, material, texRuta)
Next
contenedorDeMallas.materiales = mateList
contenedorDeMallas.MeshData = datosDeLaMalla
' Si existe informacion de la animacion, se la pasamos al nuevo contenedor
If skinInfo IsNot Nothing Then contenedorDeMallas.SkinInformation = skinInfo
' Para mas referencias ver la clase MallaAnimadaPersonalizada
contenedorDeMallas.MallaAnimada = New MallaPersonalizada()
contenedorDeMallas.MallaAnimada.Inicializa(contenedorDeMallas)
Return contenedorDeMallas ' devuelve el nuevo contenedor de mallas
Catch ex As Exception
End Try
End Function
End Class
' Personalizamos la clase MeshContainer
Public Class ContenedorDeMallaPersonalizado(Of MaterialPersonalizado As {ContenedorDeMaterial, New}, MallaPersonalizada As BaseDeLaMallaAnimada(Of MaterialPersonalizado))
Inherits MeshContainer
Private materiales_ As MaterialPersonalizado()
Private miMalla As MallaPersonalizada
Private fotogramas As Fotograma()
Public Property MallaAnimada() As MallaPersonalizada
Get
Return miMalla
End Get
Set(ByVal value As MallaPersonalizada)
miMalla = value
End Set
End Property
Public Property materiales() As MaterialPersonalizado()
Get
Return materiales_
End Get
Set(ByVal valor As MaterialPersonalizado())
materiales_ = valor
End Set
End Property
Public Function CogeFotogramas() As Fotograma()
Return fotogramas
End Function
Public Sub PonFotogramas(ByVal fotogramas_ As Fotograma())
fotogramas = fotogramas_
End Sub
End Class
' Personalizamos la clase Frame
Public Class Fotograma
Inherits Frame
Private combinado As Matrix = Matrix.Identity
Public Sub New(ByVal nombre As String)
' Personalizamos nuestro fotograma con una matriz combinada
Me.Name = nombre
Me.TransformationMatrix = Matrix.Identity
Me.combinado = Matrix.Identity
End Sub
Public Property MatrizTransformadaYCombinada() As Matrix
Get
Return combinado
End Get
Set(ByVal valor As Matrix)
combinado = valor
End Set
End Property
End Class
Imports Microsoft.DirectX.Direct3D
Public Class MallaAnimada(Of TMaterial As {ContenedorDeMaterial, New})
Inherits BaseDeLaAnimacion(Of TMaterial, MallaAnimadaPersonalizada(Of TMaterial))
Public Sub New(ByVal dispositivo As Device, ByVal xRuta As String, ByVal texRuta As String)
MyBase.New(dispositivo, xRuta, texRuta)
End Sub
End Class
Public MustInherit Class BaseDeLaAnimacion(Of MaterialPersonalizado As {ContenedorDeMaterial, New}, MallaPersonalizada As {BaseDeLaMallaAnimada(Of MaterialPersonalizado), New})
Private fotogramaRaiz As AnimationRootFrame
Private materialExtra As New List(Of ExtendedMaterial)()
Private listaDeMaterial As New List(Of MaterialPersonalizado)()
Public Sub New(ByVal dispositivo As Device, ByVal fichero As String, ByVal rutaDeLaTextura As String)
Try
' Creamos un almacen que alojara del objeto X cargado, mallas y materiales
Dim almacen As New AlojadorJerarquicoPersonalizado(Of MaterialPersonalizado, MallaPersonalizada)(dispositivo, Me, rutaDeLaTextura)
' Le indicamos la estructua jerarquica de la animacion de nuestro objeto X
fotogramaRaiz = Mesh.LoadHierarchyFromFile(fichero, MeshFlags.Managed, dispositivo, almacen, Nothing)
' Personalizamos los fotogramas
ConfiguraMatrizDeHuesos(DirectCast(fotogramaRaiz.FrameHierarchy, Fotograma))
Catch ex As Exception
End Try
End Sub
Friend Function MeteMaterial(ByVal dispositivo As Device, ByVal material As ExtendedMaterial, ByVal rutaDeLaTextura As String) As MaterialPersonalizado
Try
Dim i As Integer = 0
For Each mate As ExtendedMaterial In materialExtra
If mate.Equals(material) Then
Return listaDeMaterial(System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1))
End If
Next
Dim nuevoMaterial As New MaterialPersonalizado()
nuevoMaterial.inicializa(dispositivo, material, rutaDeLaTextura)
listaDeMaterial.Add(nuevoMaterial)
materialExtra.Add(material)
Return nuevoMaterial
Catch ex As Exception
End Try
End Function
Private Sub ConfiguraMatrizDeHuesos(ByVal fotograma As Fotograma)
Try
' Recursamos todas las veces que sean necesarias hasta tener convertidos todos los fotogramas
If fotograma.MeshContainer IsNot Nothing Then ConfiguraMatrizDeHuesos(DirectCast(fotograma.MeshContainer, ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada)))
If fotograma.FrameSibling IsNot Nothing Then ConfiguraMatrizDeHuesos(DirectCast(fotograma.FrameSibling, Fotograma))
If fotograma.FrameFirstChild IsNot Nothing Then ConfiguraMatrizDeHuesos(DirectCast(fotograma.FrameFirstChild, Fotograma))
Catch ex As Exception
End Try
End Sub
Private Sub ConfiguraMatrizDeHuesos(ByVal contenedorPersonalizado As ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada))
Try
' si el contenedor de mallas personalizado tiene informacion de la animacion
If contenedorPersonalizado.SkinInformation IsNot Nothing Then
Dim numhuesos_ As Integer = contenedorPersonalizado.SkinInformation.NumberBones
' tomamos todos los fotogramas del contenedor
Dim MatrizDeFotogramas As Fotograma() = New Fotograma(numhuesos_ - 1) {}
For i As Integer = 0 To numhuesos_ - 1
' Convertimos los fotogramas (Frame) al tipo de nuestra clase Fotograma
Dim fotograma As Fotograma = DirectCast(Frame.Find(fotogramaRaiz.FrameHierarchy, contenedorPersonalizado.SkinInformation.GetBoneName(i)), Fotograma)
If fotograma Is Nothing Then Throw New ArgumentException()
MatrizDeFotogramas(i) = fotograma
Next
contenedorPersonalizado.PonFotogramas(MatrizDeFotogramas)
End If
Catch ex As Exception
End Try
End Sub
Private Sub ActualizaMatrizDelFotograma(ByVal fotograma As Fotograma, ByVal matrixPadre As Matrix)
Try
' Combinamos la matriz padre del fotograma actual y su propia matriz
fotograma.MatrizTransformadaYCombinada = fotograma.TransformationMatrix * matrixPadre
' Si el fotograma actual, tiene hijos o no tiene hermanos, actualizamos de nuevo
If fotograma.FrameSibling IsNot Nothing Then ActualizaMatrizDelFotograma(DirectCast(fotograma.FrameSibling, Fotograma), matrixPadre)
If fotograma.FrameFirstChild IsNot Nothing Then ActualizaMatrizDelFotograma(DirectCast(fotograma.FrameFirstChild, Fotograma), fotograma.MatrizTransformadaYCombinada)
Catch ex As Exception
End Try
End Sub
Private Sub DibujaFotograma(ByVal dispositivo As Device, ByVal fotograma As Fotograma)
Try
Dim contenedorPersonalizado As ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada) = DirectCast(fotograma.MeshContainer, ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada))
While contenedorPersonalizado IsNot Nothing
DibujaContenedorDeMallas(dispositivo, contenedorPersonalizado)
contenedorPersonalizado = DirectCast(contenedorPersonalizado.NextContainer, ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada))
End While
' Si el fotograma actual, tiene hijos o tiene hermanos, volvemos a dibujar
If fotograma.FrameSibling IsNot Nothing Then DibujaFotograma(dispositivo, DirectCast(fotograma.FrameSibling, Fotograma))
If fotograma.FrameFirstChild IsNot Nothing Then DibujaFotograma(dispositivo, DirectCast(fotograma.FrameFirstChild, Fotograma))
Catch ex As Exception
End Try
End Sub
Private Sub DibujaContenedorDeMallas(ByVal dispositivo As Device, ByVal contenedorPersonalizado As ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada))
If contenedorPersonalizado.MallaAnimada.tieneInformacionAnimada_ Then
contenedorPersonalizado.MallaAnimada.Dibuja(dispositivo, contenedorPersonalizado.CogeFotogramas(), contenedorPersonalizado.materiales)
End If
End Sub
Public Sub Anima(ByVal tiempo As Single, ByVal MatrixGlobal As Matrix)
Try
If fotogramaRaiz.AnimationController IsNot Nothing Then
fotogramaRaiz.AnimationController.AdvanceTime(tiempo, Nothing)
End If
ActualizaMatrizDelFotograma(DirectCast(fotogramaRaiz.FrameHierarchy, Fotograma), MatrixGlobal)
Catch ex As Exception
End Try
End Sub
Public Sub Dibuja(ByVal dispositivo As Device)
Try
DibujaFotograma(dispositivo, DirectCast(Me.fotogramaRaiz.FrameHierarchy, Fotograma))
Catch ex As Exception
End Try
End Sub
Public Sub Dispose()
End Sub
End Class
Public Class MallaAnimadaPersonalizada(Of MaterialPersonalizado As {ContenedorDeMaterial, New})
Inherits BaseDeLaMallaAnimada(Of MaterialPersonalizado)
Public Overrides Sub GeneraMallaAnimada(ByVal contenedorDeLaMalla As MeshContainer)
Try
' Si hay informacion de animacion en el contenedor de la malla
If contenedorDeLaMalla.SkinInformation IsNot Nothing Then
tieneInformacionAnimada = True
Dim numhuesos_ As Integer = contenedorDeLaMalla.SkinInformation.NumberBones
matrices = New Matrix(numhuesos_ - 1) {}
For i As Integer = 0 To numhuesos_ - 1
matrices(i) = contenedorDeLaMalla.SkinInformation.GetBoneOffsetMatrix(i)
Next
' Genera Adyacencia, trianguliza la malla
Dim datosDeLaMalla As MeshData = contenedorDeLaMalla.MeshData
adia = New Integer(miMalla.NumberFaces * 3 - 1) {}
miMalla.GenerateAdjacency(0.001F, adia)
miMalla = contenedorDeLaMalla.SkinInformation.ConvertToBlendedMesh(datosDeLaMalla.Mesh, MeshFlags.Managed Or MeshFlags.OptimizeVertexCache, adia, numeroDeInfluencias, huesos)
numeroDeAtributos = huesos.Length
contenedorDeLaMalla.MeshData = datosDeLaMalla
End If
Catch ex As Exception
End Try
End Sub
Public Overrides Sub Dibuja(ByVal dispositivo As Device, ByVal frameMatrices As Fotograma(), ByVal materiales As MaterialPersonalizado())
Try
Dim atributoIdAnterior As Integer = -1
' Dibuja o renderiza el fotograma actual de nuestro objeto X
For iatributo As Integer = 0 To numeroDeAtributos_ - 1
Dim numBlend As Integer = 0
For i As Integer = 0 To numeroDeInfluencias_ - 1
If huesos(iatributo).BoneId(i) <> -1 Then numBlend = i
Next
If dispositivo.DeviceCaps.MaxVertexBlendMatrices >= numBlend + 1 Then
Dim matrices As Matrix() = matrices_
For i As Integer = 0 To numeroDeInfluencias_ - 1
Dim iMatrix As Integer = huesos(iatributo).BoneId(i)
If iMatrix <> -1 Then
Dim tempMatrix As Matrix = matrices(iMatrix) * frameMatrices(iMatrix).MatrizTransformadaYCombinada
dispositivo.Transform.SetWorldMatrixByIndex(i, tempMatrix)
End If
Next
dispositivo.RenderState.VertexBlend = DirectCast(numBlend, VertexBlend)
If (atributoIdAnterior <> huesos(iatributo).AttributeId) OrElse (atributoIdAnterior = -1) Then
atributoIdAnterior = huesos(iatributo).AttributeId
End If
materiales(huesos(iatributo).AttributeId + 1).aplica(dispositivo)
' Dibujamos la Malla
miMalla.DrawSubset(iatributo)
End If
Next
Catch ex As Exception
End Try
End Sub
Public Overrides Sub Dispose()
Try
miMalla.Dispose()
Catch ex As Exception
End Try
End Sub
End Class
Public MustInherit Class BaseDeLaMallaAnimada(Of MaterialPersonalizado As {ContenedorDeMaterial, New})
Inherits Malla(Of MaterialPersonalizado)
Protected huesos As BoneCombination()
Protected matrices As Matrix()
Protected adia As Integer() ' Buffer que contiene información sobre los bordes, caras y caras adyacentes
Protected numeroDeInfluencias As Integer
Public ReadOnly Property numeroDeInfluencias_() As Integer
Get
Return numeroDeInfluencias
End Get
End Property
Protected numeroDeAtributos As Integer
Public ReadOnly Property numeroDeAtributos_() As Integer
Get
Return numeroDeAtributos
End Get
End Property
Public ReadOnly Property matrices_() As Matrix()
Get
Return matrices
End Get
End Property
Protected tieneInformacionAnimada As Boolean
Public ReadOnly Property tieneInformacionAnimada_() As Boolean
Get
Return tieneInformacionAnimada
End Get
End Property
Public Sub Inicializa(ByVal contenedor As MeshContainer)
miMalla = contenedor.MeshData.Mesh
GeneraMallaAnimada(contenedor)
listaDeMaterial = New MaterialPersonalizado(0) {}
listaDeMaterial(0) = New MaterialPersonalizado()
End Sub
Public MustOverride Sub GeneraMallaAnimada(ByVal malla As MeshContainer)
Public MustOverride Sub Dibuja(ByVal dispositivo As Device, ByVal frameMatrices As Fotograma(), ByVal materiales As MaterialPersonalizado())
Public MustOverride Sub Dispose()
End Class
' Personalizamos la clase AllocateHierarchy
Public Class AlojadorJerarquicoPersonalizado(Of MaterialPersonalizado As {ContenedorDeMaterial, New}, MallaPersonalizada As {BaseDeLaMallaAnimada(Of MaterialPersonalizado), New})
Inherits AllocateHierarchy
Private clasePadre As BaseDeLaAnimacion(Of MaterialPersonalizado, MallaPersonalizada)
Private texRuta As String = ""
Private miDispositivo As Device
Public Sub New(ByVal dispositivo As Device, ByVal padre As BaseDeLaAnimacion(Of MaterialPersonalizado, MallaPersonalizada), ByVal rutaDeLaTextura As String)
clasePadre = padre
texRuta = rutaDeLaTextura
miDispositivo = dispositivo
End Sub
Public Overrides Function CreateFrame(ByVal nombre As String) As Frame
Dim fotograma As New Fotograma(nombre)
Return fotograma
End Function
Public Overrides Function CreateMeshContainer(ByVal nombre As String, ByVal datosDeLaMalla As MeshData, ByVal materiales As ExtendedMaterial(), ByVal efectos As EffectInstance(), ByVal adyacencia As GraphicsStream, ByVal skinInfo As SkinInformation) As MeshContainer
Try
'Si no hay mallas o si no estan formateados los vertices no podemos crear un contenedor
If datosDeLaMalla.Mesh Is Nothing Then Throw New ArgumentException()
If datosDeLaMalla.Mesh.VertexFormat = VertexFormats.None Then Throw New ArgumentException()
' de lo contrario creamos un contenedor de mallas, de momento vacio
Dim contenedorDeMallas As New ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada)()
contenedorDeMallas.Name = nombre ' le damos nombre al contenedor
Dim dispositivo As Device = datosDeLaMalla.Mesh.Device
contenedorDeMallas.SetMaterials(materiales)
contenedorDeMallas.SetAdjacency(adyacencia)
' crea una coleccion de materiales y se los manda al nuevo contenedor
Dim mateList As MaterialPersonalizado() = New MaterialPersonalizado(materiales.Length) {}
Dim i As Integer = 0
For Each material As ExtendedMaterial In materiales
mateList(System.Math.Max(System.Threading.Interlocked.Increment(i), i - 1)) = clasePadre.MeteMaterial(miDispositivo, material, texRuta)
Next
contenedorDeMallas.materiales = mateList
contenedorDeMallas.MeshData = datosDeLaMalla
' Si existe informacion de la animacion, se la pasamos al nuevo contenedor
If skinInfo IsNot Nothing Then contenedorDeMallas.SkinInformation = skinInfo
' Para mas referencias ver la clase MallaAnimadaPersonalizada
contenedorDeMallas.MallaAnimada = New MallaPersonalizada()
contenedorDeMallas.MallaAnimada.Inicializa(contenedorDeMallas)
Return contenedorDeMallas ' devuelve el nuevo contenedor de mallas
Catch ex As Exception
End Try
End Function
End Class
' Personalizamos la clase MeshContainer
Public Class ContenedorDeMallaPersonalizado(Of MaterialPersonalizado As {ContenedorDeMaterial, New}, MallaPersonalizada As BaseDeLaMallaAnimada(Of MaterialPersonalizado))
Inherits MeshContainer
Private materiales_ As MaterialPersonalizado()
Private miMalla As MallaPersonalizada
Private fotogramas As Fotograma()
Public Property MallaAnimada() As MallaPersonalizada
Get
Return miMalla
End Get
Set(ByVal value As MallaPersonalizada)
miMalla = value
End Set
End Property
Public Property materiales() As MaterialPersonalizado()
Get
Return materiales_
End Get
Set(ByVal valor As MaterialPersonalizado())
materiales_ = valor
End Set
End Property
Public Function CogeFotogramas() As Fotograma()
Return fotogramas
End Function
Public Sub PonFotogramas(ByVal fotogramas_ As Fotograma())
fotogramas = fotogramas_
End Sub
End Class
' Personalizamos la clase Frame
Public Class Fotograma
Inherits Frame
Private combinado As Matrix = Matrix.Identity
Public Sub New(ByVal nombre As String)
' Personalizamos nuestro fotograma con una matriz combinada
Me.Name = nombre
Me.TransformationMatrix = Matrix.Identity
Me.combinado = Matrix.Identity
End Sub
Public Property MatrizTransformadaYCombinada() As Matrix
Get
Return combinado
End Get
Set(ByVal valor As Matrix)
combinado = valor
End Set
End Property
End Class
No hay comentarios:
Publicar un comentario