Page 1

Tutorial de directx para el desarrollo de simulaciones y aplicaciones 3D Rodrigo Gutiérrez Marín Carlos Andrés Osorio Zúñiga Universidad Autónoma de Occidente Calle 25 No. 115-85 Cali(Colombia) E-mail: roci116@hotmail.com, karlosandres82@hotmail.com

©2004 Rodrigo Gutiérrez .M., Carlos A. Osorio. Z. – Todos los derechos Reservados Objetivo General •

Implementar un tutorial de DirectX a manera de brindar una guía de trabajo para que cualquier persona pueda manipular esta herramienta y poder realizar simulaciones en 3D de cualquier sistema sencillo.

Objetivos Específicos •

Aprender a desarrollar una aplicación en DirectX realizando un ejemplo paso a paso.

Desarrollar conocimientos y destrezas en la manipulación de la herramienta DirectX por medio de Visual Basic.

Aprender a crear las piezas con una extensión (.X) para utilizarlas en una aplicación DirectX.

Manipular algunas de las herramientas de visualización y animación con que cuenta DirectX.

1


INTRODUCCIÓN

En la actualidad para la realización de cualquier tipo de proyecto, las simulaciones asistidas por computador se han convertido en una gran herramienta para ingenieros y diseñadores entre otros, ya que por medio de prototipos virtuales que se asemejen al máximo a la realidad es posible representar el comportamiento de cualquier

sistema,

en

aspectos

tales

como:

eficiencia,

posibles

fallas,

funcionamiento ante determinadas condiciones internas y externas, entre otros. Direct X, es una herramienta que permite manipular imágenes en 3D y Visual Basic es un programa con el que se pueden realizar animaciones en ambientes virtuales de sistemas y mecanismos por medio de un código de programación, además permite crear la interfaz de comunicación entre las piezas de la planta física y el controlador implementado; gracias a su compatibilidad.

2


TUTORIAL DE DIRECTX PARA EL DESARROLLO DE SIMULACIONES Y APLICACIONES 3D

Interfaz Gráfica. Generalmente al elaborar cualquier tipo de proyecto se diseña una interfaz grafica de manera que se tenga una idea de que funciones va a realizar dicho sistema, así como los botones que se utilizaran, los datos que necesita y los que entrega. Una forma mas fácil de comunicar a los demás el funcionamiento de un sistema es mostrando su desempeño en el tiempo, sus capacidades, limitaciones y rangos de trabajo. DirectX es una potente herramienta para que ingenieros y diseñadores muestren de una manera ordenada y practica, el desarrollo de sus creaciones. En las aplicaciones creadas en DirectX se puede ver el funcionamiento esperado de un producto, su estética, diseño y en algunas ocasiones señales y datos que intervienen en él.

3


Figura 1. Interfaz Grafica del Sistema PĂŠndulo Invertido Rotacional.

4


DESARROLLO DEL PROGRAMA

Cuando se desea trabajar con la herramienta de DirectX desde el entorno de Visual Basic, se deben tener en cuenta algunos puntos para poder correr un programa de la manera correcta sin que este presente errores e incoherencias en el tipo de variables que se usan con DirectX. Para empezar, debemos abrir un proyecto nuevo en Visual Basic (EXE estándar) y como primera medida, ir al menú Proyecto y seleccionar Referencias... ; en la lista se debe marcar el check box de "DirectX 7 for Visual Basic Type Library” y pulsar OK.

Figura 2. Referencia para Utilizar DirectX en un Proyecto.

Para seguir con este tutorial es indispensable el manejo de un control ActiveX para el manejo de DirectX llamado RMControl, el cual será el objeto que contenga la visualización y sobre el cual se manipulen las propiedades de la animación. Al ser un componente, este se puede agregar yendo al menú Proyecto y seleccionando 5


Componentes... o con la combinación (Ctrl. + T) allí se examina la ubicación en donde tengamos este componente y se selecciona el “rmcontrol.ocx” y se escoge para ser agregado al proyecto.

Figura 3. Control ActiveX para utilizar RMCanvas.

La utilización del control ActiveX (rmcontrol.ocx) disminuye en una gran parte los comandos de inicialización para los objetos en DirectX y además por ser un objeto contenedor, toda la manipulación de cámaras, colores, texturas, inserción de nuevos objetos, etc, se harán directamente sobre el objeto mencionado de tipo RMCanvas. Cabe decir a esta altura del tutorial que la manipulación de DirectX se hará en modo de ventana y es necesario informar a quien este interesado, que el manejo con pantalla completa, tiene una manipulación totalmente distinta que no se tendrá en cuenta en este tutorial. Para entrar en materia de una vez, después de haber realizado los pasos anteriores y tener todos los componentes y referencias bien establecidas y listas,

6


se puede iniciar el desarrollo en DirectX. En el formulario principal donde se efectuara la animación, (Form1 por defecto) se debe insertar un objeto RMCanvas que se encuentra en la barra general al lado izquierdo del entorno de diseño (ver parte izquierda de la figura 4), este objeto debe ser tan grande como se quiera que sea la ventana donde se visualizaran los objetos 3D. Este objeto debe llamarse de modo que lo identifiquemos claramente en cualquier parte y en cualquier momento del programa, el nombre que utilizaremos en este caso es el de “espacio” tratando de recordar que este será nuestro espacio de trabajo. (Para cambiar el nombre del objeto, lo seleccionamos y en la barra de propiedades al lado derecho de la ventana de diseño, cambiamos el campo nombre, RMCanvas por espacio; Parte derecha de la Figura 4).

Figura 4. Ubicación del componente RMCanvas y de la propiedad Nombre.

7


De ahora en adelante se mostrara el código que se debe utilizar para la inicialización de DirectX en el proyecto y para la declaración de todas las variables que se han de utilizar en la animación. Entre este grupo de variables para la animación, se puede observar que todas son de tipo publicas (Public), por lo tanto desde cualquier lugar del programa se puede acceder a ellas, además para entrar en el modo de programación en 3D con DirectX hay tres tipos de objetos básicos; •

