|
| Autor |
Mensaje |
WhiteSkull Moderador Global

Registrado: 20 Mar 2009 Mensajes: 2084 Ubicación: y*width+x
|
Publicado: Jue 08 Oct, 2009 19:33 pm
Título del mensaje: Tutorial de DirectX para VB .NET (DirectX8+) |
|
|
Introducción
Pues nada, a raíz de un "jueguillo" hecho por uno de nuestros colaboradores, el compañero joxeduke12, he seguido intentando mejorarlo usando el mismo lenguaje pero con .NET de fondo. Las siguientes mejoras de dicho juego y el original, pueden ser descargados en éste enlace, http://lospillaos.es/foro/siguiente-vt2792.html?amp;postdays=0&postorder=asc&start=15. El problema que surgía es que los componentes gráficos convencionales son muy lentos, incluso usando un componente llamado ASPRITE que supuestamente usa las DirectX y el cual es posible descargarse por algún lugar de la red. Ello es debido a que la petición gráfica pasa por diferentes capas hasta llegar al hardware, así que se hace necesario prescindir de los intermediarios y pasar "directamente" por su "manager" o "encargado".
En éste tutorial se intentará enseñar los métodos básicos para desarrollar "jueguillos" 2D con DirectX en VBasic, para que otro, si puede, continúe el legado o lo use a su antojo.
Comienzo
Primeramente me decanté por .NET, no sólo por la sencilles de uso de sus componentes, cómo Microsoft.DirectX.Direct3D el cual hay que referenciar. Si no porque además no conseguía hacer funcionar algunas funciones de la vieja dx8vb.dll, sólo consiguiendo usar un método de vértices que creaban un polígono con textura (que es posible que más adelante explique), a pesar de que existe una función Sprite en la DLL antes citada.
Comencemos pues. Primeramente debemos referenciar el componente .NET Microsoft.DirectX.Direct3D , para aquel que no lo sepa, una vez creado el proyecto clikeamos en la barra del menú, en Proyectos->Agregar referencia (versión española) y buscamos la citación comentada. Luego incluimos en la cabecera del código más de lo mismo:
| Código: | Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
|
Y ya estamos listos para empezar.
Primer paso, incialización
La inicialización y configuración del dispositivo abstracto, que accede al hardware por nosostros, requiere del uso de un objeto clave, que será declarado de la siguiente forma, para ello usamos un nombre significativo:
Dim dispositivo As Direct3D.Device
Dicho dispositivo representará a la parte gráfica, encargándose éste de buscarse la vida para poner imágenes y hacer todo lo que le pidamos. Antes de asignarle el dispositivo, pues de momento sólo lo hemos "declarado", hay que pasarle unos parámetros, los cuales enseñaremos los mínimos indispensables, ya que son muchos. Siendo los siguientes: El SwapEffect, BackBufferWidth, BackBufferHeight y Windowed. Para ello declaramos e incializamos los parámetros de la siguiente forma:
| Código: | Dim parametro As PresentParameters = New PresentParameters
parametro.SwapEffect = SwapEffect.Discard ' Descartamos efectos en el volcado
parametro.BackBufferWidth = Me.Width ' Asignamos ancho del formulario
parametro.BackBufferHeight = Me.Height ' Asignamos la altura del formulario
parametro.Windowed = True ' Se ejecutará en modo ventana
...
...
|
seguidamente asignamos el dispositivo...
| Código: | ...
dispositivo = New Direct3D.Device(0, DeviceType.Hardware, Me, CreateFlags.SoftwareVertexProcessing, parametro)
|
Ya está... ven que fácil. Ya tenemos una aplicación DirectX, que no hace nada.
Dibujar Sprites
La forma para declarar e inicializar un objeto Sprite se puede resumir todo en una sóla línea.
Dim MiSprite As Sprite=New Sprite(dispositivo)
Ahora disponemos de un objeto Sprite, pero el Sprite por si sólo no hace nada, necesitamos la textura o imagen que queramos mostrar. Por lo tanto habrá que declarar e inicializar la textura que vestirá nuestro Sprite. Hay que añadir que es posible usar todo tipo de formatos bitmaps, pero para evitar embrollos innecesarios yo recomendaría usar para Sprites que usan Canal Alpha o transparencia, un fichero PNG, que previamente desde un editor gráfico hayamos asignado el color transparente.
Dim textura As Texture = TextureLoader.FromFile(dispositivo, Fichero)
Habrá que incluir estás tres líneas después de crear el dispositivo, si queremos que funcionen las transparencias.
| Código: | dispositivo.RenderState.AlphaBlendEnable = True
dispositivo.RenderState.SourceBlend = Blend.SourceAlpha
dispositivo.RenderState.DestinationBlend = Blend.InvSourceAlpha |
Bueno, una vez que ya tenemos preparados el Sprite con su correspondiente textura, ya sólo nos falta pasar al Render. El Render, es el proceso de pintado en el buffer, y el volcado de éste a la pantalla visible. Para ello DirectX usa un método muy similar a OpenGl, por si alguien no lo ha usado lo explicaré. Consiste en dos métodos del objeto dispositivo, una de comienzo, BeginScene, y otra de fin, EndScene. Dentro de éstos dos métodos, se registrarán todas las peticiones gráficas y todas las peticiones gráficas que se encuentren fuera de los mencionados métodos se omitirá. Luego hay un tercer método, Present, que se encarga de llevar estas peticiones al "sumo sacerdote" o "manager" que invocará con su magia todo lo necesario para que veamos los gráficos por la pantalla.
| Código: | ...
...
' Bucle infinito
dispositivo.BeginScene() ' Comienzo del buffer
' Aqui dibujamos lo que queramos
dispositivo.EndScene() ' Fin del buffer
dispositivo.Present() ' Muestra por pantalla el resultado
...
...
|
Ahora que ya sabemos el procedimiento del Render, sólo falta sustituir la línea ' Aqui dibujamos lo que queramos del ejemplo anterior, por éstas líneas, que muestran el procedimiento para dibujar un Sprite.
| Código: | MiSprite.Begin(SpriteFlags.None) ' comenzamos a pintar nuestro sprite
MiSprite.Draw2D(textura _ ' Obviamente, la textura
, New Point(0, 0) _ ' El centro del Sprite, tiene su explicacion
, 0 _ ' El angulo de rotacion (lo podemos girar)
, New Point(100, 50) ' Las coordenadas X e Y de la pantalla
, Color.White) ' Filtro de color
MiSprite.Flush()
MiSprite.End() ' Fin del pintado
|
Aparte de Draw2D, Sprite incluye otro método más complejo que permite hacer más filigranas cómo escalados, recortes, etc... Draw, pero eso ya lo dejo a ustedes para que practiquen e investiguen por cuenta propia. Próximamente o cuando tenga ganas explicaré otras historias de las DirectX. Espero que les sea util, chao!!  |
http://www.youtube.com/watch?v=-lT1zCukNQY
|
|
| Volver arriba |
|
|
weirdmix Moderador Global