El tipo Direct3DRMFrame3 que son los objetos que contienen todas las propiedades de ubicación y jerarquías de las piezas que se utilizaran en la animación.

El tipo Direct3DRMMeshBuilder3 que son los que contienen las texturas de las piezas, las relaciones de geometría, las propiedades de iluminación, material, sombras, etc.

Y el tipo RMCanvas que se menciono anteriormente, el cual presenta una gran cantidad de propiedades para utilizar en la animación, tales como, luces ambientales, resolución, ubicación de cámaras, color del fondo, sombras, renderizado y todos los eventos relacionados a un objeto en el entorno Visual Basic, tales como, MouseDown, MouseUp, MouseMove, etc.

La carga de piezas, las configuraciones de las cámaras, los colores de las luces, etc se hacen en el procedimiento Form_Load(), pero las características se pueden cambiar en cualquier parte del programa ya que todas las variables son publicas. Teniendo claras las características y tipos de los objetos anteriormente mencionados, se puede iniciar la programación. Unas características interesantes del objeto “espacio” es el color de fondo y las luces; para modificar el fondo, se utiliza la siguiente línea de código:

8


espacio.SceneFrame.SetSceneBackgroundRGB R, G, B

(1)

Donde R, G, y B son valores entre 0 y 255 que se escogen dependiendo del color que se quiera colocar en el fondo, siendo estos valores una combinación de rojo, verde y azul. Por ejemplo:

Figura 5. Combinación RGB para los colores del fondo. Color

R

G

B

Rojo

255

0

0

Azul

0

0

255

Verde

0

255

0

Blanco

255

255

255

Negro

0

0

0

Violeta

0.4

0.3

0.8

Para modificar las luces, se utiliza una función similar a la anterior en lo que tiene que ver al manejo de colores: espacio.AmbientLight.SetColorRGB R, G, B

(2)

Después de cambiar el fondo y las luces, se pueden importar las piezas que realizaran la animación, para esto, en las declaraciones generales del Form1 (parte superior del código) se debe crear un objeto contenedor de todos los demás que se vallan a importar, por eso, este es uno de los objetos mas importantes ya que es el que tendrá la mayor jerarquía o en otras palabras será el que represente

9


a todos los demás. Este objeto se puede llamar de cualquier manera, en este tutorial se escogió el nombre de “todo” ya que será el que contenga todas las piezas del sistema; el objeto todo se declara de la siguiente manera: Public todo As Direct3DRMFrame3

(3)

Para importar los objetos que se quieren agregar en la animación, se deben tener en cuenta dos cosas: que los archivos a importarse tengan la extensión .X para que visual Basic con las instrucciones de DirectX pueda cargar las propiedades de materiales, texturas y las mallas (propiedades geométricas) que tienen establecidas las piezas y además se debe garantizar que en el archivo solo exista una sola pieza. Para observar las piezas .X se puede utilizar el programa 3D exploration de acceso publico el cual muestra todas las características de un archivo con esta extensión. Para Recordar: Se crea en el Form1 del proyecto un objeto de tipo RMCanvas el cual se nombra “espacio”, el paso siguiente es declarar en la parte general del Form1 los objetos que se deben utilizar; al cargar una pieza (*.X). Para esto se deben declarar dos objetos: Public Nombre_de_la_Pieza As Direct3DRMFrame3

(4)

Public Nombre_de_la_Pieza _m As Direct3DRMMeshBuilder3 Como se menciono anteriormente, Direct3DRMFrame3 contiene las propiedades de

ubicación

(principalmente)

y

Direct3DRMMeshBuilder3

contiene

las

propiedades geométricas. Si se ha llegado a manejar el entorno Visual Basic, se sabe que para referirse a un objeto o a una variable en todas las líneas de código se utiliza: 10


With Nombre_de_la_Variable (5) End With Y en la mitad de la instrucción (5) se escriben las líneas de código que tengan que ver con la variable. En el procedimiento Form_Load se usa lo anterior para referirse a “espacio” e importar las piezas que requiera la animación, así: With espacio Set todo = .D3DRM.CreateFrame(.SceneFrame) . StartWindowed

(6) Set Base_en_I = .D3DRM.CreateFrame(.SceneFrame) Set Base_en_I_m = .D3DRM.CreateMeshBuilder() Base_en_I_m.LoadFromFile App.Path + "\Base_en_I.x", 0, D3DRMLOAD_FROMFILE, Nothing, Nothing Base_en_I.AddVisual Base_en_I_m

End With

La

primera

instrucción

dentro

.D3DRM.CreateFrame(.SceneFrame)),

del

método

anterior