Registrado: 08 May 2008 Mensajes: 618 Ubicación: DF - MEXICO
|
|
| Volver arriba |
|
|
Tesis Administrador

Registrado: 04 Mar 2007 Mensajes: 2750 Ubicación: Valencia - España
|
|
| Volver arriba |
|
|
WhiteSkull Moderador Global

Registrado: 20 Mar 2009 Mensajes: 2084 Ubicación: y*width+x
|
|
| Volver arriba |
|
|
Arael25 Colaborador

Registrado: 13 Mar 2007 Mensajes: 611 Ubicación: Lima - Peru
|
|
| Volver arriba |
|
|
WhiteSkull Moderador Global

Registrado: 20 Mar 2009 Mensajes: 2084 Ubicación: y*width+x
|
|
| Volver arriba |
|
|
Tesis Administrador

Registrado: 04 Mar 2007 Mensajes: 2750 Ubicación: Valencia - España
|
|
| Volver arriba |
|
|
WhiteSkull Moderador Global

Registrado: 20 Mar 2009 Mensajes: 2084 Ubicación: y*width+x
|
Publicado: Jue 25 Feb, 2010 01:57 am
Título del mensaje: Re: Tutorial de DirectX para VB .NET (DirectX8+) |
|
|
LUCES Y OBJETOS 3D
Introducción
Bueno, brevemente explicaré cómo usar gráficos 3D y cómo aplicar luces en las escenas usando cómo no, las DirectX en .NET. Increiblemente después de haberme regalado a mi mismo la Xbox 360, me puse a probar la librería XNA, que supuestamente es un wrapper (un envolvente) de las DirectX y supuestamente sus creadores (El equipo de Brian Keller y cia) creen que el desarrollo de videojuegos con esa cosa será el no va más. Y cómo comentaba, increíblemente, porque las XNA, para quien no haya tenido contacto, repito, con esa cosa, es lo peor de lo peor. Sencillamente es más fácil usar directamente las X que trabajar con eso. Sobre todo porque mucho del trabajo se realiza directamente con los shaders. Ya en otra ocasión haré también otro tutorial de las XNA, y ya comprobareis la tremenda diferencia. Pero antes del XNA, mostraré mis pequeños conocimientos con Tao-FrameWork, usando OpenGl en .NET, si si, cómo han leído, OPENGL. Pero cómo decía el narrador de "Conan el barbaro" al final de la peli; "..eso es otra historia..".
Comienzo
Vamos a lo que vamos. Básicamente lo mismo que explique anteriormente, inicializar el dispositivo, parámetros, etc.. es casi todo idéntico.
| Código: | Dim Parametros As PresentParameters = New PresentParameters
Parametros.SwapEffect = SwapEffect.Discard
Parametros.BackBufferHeight = Me.Height
Parametros.BackBufferWidth = Me.Width
Parametros.AutoDepthStencilFormat = DepthFormat.D16
Parametros.EnableAutoDepthStencil = True
Parametros.Windowed = True
' Creamos dispositivo
dispositivo = New Device(0, DeviceType.Hardware, Me, CreateFlags.SoftwareVertexProcessing, Parametros)
' Transparencias
dispositivo.RenderState.AlphaBlendEnable = True
dispositivo.RenderState.SourceBlend = Blend.SourceAlpha
dispositivo.RenderState.DestinationBlend = Blend.InvSourceAlpha |
Ya tenemos el dispositivo a punto y listo.
Luces
Para escenas estáticas, no necesitaremos actualizar las luces, es más solo debemos inicializarlas y éstas se aplicaran con la escena. Para trabajar con las luces se usará el dispositivo (Microsoft.DirectX.Direct3D.Device) que previamente ya habíamos inicializado y declarado (no por este orden). El dispositivo contiene un miembro de nombre Light que contiene una serie de propiedades elementales para habilitar dicha luz.
Primero me olvidaba comentar que hay que habilitar el render de la luz
| Código: | | dispositivo.RenderState.Lighting = True |
Luego parametrizamos la luz, en éste caso pondremos una luz puntual de color violeta
| Código: | dispositivo.Lights(0).Type = LightType.Point
dispositivo.Lights(0).Diffuse = Color.Violet
dispositivo.Lights(0).Range = 100
dispositivo.Lights(0).Specular = Color.Violet
dispositivo.Lights(0).Position = New Vector3(0, 5, 0)
dispositivo.Lights(0).Attenuation0 = 0.1
dispositivo.Lights(0).Update()
dispositivo.Lights(0).Enabled = True |
Pero ojo, no sólo por contener luz en una escena los objetos se iluminaran. Entre otras cosas será necesario aplicar un material. En éste caso lo aplicaremos a toda la escena de ésta forma, para ello lo haremos transparente, luego ya vosotros podréis jugar con los parámetros y sacar vuestras propias conclusiones.
| Código: | ' Configura el efecto producido por la luz sobre el objeto
' de lo contrario lo veriamos en Negro si activamos la Luz
Dim mat As Material = New Material()
mat.Ambient = Color.Transparent
mat.Diffuse = Color.Transparent
dispositivo.Material = mat |
Ya está. Y se hizo la luz...
Vertices 3D
Por lo general, los objetos 3D nos lo tendremos que currar. Para ello podremos usar primitivas, al igual que en Open-Gl, podremos hacer objetos basados en triángulos, cuadrados o polígonos. Creando para ello una lista de vértices que se procesaran con los métodos adecuados del dispositivo. Para simplificar el tutorial, trataremos con la clase CustomVertex. Los vértices podrán contener datos necesarios para aplicar una textura, colores sólidos o ambas cosas. Cómo nos moveremos en un espacio 3D, habrá que fijar los vértices con coordenadas XYZ.
| Código: | ' Creamos un objeto3D que lo almacenamos en un array
Dim verts() As CustomVertex.PositionColoredTextured = New CustomVertex.PositionColoredTextured(3) {}
verts(0) = New CustomVertex.PositionColoredTextured(0, 0, 0, Color.Red.ToArgb(), 0, 0)
verts(1) = New CustomVertex.PositionColoredTextured(10, 0, 0, Color.Green.ToArgb(), 1, 0)
verts(2) = New CustomVertex.PositionColoredTextured(5, 10, 0, Color.Yellow.ToArgb(), 1, 1) |
Bueno aquí he creado unos tres puntos casi al boleo. Pero vale para entender cómo funciona el tema. Ahora sólo falta pasarlo al render, recordad cómo expliqué anteriormente, tiene que estar dentro del BeginScene y EndScene.
| Código: | dispositivo.VertexFormat = CustomVertex.PositionColoredTextured.Format
dispositivo.DrawUserPrimitives(PrimitiveType.TriangleList, 1, verts) |
Cómo veis hemos usado el método DrawUserPrimitive, al cual le decimos que tipo de primitivas, en éste caso es un triangulito (o eso parece), luego le decimos cuantos polígonos, lógicamente uno y al final le pasamos la matriz de vértices.
Mallas
Y ya por último acabamos con las mallas. Una malla es la representación consistente de varios polígonos. Aunque podríamos hacer mallas dibujando polígono por polígono, ésto nos llevaría mucho tiempo. Por lo que para trabajar con gráficos 3D muchos se deciden por emplear herramientas de diseño. Para nuestro ejemplo, usaremos el tigre que trae las SDK de DirectX 8, es un tigre muy bonito y sencillo. De momento no lo animaremos, eso lo dejamos para más adelante. Junto con el fichero X, además nos encontraremos con una textura. Si vais a usar otro fichero para éste tutorial, intentar que sea un objeto con una única textura.
Entonces lo primero es cargar la textura.
| Código: | | Dim tex As Texture = TextureLoader.FromFile(dispositivo, "Tiger.bmp") |
Y ahora cargamos la malla o el objeto 3d.
| Código: | Dim Malla As Mesh
Malla = Mesh.FromFile("Tiger.X", MeshFlags.DoNotClip, dispositivo)
Malla = Malla.Clone(Malla.Options.Value, CustomVertex.PositionNormalTextured.Format, dispositivo)
Malla.ComputeNormals() |
Ya tenemos el objeto y la textura. Y ya para finalizar lo renderizamos, y vuelvo a recordar a la peña, que debe estar entre el BeginScene y el EndScene. Para renderizar la malla usamos el método DrawSubset de la Malla, y para texturizar SetTexture del dispositivo.
| Código: | ' Objeto 3D
dispositivo.SetTexture(0, tex)
Malla.DrawSubset(0) |
Podremos usar SetTexture también para el ejemplo anterior de los vértices.
Para los incrédulos, adjunto un enlace con un par de ejemplos:
http://ge.tt/8vBpaaB?c |
http://www.youtube.com/watch?v=-lT1zCukNQY
Ultima edición por WhiteSkull el Sab 24 Dic, 2011 01:46 am; editado 2 veces
|
|
| Volver arriba |
|
|
Vila Usuario Inquieto

Registrado: 14 May 2010 Mensajes: 123 Ubicación: Vulpesheim
|
Publicado: Jue 01 Jul, 2010 22:35 pm
Título del mensaje: Re: Tutorial de DirectX para VB .NET (DirectX8+) |
|
|
Estimado White Skull.
Muy bueno su tutorial sobre Direct X. Yo también lo pienso utilizar con el lenguaje C#, que me parece mucho más cómodo para la POO, pero de hecho el VB.NET es equivalente a él en potencia. |
|
|
|
| Volver arriba |
|
|
Vila Usuario Inquieto

Registrado: 14 May 2010 Mensajes: 123 Ubicación: Vulpesheim
|
Publicado: Jue 01 Jul, 2010 22:43 pm
Título del mensaje: Re: Tutorial de DirectX para VB .NET (DirectX8+) |
|
|
| WhiteSkull escribió: | LUCES Y OBJETOS 3D
Introducción
Bueno, brevemente explicaré cómo usar gráficos 3D y cómo aplicar luces en las escenas usando cómo no, las DirectX en .NET.
[...]
Para los incrédulos, adjunto un enlace con un par de ejemplos:
http://rapidshare.com/files/355415599/MisejemplosDirectX.rar.html
MD5: F8B54F3BD1A7AC25847A487411974372 |
Intenté descargar el ejemplo del sitio mencionado, pero me salió el sgte mensaje de error:
| Cita: | Error
This file is neither allocated to a Premium Account, or a Collector's Account, and can therefore only be downloaded 10 times.
This limit is reached.
To download this file, the uploader either needs to transfer this file into his/her Collector's Account, or upload the file again. The file can later be moved to a Collector's Account. The uploader just needs to click the delete link of the file to get further information.
|
¿A qué se debe? |
|
|
|
| Volver arriba |
|
|
WhiteSkull Moderador Global