(Set

Base_en_I

=

es para ligar el objeto que se creo anteriormente

(todo) al “espacio”. Como menciono hace un momento, el objeto “todo” es aquel de donde se derivaran los demás, por lo tanto este tiene que estar directamente conectado con el espacio total de trabajo para después ligar por medio de jerarquías los objetos insertados a otros o a “todo”. 11


La línea (.StartWindowed) configura el espacio de trabajo a trabajar en ventana como se tenía establecido. Las 4 líneas de código siguientes son la forma de importar un archivo .X a la animación que se esta realizando, las letras en azul son el nombre de la variable en la cual se quiere importar el archivo. En este caso se quiere crear un objeto llamado Base_en_I con las propiedades que contiene el archivo (en rojo) Base_en_I.x, es claro que entre comillas se escribe la ruta donde se encuentra ubicado el archivo; en este caso, el archivo se debe encontrar en la misma carpeta donde se creo el proyecto. Es un poco imperceptible que para importar un archivo .X a la animación se necesiten 2 variables, pero hay que recordar que se necesita una variable para la ubicación y otra para las propiedades de geometría, que en este caso se llama Base_en_I_m. Hasta ahora lo que se lleva de código debe mostrar lo siguiente:

Figura 6. Presentación de la Primera pieza en la Animación.

12


Y el código implementado debe ser similar al siguiente: Public todo As Direct3DRMFrame3

'objeto principal del cual se derivan todos.

'---------declaración de piezas--------------------Public Base_en_I As Direct3DRMFrame3 Public Base_en_I_m As Direct3DRMMeshBuilder3 Private Sub Form_Load() espacio.SceneFrame.SetSceneBackgroundRGB 0.4, 0.3, 0.8 'color de fondo espacio.AmbientLight.SetColorRGB 100, 0, 0

'color de luz ambiental

(7)

With espacio Set todo = .D3DRM.CreateFrame(.SceneFrame) .StartWindowed Set Base_en_I = .D3DRM.CreateFrame(.SceneFrame) Set Base_en_I_m = .D3DRM.CreateMeshBuilder() Base_en_I_m.LoadFromFile App.Path + "\Base_en_I.x", 0, D3DRMLOAD_FROMFILE, Nothing, Nothing Base_en_I.AddVisual Base_en_I_m End With End Sub

Para observar la pieza importada de una mejor manera, se puede tener en cuenta otro tipo de propiedad que presenta DirectX; el manejo de cámaras. Si se mira un poco atrás, el objeto que representa DirectX en esta aplicación es el objeto “espacio” (de tipo RMCanvas) y este por defecto posee las cámaras, solamente se deben manipular (todas las instrucciones se colocan dentro del With). La instrucción para realizar los movimientos de cámara es la siguiente: espacio.CameraFrame.SetPosition Nothing, X, Y, Z

13

(8)


Siendo X, Y, Z las coordenadas donde se quiere colocar la cámara, (Z entrando en la pantalla); de este modo si se le da un valor de –100 a Z en la instrucción, la pieza se vera más pequeña:

Figura 7. Manejo de la cámara en el eje Z.

Al dar coordenadas a la cámara en X (eje horizontal) e Y (eje vertical) se puede mover el foco de la cámara como se requiera. En este punto del programa es indispensable mencionar las jerarquías, su uso, implementación y razón. Estas propiedades se utilizan en DirectX para ensamblar unas piezas con otras y para generar las rotaciones y traslaciones de varias piezas a la vez. Observe un ejemplo sencillo.

14


Figura 8. Ejemplo de Jerarquías. Mano

Muñeca Antebrazo Hombro

Codo Brazo

Las articulaciones de la extremidad superior derecha y sus huesos, representarían las partes del sistema, así, se conoce que cuando se mueve el hombro, se mueven todas las partes de la extremidad (el brazo, el codo, el antebrazo, la muñeca y el puño), por lo tanto el hombro será el padre de todos los demás. Así el hombro será el padre del brazo, este a su vez será el padre del codo, el codo será el padre del antebrazo, el antebrazo será el padre de la muñeca y la muñeca será el padre de la mano. Viéndolo de otra manera, la mano será hija se la muñeca, la muñeca será hija del antebrazo y así sucesivamente hasta llegar al hombro. Esta es la forma de establecer las jerarquías de un sistema, y en el ejemplo del péndulo invertido rotacional las jerarquías se establecen así:

15


Figura 9. Jerarquías en el Péndulo Invertido Rotacional.

Barra Vertical Acople_B

Base en L

Motor

Base en I

Barra Horizontal

Acople_P

Base en C

En la figura 9, la Barra vertical es hija de Acople_P, Acople_P es hijo de Barra Horizontal, Barra Horizontal es Hija de Acople_B, Acople_B es hijo del Motor, El Motor es hijo de la Base en L, la base en L es hija de la Base en I y la Base en C también es hija de la Base en I. En DirectX para agregar las jerarquías se usa la siguiente instrucción (9): Padre.AddChild Hijo

(9)

Y así, sí se mueve o rota la pieza Padre, su hijo se desplazara o girara con ella. Con el concepto de jerarquías claro, se pueden importar todas las piezas a la ventana de animación (se sugiere que se haga 1 a 1) para ensamblarlas y dejar listo el modelo en 3D del sistema. La primera jerarquía que se debe establecer es la de “todo” (objeto contenedor de todo el ensamble) y la pieza con mayor jerarquía en el ensamble. En el ejemplo del péndulo la pieza con mayor jerarquía es la Base en I. La línea a agregar en el código es la siguiente (10): 16


todo.AddChild Base_en_I

(10)

Para agregar la segunda pieza que hace parte del sistema (Base en C) se usan las mismas instrucciones que para la base en I; primero se declaran en la parte superior del código, (11)

Public Base_en_C As Direct3DRMFrame3 Public Base_en_C_m As Direct3DRMMeshBuilder3

y después se importa el archivo correspondiente (.X) en el procedimiento Form_Load pero sin olvidar que se hace dentro del With del objeto “espacio” Set Base_en_C = .D3DRM.CreateFrame(.SceneFrame) Set Base_en_C_m = .D3DRM.CreateMeshBuilder() Base_en_C_m.LoadFromFile App.Path + "\Base_en_C.x", 0,D3DRMLOAD_FROMFILE,Nothing, Nothing Base_en_C.AddVisual Base_en_C_m

Figura 10. Vista de las dos primeras piezas Importadas en la animación.

17

(12)


Para observar el modelo en 3D las jerarquías de todas las piezas importadas ya deben estar establecidas,

de esta forma cada que importemos una pieza

debemos establecer su jerarquía (13). Para la pieza agregada (Base_en_C) la jerarquía es la siguiente: Base_en_I.AddChild Base_en_C

(13)

De la figura 10 se puede observar que la Base en C no se encuentra en la posición adecuada por lo que es necesario moverla solo en –Y

y en –X

(aparentemente) por medio de la instrucción (14) Pieza_a_Mover.SetPosition Obj_Referencia, X, Y, Z

(14)

Y específicamente en el ejemplo: Base_en_C.SetPosition todo, -6.2, -25.2, 0

(15)

Permitiendo de esta manera que las piezas queden bien ubicadas. NOTA: el posicionamiento de las piezas se debe realizar una línea antes de establecer las jerarquías, para obtener buenos resultados.

18


Figura 11. Ubicaci贸n adecuada de la Base en C

Hasta ahora el c贸digo implementado debe ser similar al siguiente: ___________Parte 1_______________________________________________________________________________

Public todo As Direct3DRMFrame3

'objeto principal del cual se derivan todos.

'---------declaraci贸n de piezas--------------------Public Base_en_I As Direct3DRMFrame3

'objeto 1

Public Base_en_I_m As Direct3DRMMeshBuilder3 Public Base_en_C As Direct3DRMFrame3

'objeto 2

Public Base_en_C_m As Direct3DRMMeshBuilder3

(16) Private Sub Form_Load() espacio.SceneFrame.SetSceneBackgroundRGB 0.4, 0.3, 0.8

'color de fondo

espacio.AmbientLight.SetColorRGB 100, 0, 0

'color de luz ambiental

With espacio Set todo = .D3DRM.CreateFrame(.SceneFrame) .StartWindowed

19


___________Parte 2_______________________________________________________________________________ Set Base_en_I = .D3DRM.CreateFrame(.SceneFrame) Set Base_en_I_m = .D3DRM.CreateMeshBuilder() Base_en_I_m.LoadFromFile App.Path + "\Base_en_I.x", 0, D3DRMLOAD_FROMFILE, Nothing, Nothing Base_en_I.AddVisual Base_en_I_m Set Base_en_C = .D3DRM.CreateFrame(.SceneFrame) Set Base_en_C_m = .D3DRM.CreateMeshBuilder() Base_en_C_m.LoadFromFile App.Path + "\Base_en_C.x", 0,D3DRMLOAD_FROMFILE,Nothing, Nothing Base_en_C.AddVisual Base_en_C_m ___________Parte3_______________________________________________________________________________ Base_en_C.SetPosition todo, -6.2, -25.2, 0 ___________Parte4_______________________________________________________________________________ todo.AddChild Base_en_I Base_en_I.AddChild Base_en_C ___________Parte5_______________________________________________________________________________ espacio.CameraFrame.SetPosition Nothing, 0, 0, -100

'ubic. de la cámara

End With End Sub

En la parte superior del código (parte 1) se encuentran las declaraciones generales; en la parte 2 el llamado a las piezas (importar el archivo) en la parte 3 las posiciones iniciales de las piezas (para ensamblarlas) en la parte 4 la asignación de jerarquías y en la parte 5 la ubicación de la cámara. Cuando la pieza se encuentra en su posición tanto en X como en Y y Z insertamos otra pieza y repetimos el proceso una vez mas. Pero en Z no se sabe si la pieza esta bien ubicada, por lo tanto, se debe girar el modelo (todo) para saber si esta

20


bien. Esto se hace con la instrucción (17) que se debe agregar en la parte 5 del código: Obj_a_Rotar.AddRotationD3DRMCOMBINE_AFTER, X, Y, Z, (Ang_en_Rad)

(17)

Siendo X,Y o Z el eje o los ejes sobre los que se quiere rotar, colocando un “1” sobre el que se quiera hacer la rotación y entre paréntesis el angulo en radianes. En el péndulo se escribe: todo.AddRotation D3DRMCOMBINE_AFTER, 0, 1, 0, (45 * deg2rad)

(18)

Siendo deg2rad una constante (P / 180) para transformar el angulo escrito a radianes, y asi girar un angulo de 45° en el eje Y.

Figura 12. Visualización después de girar el modelo.

21


y se nota que no se visualiza por completo la Base en C, debido a que el objeto que realiza la visualización (espacio) no cuenta con un buffer de profundidad adecuado, por lo tanto se debe ampliar (19), agregando la siguiente línea de código después de la rotación anterior (18): Variable.Viewport.SetBack Valor_Profundidad_deseada

(19)

En el péndulo: espacio.Viewport.SetBack 5000

(20)

De esta manera, se puede realizar el ensamble y manejar las cámaras de la forma que se quiera. Después de cambiar el buffer de profundidad, la visualización queda de la siguiente manera: Figura 13. Visualización con un Buffer de Profundidad adecuado.

El resto de piezas se insertan y se ubican de la misma manera, el código para el ensamble completo es el siguiente: 22


Const deg2rad = 3.1416 / 180 Const rad2deg = 180 / 3.1416 Const pi = 3.141592654

(21)

'------obj principal----------------------------Public todo As Direct3DRMFrame3

'objeto principal del cual se derivan todos.

'---------declaracion de piezas--------------------Public Base_en_I As Direct3DRMFrame3 Public Base_en_I_m As Direct3DRMMeshBuilder3 Public Base_en_C As Direct3DRMFrame3 Public Base_en_C_m As Direct3DRMMeshBuilder3 Public Base_en_L As Direct3DRMFrame3 Public Base_en_L_m As Direct3DRMMeshBuilder3 Public motor As Direct3DRMFrame3 Public motor_m As Direct3DRMMeshBuilder3 Public acople_B As Direct3DRMFrame3 Public acople_B_m As Direct3DRMMeshBuilder3 Public barra_h As Direct3DRMFrame3 Public barra_h_m As Direct3DRMMeshBuilder3 Public acople_p As Direct3DRMFrame3 Public acople_p_m As Direct3DRMMeshBuilder3 Public pend As Direct3DRMFrame3 Public pend_m As Direct3DRMMeshBuilder3 Public barra_p As Direct3DRMFrame3 Public barra_p_m As Direct3DRMMeshBuilder3 Private Sub Form_Load() espacio.SceneFrame.SetSceneBackgroundRGB 0.4, 0.3, 0.8

'color de fondo

espacio.AmbientLight.SetColorRGB 100, 0, 0

'color de luz ambiental

With espacio 'Espacio de trabajo para DirectX dentro del FORM todas las propiedades a agregar, se agregan dentro de este with las piezas, la iluminaci贸n, etc. Set todo = .D3DRM.CreateFrame(.SceneFrame) .StartWindowed '------------ llamado de piezas (archivos)

23


Set Base_en_I = .D3DRM.CreateFrame(.SceneFrame) Set Base_en_I_m = .D3DRM.CreateMeshBuilder() Base_en_I_m.LoadFromFile App.Path + "\Base_en_I.x", 0, D3DRMLOAD_FROMFILE, Nothing, Nothing Base_en_I.AddVisual Base_en_I_m Set Base_en_C = .D3DRM.CreateFrame(.SceneFrame) Set Base_en_C_m = .D3DRM.CreateMeshBuilder() Base_en_C_m.LoadFromFile App.Path + "\Base_en_C.x",0,D3DRMLOAD_FROMFILE,Nothing, Nothing Base_en_C.AddVisual Base_en_C_m Set Base_en_L = .D3DRM.CreateFrame(.SceneFrame) Set Base_en_L_m = .D3DRM.CreateMeshBuilder() Base_en_L_m.LoadFromFile App.Path +"\Base_en_L.x",0, D3DRMLOAD_FROMFILE, Nothing, Nothing Base_en_L.AddVisual Base_en_L_m

Set motor = .D3DRM.CreateFrame(.SceneFrame) Set motor_m = .D3DRM.CreateMeshBuilder() motor_m.LoadFromFile App.Path + "\MOTOR.x", 0, D3DRMLOAD_FROMFILE, Nothing, Nothing motor.AddVisual motor_m Set acople_B = .D3DRM.CreateFrame(.SceneFrame) Set acople_B_m = .D3DRM.CreateMeshBuilder() acople_B_m.LoadFromFile App.Path + "\Acople_B.x", 0, D3DRMLOAD_FROMFILE, Nothing, Nothing acople_B.AddVisual acople_B_m Set barra_h = .D3DRM.CreateFrame(.SceneFrame) Set barra_h_m = .D3DRM.CreateMeshBuilder() barra_h_m.LoadFromFile App.Path + "\Barra_H.x", 0, D3DRMLOAD_FROMFILE, Nothing, Nothing barra_h.AddVisual barra_h_m Set acople_p = .D3DRM.CreateFrame(.SceneFrame) Set acople_p_m = .D3DRM.CreateMeshBuilder() acople_p_m.LoadFromFile App.Path + "\Acople_P.x", 0, D3DRMLOAD_FROMFILE, Nothing, Nothing acople_p.AddVisual acople_p_m Set pend = .D3DRM.CreateFrame(.SceneFrame) Set pend_m = .D3DRM.CreateMeshBuilder() pend_m.LoadFromFile App.Path + "\pend.x", 0, D3DRMLOAD_FROMFILE, Nothing, Nothing

24


pend.AddVisual pend_m Set barra_p = .D3DRM.CreateFrame(.SceneFrame) Set barra_p_m = .D3DRM.CreateMeshBuilder() barra_p_m.LoadFromFile App.Path + "\Barra_V.x", 0, D3DRMLOAD_FROMFILE, Nothing, Nothing barra_p.AddVisual barra_p_m '------------posiciones iniciales Base_en_I.SetPosition todo, 0, 0, 0 Base_en_C.SetPosition todo, -6.2, -25.2, 0 Base_en_L.SetPosition Base_en_I, -3.2, 22.4, 0 motor.SetPosition Base_en_L, -2, -0.2, 0 acople_B.SetPosition motor, 0, 4.6, 0 barra_h.SetPosition acople_B, 13, 0.4, 0 acople_p.SetPosition barra_h, 11.7, -2, 0 pend.SetPosition acople_p, 3.5, -0.15, 0 barra_p.SetPosition pend, 0.75, 21.3, 0 ' ----------- jerarqu铆as todo.AddChild Base_en_I Base_en_I.AddChild Base_en_C Base_en_I.AddChild Base_en_L Base_en_L.AddChild motor motor.AddChild acople_B acople_B.AddChild barra_h barra_h.AddChild acople_p acople_p.AddChild pend pend.AddChild barra_p

'------------ubicaci贸n en la pantalla todo.AddRotation D3DRMCOMBINE_AFTER, 0, 1, 0, (45 * deg2rad) espacio.CameraFrame.SetPosition Nothing, 13, 25, -120

'ubicaci贸n de la c谩mara

espacio.Viewport.SetBack 5000

'calidad de imagen

End With End Sub

25


Y muestra como resultado el ensamble total.

Figura 14. Ensamble Total.

Recordar: Para poder visualizar el modelo e 3D se deben haber establecido las jerarquías de todas las piezas en el ensamble; cuando se esta ensamblando es útil ubicar todo el conjunto de instrucciones para el posicionamiento de las piezas en un mismo sitio, las instrucciones para establecer las jerarquías después del posicionamiento y los movimientos y rotaciones del sistema en otro sitio después de todo lo anterior (un buen ejemplo de código y organización es la que se dio en el código (21). Algunas veces es necesario girar algunas piezas para el posicionamiento inicial durante el ensamble, aunque en el ejemplo del péndulo no fue necesario realizarlo, la instrucción para llevar a cabo esta operación es:

26


Obj_a_Rotar.AddRotationD3DRMCOMBINE_AFTER, X, Y, Z, (Ang_en_Rad) Que fue la misma con la que se roto todo el sistema (18), solo que en el caso de rotar una pieza, se cambia Obj_a_Rotar por el nombre de la pieza.

27


MANEJO DE CAMARAS

La forma mas sencilla de implementar el manejo de cámaras se puede visualizar en la siguiente imagen:

Figura 15. Botones Agregados a la aplicación para las cámaras.

El ejemplo consiste en manualmente con el uso de botones de comando se logre un desplazamiento de la cámara en todas las direcciones, para esto es necesario la creación de variables que guarden el valor en cada momento de la posición de la cámara, en el ejemplo se llaman camarax, camaray, camaraz, estas variables inician con un valor especifico (el que se le dio para visualizar el ensamble de forma correcta en el código completo de la aplicación) y luego cuando se de click

28


en cualquiera de los comandos de la cámara, se sume o se reste a la variable de posición guardada según sea el caso. Si se da click en Cámara X menos, la variable camarax, se tendrá que remplazar por camarax - 5 con el objetivo de que la cámara se desplace 5 unidades hacia la izquierda, veamos: Private Sub CXmenos_Click() camarax = camarax - 5 espacio.CameraFrame.SetPosition Nothing, camarax, camaray, camaraz

(22)

espacio.Render End Sub

La segunda línea dentro del procedimiento corresponde a la forma como se ubica la cámara en el espacio (8), pero con las variables o la variable que se cambio, ya actualizada, este cambio solo se observa cuando se renderiza de nuevo la ventana, por lo tanto la tercera línea corresponde a la renderizacion y no se debe olvidar que después de realizar cualquier movimiento de cámara o de piezas se debe renderizar para poder observar el cambio. La estructura de la instrucción para renderizar es la siguiente: Obj_RMCanvas.Render

(23)

De igual manera se implementa el desplazamiento hacia la derecha, arriba, abajo y el zoom que consiste simplemente en un desplazamiento de la cámara en el eje Z. La función restaurar, como su nombre lo indica reinicializa las variables de la cámara con los valores iniciales en las tres coordenadas (24).

(24)

Private Sub restore_Click() camarax = 13

29


camaray = 20 camaraz = -100 espacio.CameraFrame.SetPosition Nothing, camarax, camaray, camaraz espacio.Render End Sub Private Sub CXmas_Click() camarax = camarax + 5 espacio.CameraFrame.SetPosition Nothing, camarax, camaray, camaraz espacio.Render End Sub Private Sub CXmenos_Click() camarax = camarax - 5 espacio.CameraFrame.SetPosition Nothing, camarax, camaray, camaraz espacio.Render End Sub Private Sub CYmas_Click() camaray = camaray + 5 espacio.CameraFrame.SetPosition Nothing, camarax, camaray, camaraz espacio.Render End Sub Private Sub CYmenos_Click() camaray = camaray - 5 espacio.CameraFrame.SetPosition Nothing, camarax, camaray, camaraz espacio.Render End Sub Private Sub Zmas_Click() camaraz = camaraz + 5 espacio.CameraFrame.SetPosition Nothing, camarax, camaray, camaraz espacio.Render End Sub Private Sub Zmenos_Click() camaraz = camaraz - 5

30


espacio.CameraFrame.SetPosition Nothing, camarax, camaray, camaraz espacio.Render End Sub

Las rotaciones en DirectX es un aspecto un poco complejo de implementar y en este caso no se hará énfasis en esto, pero una forma muy útil de realizarlas es con códigos que otros programadores han utilizado y son de fácil adquisición en Internet, aquí presentaremos el que se utilizo en la aplicación final de la aplicación que simula un péndulo invertido rotacional:

Public Sub RotateTrackBall(X As Integer, Y As Integer) Dim delta_x As Single, delta_y As Single Dim delta_r As Single, radius As Single, denom As Single, angle As Single ' rotation axis in camcoords, worldcoords, sframecoords Dim axisC As D3DVECTOR Dim wc As D3DVECTOR Dim axisS As D3DVECTOR Dim Base_en_C As D3DVECTOR Dim origin As D3DVECTOR delta_x = X - m_lastX delta_y = Y - m_lastY m_lastX = X m_lastY = Y delta_r = Sqr(delta_x * delta_x + delta_y * delta_y) radius = 50 denom = Sqr(radius * radius + delta_r * delta_r) If (delta_r = 0 Or denom = 0) Then Exit Sub angle = (delta_r / denom) axisC.X = (-delta_y / delta_r) axisC.Y = (-delta_x / delta_r) axisC.z = 0 Form1.Espacio.CameraFrame.Transform wc, axisC todo.InverseTransform axisS, wc Form1.Espacio.CameraFrame.Transform wc, origin todo.InverseTransform Base_en_C, wc

31

(25)


axisS.X = axisS.X - Base_en_C.X axisS.Y = axisS.Y - Base_en_C.Y axisS.z = axisS.z - Base_en_C.z axisS.X = axisS.X * roty axisS.z = axisS.z * roty todo.AddRotation D3DRMCOMBINE_BEFORE, axisS.X, axisS.Y, axisS.z, angle End Sub

32


ANIMACIÓN

La animación consiste en dar movimiento coordinado o adecuado a las partes del sistema cumpliendo una base de reglas, ecuaciones o necesidades. Esto en DirectX se logra con traslaciones, movimiento o rotaciones. Las piezas siempre giran en torno a sus ejes coordenados y estos se establecen cuando se construyen las piezas y se crean los archivos .X si por ejemplo, una pieza circular no tiene su eje en su centro, esta al girar con respecto a ese eje no lo hará de forma adecuada (rotara de forma excéntrica). Por esta razón en esta altura del programa, es indispensable la buena realización de las piezas. La animación es simple y cosiste en mover lo que se quiera desplazar y girar lo que se quiera rotar, se hace esta afirmación ya que los ejes de las piezas son móviles y las piezas solo se unen por sus jerarquías ya establecidas, las cuales restringen los grados de libertad; por ejemplo, en el péndulo se tienen 2 grados de libertad rotacionales, y las articulaciones que permiten estos movimientos son acople_B y pend para los grados de libertad fi ( ) en el brazo y teta ( ) en el péndulo respectivamente. Por lo tanto teniendo en cuenta las jerarquías, si se mueve o rota acople_B se deben mover o rotar todos sus hijos (barra_h, acople_p y pend). Y pend como es el último hijo y rota también, solo debe rotar con respecto al eje establecido (cuando rota acople_B se mueve el eje de pend). Las instrucciones para llevar a cabo las rotaciones y traslaciones son: Pieza_a_Rotar.AddRotation D3DRMCOMBINE_AFTER, X, Y, Z, angulo_en_rad

Pieza_a_Desplazar.AddTranslation D3DRMCOMBINE_AFTER, X, Y, Z

33

(26)


Pieza_a_Mover.SetPosition Pieza_Referencia, X, Y, Z

La primera instrucción (26) rota la pieza con respecto a su eje (X, Y o Z según se escoja y se coloque “1”) un ángulo especifico (en radianes). La segunda instrucción desplaza la pieza desde el punto actual hasta las coordenadas finales que establezcan el X, Y, Z que se utilice (el origen es el punto actual donde se encuentra la pieza antes de ser movida). La tercera instrucción mueve de manera absoluta la pieza que se quiere con respecto a otra pieza (pieza de referencia). Cualquiera de las tres opciones se puede usar dependiendo de la aplicación, en el péndulo se utilizan dos rotaciones como se menciono anteriormente y cabe decir que después de realizar la traslación, movimiento o rotación se tiene que renderizar para observar el movimiento. En el ejemplo que se hará a continuación, se utiliza la posición de un par de barras de desplazamiento para fijar los ángulos que se van moviendo tanto la barra horizontal (con fi ) como la barra vertical (con ). En el Form 1 se debe tener lo siguiente:

34


Figura 16. Barras de Desplazamiento agregadas a la aplicación para la animación.

Las dos barras tienen como limite inferior 0 y como superior 360 que sería una vuelta completa. En el procedimiento que se ejecuta cada vez que la barra cambie se debe agregar el código (27) para teta: Private Sub V_teta_Change()

Text1.Text = V_teta.Value

(27)

teta = Val(Text1.Text) animación teta, fi End Sub

Y el (28) para fi: Private Sub V_fi_Change()

Text2.Text = V_fi.Value fi = Val(Text2.Text) animacion teta, fi End Sub

35

(28)


Como se observa, la barra teta se llama V_teta (27) y la barra fi se llama V_fi (28) y se almacena en la variable teta y la variable fi respectivamente, el valor actual de la barra de desplazamiento, pasando después los valores de teta y fi adquiridos a la función animación. La función Animación consiste en mover los elementos que se necesita en el modelo (acople_B y pend) con los parámetros establecidos que se le pasaron ( y ), la función es la (29): Sub animacion(teta1 As Double, fi1 As Double)

pend.AddRotation D3DRMCOMBINE_AFTER, 1, 0, 0, ((teta1 - teta_a) * deg2rad)

(29)

acople_B.AddRotation D3DRMCOMBINE_AFTER, 0, 1, 0, ((fi1 - fi_a) * deg2rad) teta_a = teta1 fi_a = fi1 espacio.Render End Sub

Donde solamente cabe aclarar que el ángulo se debe mover de forma incremental, y si la barra de desplazamiento tenia por ejemplo el valor 2 y se movió al valor 3 el angulo que se debe mover en la animación es la diferencia, entre el angulo actual y el anterior (3 – 2 = 1) y esta es la manipulación que se hace en la función animación con las variables teta_a y fi_a y el angulo que se le paso a la función ( y ).

36


Figura 17. Movimiento de 90ยบ para fi ( )

Figura 18. Movimiento de 90ยบ para teta ( )

En la figura 17 se ve una posiciรณn de 90 grados para la barra horizontal y en la figura 18, un giro de 90 grados para la barra pendular.

37


De esta manera y dependiendo de la habilidad que se tenga en el manejo de Visual Basic se pueden hacer animaciones mรกs complejas o mรกs simples.

38


IMPLEMENTACION DE ECUACIONES DIFERENCIALES

Si en la animación se quiere mostrar el comportamiento real del sistema, el cual se da (en la mayoría de ocasiones) en ecuaciones diferenciales se deben tener en cuenta algunas cosas: •

Tener un algoritmo para la solución numérica de las ecuaciones diferenciales.

Conocer los límites que tiene el modelo matemático e implementarlos para que se logre una animación adecuada.

Preferiblemente tener las ecuaciones del sistema en variables de estado.

Un algoritmo adecuado para la solución numérica de sistemas de ecuaciones diferenciales es Runge_Kutta. Si se tienen las ecuaciones del sistema en variables de estado (30).

dy1 = f1 (t , y1 , y 2 ... y n ) dt dy 2 = f 2 (t , y1 , y 2 ... y n ) dt ... dy n = f n (t , y1 , y 2 ... y n ) dt

Se puede implementar el siguiente algoritmo

39

(30)


PASO 1:

Asignar h, inicializar t =a y asignar las condiciones iniciales a y1 Donde a es el tiempo inicial de la ecuaciรณn, h es el paso o incremento que se darรก en el tiempo e i es la iteraciรณn actual.

PASO 2:

Incrementar i en cada iteraciรณn del algoritmo

PASO 3:

Calcular los valores de K que estimaran la soluciรณn numรฉrica.

K1 = h f (t , y1 ) K 2 = h f (t + h / 2, y1 + K1 / 2) K 3 = h f (t + h / 2, y1 + K 2 / 2) K 4 = h f (t + h, y1 + K 3 )

(31)

Donde y1 es la soluciรณn actual a la ecuaciรณn diferencial y solo se esta haciendo el calculo de las constantes K para 1 variable, en el caso del sistema de ecuaciones completo salen cuatro constantes para cada variable.

PASO 4:

Calcular la salida actual de la ecuaciรณn diferencial. y1 = y1 + ( K 1 + 2 K 2 + 2 K 3 + K 4 ) / 6

PASO 5:

(32)

Asignar la salida de la ecuaciรณn diferencial Salida (t , y1) y volver al paso 2 para una prรณxima iteraciรณn.

PASO 6:

PARAR

Y la implementaciรณn en Visual Basic para el sistema de 4 ecuaciones es la siguiente: Function Runge_Kutta()

40


Dim k11, k12, k13, k14 As Double 'los k1 para las ecuaciones Dim k21, k22, k23, k24 As Double 'los k2 para las ecuaciones Dim k31, k32, k33, k34 As Double 'los k3 para las ecuaciones Dim k41, k42, k43, k44 As Double 'los k4 para las ecuaciones 'X es el tiempo que se incrementa de acuerdo al paso X = h * i2 k11 = h * x1p(X, y1, y2, y3, y4) k12 = h * x3p(X, y1, y2, y3, y4) k13 = h * x2p(X, y1, y2, y3, y4) k14 = h * x4p(X, y1, y2, y3, y4) k21 = h * x1p(X + h / 2, y1 + k11 / 2, y2 + k12 / 2, y3 + k13 / 2, y4 + k14 / 2) k22 = h * x3p(X + h / 2, y1 + k11 / 2, y2 + k12 / 2, y3 + k13 / 2, y4 + k14 / 2) k23 = h * x2p(X + h / 2, y1 + k11 / 2, y2 + k12 / 2, y3 + k13 / 2, y4 + k14 / 2) k24 = h * x4p(X + h / 2, y1 + k11 / 2, y2 + k12 / 2, y3 + k13 / 2, y4 + k14 / 2) k31 = h * x1p(X + h / 2, y1 + k21 / 2, y2 + k22 / 2, y3 + k23 / 2, y4 + k24 / 2) k32 = h * x3p(X + h / 2, y1 + k21 / 2, y2 + k22 / 2, y3 + k23 / 2, y4 + k24 / 2) k33 = h * x2p(X + h / 2, y1 + k21 / 2, y2 + k22 / 2, y3 + k23 / 2, y4 + k24 / 2) k34 = h * x4p(X + h / 2, y1 + k21 / 2, y2 + k22 / 2, y3 + k23 / 2, y4 + k24 / 2) k41 = h * x1p(X + h, y1 + k31, y2 + k32, y3 + k33, y4 + k34) k42 = h * x3p(X + h, y1 + k31, y2 + k32, y3 + k33, y4 + k34) k43 = h * x2p(X + h, y1 + k31, y2 + k32, y3 + k33, y4 + k34) k44 = h * x4p(X + h, y1 + k31, y2 + k32, y3 + k33, y4 + k34) y1 = y1 + (1 / 6) * (k11 + 2 * k21 + 2 * k31 + k41) y2 = y2 + (1 / 6) * (k12 + 2 * k22 + 2 * k32 + k42) y3 = y3 + (1 / 6) * (k13 + 2 * k23 + 2 * k33 + k43) y4 = y4 + (1 / 6) * (k14 + 2 * k24 + 2 * k34 + k44) i2 = i2 + 1 End Function

41

(33)


x1p es la ecuación 1 en variables de estado implementada en otra función que recibirá los parámetros X, y1, y2, y3, y4 que son:

X = El tiempo y1 = Solución actual a la ecuación diferencial de x1. y2 = Solución actual a la ecuación diferencial de x2. y3 = Solución actual a la ecuación diferencial de x3. y4 = Solución actual a la ecuación diferencial de x4. h, es el valor del paso que se incrementa cada vez (es el incremento de tiempo para solucionar la ecuación). Los valores de k son coeficientes que se utilizan para solucionar el sistema de ecuaciones y calcular los valores siguientes de y1, y2,y3, y4. Las funciones de x2p, x3p y x4p cuentan con los mismos parámetros mencionados anteriormente y sus funciones son las establecidas por el modelo matemático del sistema en variables de estado.

42


CONSTRUCCIÓN DE PIEZAS

Cada una de las piezas que compone el sistema se debe construir de manera independiente en un programa de diseño CAD , en este caso se usara SolidEdge o SolidWorks, y para mayor comodidad se debe procurar construir cada pieza estableciendo un eje de referencia y conservando las respectivas posiciones de cada una de las piezas. Cuando se trabaja con SolidEdge o SolidWorks las piezas se almacenan con una extensión establecida las cuales no son compatibles con DirectX, por lo que es necesario convertirlas a un tipo de extensión (*.X) que es compatible con DirectX, operación que se puede realizar de dos modos; por medio de un programa llamado 3D-Exploration o con 3D Studio Max. Para ligar las piezas construidas en SolidWorks o SolidEdge a cualquiera de estos dos programas, se deben guardar las piezas con una extensión (*.stl) para con la ayuda de los otros programas (3D-Exploration o 3D Studio Max) se exporten las piezas a un formato adecuado para DirectX (*.X). En el caso de que el programa con el que se crean las figuras sea SolidWorks, la ubicación del eje de coordenadas solo importa al final, ya que este se puede definir en el punto que se quiera siendo el punto mas indicado los ejes de simetría o giro de la pieza.

43


Figura 19. Forma de Agregar el eje de coordenadas en SolidWorks.

El paso siguiente es guardar la pieza en formato (*.stl) indicando el sistema de coordenadas con que se quiera guardar.

Figura 20. Guardar la Pieza (*.stl) con un eje de coordenadas establecido.

44


Cuando el programa con que se diseñan las piezas es SolidEdge, se debe asegurar que el eje de coordenadas global del entorno CAD sea el mismo que se necesite para la pieza ya que este no se puede cambiar como en SolidWorks. Cuando la pieza esta lista en formato (*.stl) se puede convertir a (*.X) por medio de 3D Explorartion simplemente exportando la pieza a este formato, pero si por el contrario se usa 3D-StudioMax, se debe utilizar en conjunto con un plugg-in llamado PandaDXExport5 que permite cambiar las texturas y los materiales a las piezas dando una mejor apariencia a estas. Después de tener la pieza con su respectivo material, esta se exporta a (*.X) se guarda y en las opciones que salen a continuación sé escogen todas las opciones menos flip-normal y bones.

Así se concluye este tutorial que busca de forma guiada, dar los conceptos básicos para implementar una aplicación en DirectX con todas sus partes.

45


CONCLUSIONES

La implementación o representación de sistemas a través de herramientas asistidas por computador en entornos virtuales, es de gran importancia en el desarrollo de grandes y pequeños proyectos, ya que es posible estudiar o hacerse una idea del funcionamiento real

de la planta de estudio y su

desempeño ante determinadas condiciones de trabajo. •

Después de adquirir experiencia en el manejo de elementos en DirectX, la animación y la forma de dar movimiento a elementos es sencilla y muy potente.

El manejo de la herramienta de DirectX, es una ayuda muy importante a nivel de la ingeniería ya que para proyectos macros permite ver de manera casi real como se comporta una planta o un proyecto en general que se quiera realizar, ya que en este tutorial se dan las bases necesarias para aprender a manejar el programa de DirectX, sin dejar a un lado que la herramienta plataforma es VisualBasic y es importante aprender a manejarlo bien de manera principal para poder hacer la interfase.

Usted puede distribuir este archivo libremente cuantas veces quiera sin alterar su contenido. De ninguna manera puede ser vendido. ©2004 Rodrigo Gutiérrez .M., Carlos A. Osorio. Z. – Todos los derechos Reservados

46

Tutorial básico Directx 7  

Tutorial básico Directx 7

Read more
Read more
Similar to
Popular now
Just for you