Registrado: 20 Mar 2009 Mensajes: 2084 Ubicación: y*width+x
|
|
| Volver arriba |
|
|
WhiteSkull Moderador Global

Registrado: 20 Mar 2009 Mensajes: 2084 Ubicación: y*width+x
|
Publicado: Mie 28 Jul, 2010 05:06 am
Título del mensaje: Re: Tutorial de DirectX para VB .NET (DirectX8+) |
|
|
ANIMAR UN OBJETO 3D ANIMADO
Introducción
Que tal! Pues aquí de vuelta con los DirectX, que cómo indica el título de éste capítulo, vamos animar un fichero X animado, porque anteriormente ya habíamos tratado las luces, carga de ficheros X 'estáticcos', Sprites y fundamentos 3D. Entonces ahora toca ésto y luego pues se tocará para acabar el sonido y el control de datos de los dispositivos de entrada, suficiente pienso, para comenzar un modesto juego 3D completo, pero lo trataremos a su tiempo, así que tranquilos.
Antes que nada, el trabajo no es mío al cien por cien, realmente es una clase adaptada de RobyDx que a su vez extrajo la información del libro Managed DirectX 9 Kick Start de Tom Miller, así que las flores nos las repartimos todos .
Comienzo
Para comenzar, tenemos que tener suficientemente claros los conceptos que aprendimos en los anteriores capítulos, y tener un buen nivel de programación en .NET. Entonces nos comeremos el paso de inicialización y declaración del dispositivo, aunque lo resumiremos con código, cualquier duda, repasen los capítulos anteriores.
| Código: | Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
Public Class Form1
Private dispositivo As Device
Private Parametros As PresentParameters
Private Sub Form1_Load(ByVal sender As Object, ByVal e As EventArgs) Handles MyBase.Load
Parametros = New PresentParameters()
Parametros.AutoDepthStencilFormat = DepthFormat.D16
Parametros.SwapEffect = SwapEffect.Discard
Parametros.EnableAutoDepthStencil = True
Parametros.BackBufferHeight = Me.Height
Parametros.BackBufferWidth = Me.Width
Parametros.Windowed = True
dispositivo = New Device(0, DeviceType.Hardware, Me, CreateFlags.SoftwareVertexProcessing, Parametros)
Me.SetStyle(ControlStyles.Opaque Or ControlStyles.AllPaintingInWmPaint, True)
End Sub
...
...
|
Ya tenemos el dispositivo a punto y listo.
El material personalizado
Necesitaremos personalizar algunas de las clases ya existentes en la librería DirectX. Dado que no existe ninguna Clase que por si sola anime un objeto X animado. Entonces lo primero será empezar por crear un contenedor de materiales, que cómo indica su nombre, contendrá los materiales de la malla animada. El contenedor podrá contener materiales texturizados y sin texturizar.
Creamos una clase llamada MaterialPersonalizado, que contendrá el siguiente código:
| Código: | Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
' Creamos nuestra clase para almacenar nuestros materiales personalizados
Public MustInherit Class ContenedorDeMaterial
Public MustOverride Sub inicializa(ByVal dispositivo As Device, ByVal material As ExtendedMaterial, ByVal rutaDeLaTextura As String)
Public MustOverride Sub aplica(ByVal dispositivo As Device)
Public MustOverride Sub dispose()
End Class
Public Class SinMaterial
Inherits ContenedorDeMaterial
Public Overrides Sub inicializa(ByVal dispositivo As Device, ByVal material As ExtendedMaterial, ByVal rutaDeLaTextura As String)
End Sub
Public Overrides Sub aplica(ByVal dispositivo As Device)
End Sub
Public Overrides Sub dispose()
End Sub
End Class
Public Class MaterialSinTexturizar
Inherits SinMaterial
Protected materia As Material
Public Overrides Sub inicializa(ByVal dispositivo As Device, ByVal material As ExtendedMaterial, ByVal rutaDeLaTextura As String)
MyBase.inicializa(dispositivo, material, rutaDeLaTextura)
Me.materia = material.Material3D
Me.materia.AmbientColor = Me.materia.DiffuseColor
End Sub
Public Overrides Sub aplica(ByVal dispositivo As Device)
dispositivo.Material = Me.materia
End Sub
Public Overrides Sub dispose()
End Sub
End Class
Public Class MaterialTexturizado
Inherits MaterialSinTexturizar
Private textura As Texture
Public Overrides Sub inicializa(ByVal dispositivo As Device, ByVal material As ExtendedMaterial, ByVal rutaDeLaTextura As String)
MyBase.inicializa(dispositivo, material, rutaDeLaTextura)
If material.TextureFilename Is Nothing Then
Return
End If
If rutaDeLaTextura = "" Then
Me.textura = TextureLoader.FromFile(dispositivo, material.TextureFilename)
Else
Me.textura = TextureLoader.FromFile(dispositivo, rutaDeLaTextura & "\" & Convert.ToString(material.TextureFilename))
End If
End Sub
Public Overrides Sub aplica(ByVal dispositivo As Device)
dispositivo.SetTexture(0, textura)
dispositivo.Material = materia
End Sub
Public Overrides Sub dispose()
If textura IsNot Nothing Then
textura.Dispose()
End If
End Sub
End Class |
La malla personalizada
Al igual que con el contenedor de materiales, necesitaremos una malla especial que soporte animaciones, para ello usaremos un Mesh para crear nuestra malla personalizada, que soportará de momento nuestro material personalizado.
Creamos una clase llamada MallaPersonalizada, que contendrá el siguiente código: | Código: | Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D
Public MustInherit Class MallaBase(Of MallaPersonalizada As BaseMesh, MaterialPersonalizado As {ContenedorDeMaterial, New})
Protected miMalla_ As MallaPersonalizada
Protected listaDeMaterial As MaterialPersonalizado()
Public Property miMalla() As MallaPersonalizada
Get
Return miMalla_
End Get
Set(ByVal valor As MallaPersonalizada)
miMalla_ = valor
End Set
End Property
End Class
Public Class Malla(Of MaterialPersonalizado As {ContenedorDeMaterial, New})
Inherits MallaBase(Of Mesh, MaterialPersonalizado)
Public Sub New()
End Sub
Protected Overrides Sub Finalize()
Try
miMalla.Dispose()
For i As Integer = 0 To listaDeMaterial.Length - 1
listaDeMaterial(i).dispose()
Next
Finally
MyBase.Finalize()
End Try
End Sub
End Class
|
Nuestra clase MallaAnimada
Y por último personalizamos AllocateHierarchy, el MeshContainer y el Frame, clases nativas de DirectX. Para luego dar paso a nuestra clase, MallaAnimada.
Creamos una clase llamada MallaAnimada, y metemos el código:
| Código: | 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 filesrc As String, ByVal texRuta As String)
MyBase.New(dispositivo, filesrc, 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)
' 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))
End Sub
Friend Function MeteMaterial(ByVal dispositivo As Device, ByVal material As ExtendedMaterial, ByVal rutaDeLaTextura As String) As MaterialPersonalizado
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
End Function
Private Sub ConfiguraMatrizDeHuesos(ByVal fotograma As Fotograma)
' 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))
End Sub
Private Sub ConfiguraMatrizDeHuesos(ByVal contenedorPersonalizado As ContenedorDeMallaPersonalizado(Of MaterialPersonalizado, MallaPersonalizada))
' 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
End Sub
Private Sub ActualizaMatrizDelFotograma(ByVal fotograma As Fotograma, ByVal matrixPadre As Matrix)
' 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)
End Sub
Private Sub DibujaFotograma(ByVal dispositivo As Device, ByVal fotograma As Fotograma)
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))
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)
If fotogramaRaiz.AnimationController IsNot Nothing Then fotogramaRaiz.AnimationController.AdvanceTime(tiempo, Nothing)
ActualizaMatrizDelFotograma(DirectCast(fotogramaRaiz.FrameHierarchy, Fotograma), MatrixGlobal)
End Sub
Public Sub Dibuja(ByVal dispositivo As Device)
DibujaFotograma(dispositivo, DirectCast(Me.fotogramaRaiz.FrameHierarchy, Fotograma))
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)
' 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
End Sub
Public Overrides Sub Dibuja(ByVal dispositivo As Device, ByVal frameMatrices As Fotograma(), ByVal materiales As MaterialPersonalizado())
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
End Sub
Public Overrides Sub Dispose()
miMalla.Dispose()
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
'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
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
|
Y por último decir que la clase no está completamente acabada, que es posible mejorarla, yo simplemente simplifique y adapté un proyecto en C sharp a Visual Basic, e intente dejarlo casi en el esqueleto para que fuera fácil su reutilización. Lo lógico es que si la finalidad es crear un juego o lo que sea, es que el interesado haga sus propias clases de gráficos , sonido, etc... lo compile todo en una DLL y la use en el juego.
Bueno una vez que ya tenemos nuestras clases creadas, la forma de usarla es bastante obvia.
| Código: | dim malla As MallaAnimada(Of MaterialTexturizado)
...
...
malla = New MallaAnimada(Of MaterialTexturizado)(dispositivo, "ObjetoAnimado.x", "")
|
y luego para dibujarlo, podremos escoger varias opciones, podemos por ejemplo usar un timer e indicarle cada tantos intervalos pinte, podemos usar el evento paint, etc... Pero lo importante es que siga el procedimiento ya explicado en anteriores capítulos.
| Código: | ...
dispositivo.Transform.Projection = Matrix.PerspectiveFovLH(CSng(Math.PI / 4), Me.Width / Me.Height, 1, 50)
dispositivo.Transform.World = Matrix.RotationAxis(New Vector3(0, 1.0, 0.0), 0.0)
dispositivo.Transform.View = Matrix.LookAtLH(New Vector3(0, 0, 5), New Vector3(0, 0, 0), New Vector3(0, 1, 0))
dispositivo.Clear(ClearFlags.Target Or ClearFlags.ZBuffer, Color.Blue.ToArgb(), 1, 0)
dispositivo.BeginScene()
malla.Anima(0.015F, Matrix.Translation(0, 0, 0))
malla.Dibuja(dispositivo)
dispositivo.EndScene()
dispositivo.Present()
...
...
|
Bueno, pues hasta otra . |
http://www.youtube.com/watch?v=-lT1zCukNQY
|
|
| Volver arriba |
|
|
Tesis Administrador

Registrado: 04 Mar 2007 Mensajes: 2750 Ubicación: Valencia - España
|
|
| Volver arriba |
|
|
javi0unavailable
Registrado: 08 Feb 2012 Mensajes: 8
|
Publicado: Mie 08 Feb, 2012 19:35 pm
Título del mensaje: Re: Tutorial de DirectX para VB .NET (DirectX8+) |
|
|
Disculpas por responder a un post antiguo pero realmente necesito ayuda.
Quiero hacer un pequeño juego, cutre, para el proyecto final de FP. Llevo varios días leyendo sobre DirectX,XNA... y tras decidirme hace un par de días por usar las librerías DirectX directamente no me surgen nada más que inconvenientes.
El último que me ha surgido y el que me impide empezar (por fin) a programar es que no puedo crear el Device.
Agrego las referencias
| Cita: | Imports Microsoft.DirectX
Imports Microsoft.DirectX.Direct3D |
y al intentar crear el device
| Cita: |
Public Class gameEngine
Dim _dispositivo As Direct3D.Device
End Class
|
El Visual Studio 2010 me dice: "el tipo Direct3D.Device no está definido"
He probado a ponerlo de varias formas de escribirlo, pero ese no es el problema. No puedo instanciar el Device.
Lo único que he visto al buscar y que me pueda resultar útil es que he encontrado en la MSDN el objeto Device en otro espacio de nombre:
Espacio de nombres: Microsoft.WindowsMobile.DirectX.Direct3D
He pensado en agregar ese espacio de nombres, pero me faltan las librerías que tengo que referenciar. También me surge la duda que en en la página de Microsoft sobre directx hace referencia a WindowsMobile para smartphones y pocket PC, la duda es si vale para programar juegos en PC.
Ya no se si no puedo usar las DirectX como tal y lo tengo que usar a través de XNA (que también lo intenté probar antes de decantarme por DirectX a pelo y tuve problemas por eso lo dejé), en fin, me gustaría seguir este tutorial de WhiteSkull que está muy bien (felicidades), pero....
A ver si alguno me podéis dar ese empujón que me falta para comenzar.
Gracias por leer. |
|
|
|
| Volver arriba |
|
|
WhiteSkull Moderador Global

Registrado: 20 Mar 2009 Mensajes: 2084 Ubicación: y*width+x
|
|
| Volver arriba |
|
|