View
238
Download
3
Category
Preview:
DESCRIPTION
Tutorial básico Directx 7
Citation preview
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.
2
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.
3
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.
4
Figura 1. Interfaz Grafica del Sistema Péndulo Invertido Rotacional.
5
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
6
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,
7
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.
8
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:
9
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
10
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:
11
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 del método anterior (Set Base_en_I =
.D3DRM.CreateFrame(.SceneFrame)), 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”.
12
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.
13
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 (8)
14
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.
15
Figura 8. Ejemplo de Jerarquías.
Las articulaciones de la extremidad superior derecha y sus hueso
las partes del sistema, así, se conoce que cuando se mueve
mueven todas las partes de la extremidad (el brazo, el codo,
muñeca y el puño), por lo tanto el hombro será el padre de todos l
hombro será el padre del brazo, este a su vez será el padre del co
el padre del antebrazo, el antebrazo será el padre de la muñeca y
el padre de la mano. Viéndolo de otra manera, la mano será hija
muñeca será hija del antebrazo y así sucesivamente hasta llegar a
Esta es la forma de establecer las jerarquías de un sistema, y e
péndulo invertido rotacional las jerarquías se establecen así:
Hombro
Brazo
An
Mano
Muñeca
tebrazo
Codo
s,
e
o
d
l
se
l
n
representarían
el hombro, se
l antebrazo, la
s demás. Así el
o, el codo será
a muñeca será
la muñeca, la
hombro.
el ejemplo del
16
Figura 9. Jerarquías en el Péndulo Invertido Rotacional.
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):
Barra Vertical
Base en L
Base en C
Acople_B
Motor
Base en I
Barra Horizontal Acople_P
17
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,
Public Base_en_C As Direct3DRMFrame3 (11) 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() (12)
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.
18
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.
19
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
20
___________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
21
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 (π / 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.
22
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:
23
Const deg2rad = 3.1416 / 180 Const rad2deg = 180 / 3.1416 Const pi = 3.141592654
'------obj principal----------------------------- (21)
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)
24
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
25
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
26
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:
27
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.
28
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
29
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).
Private Sub restore_Click() (24) camarax = 13
30
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
31
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) (25) 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
32
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
33
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 (26)
34
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:
35
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 (28) fi = Val(Text2.Text)
animacion teta, fi End Sub
36
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 φ).
37
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.
38
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.
39
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).
(30)
Se puede implementar el siguiente algoritmo
)...,,(
...
)...,,(
)...,,(
21
2122
2111
nnn
n
n
yyytfdt
dy
yyytfdt
dy
yyytfdt
dy
=
=
=
40
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.
(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.
(32)
PASO 5: 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()
),()2/,2/()2/,2/(
),(
314
213
112
11
KyhtfhKKyhtfhKKyhtfhK
ytfhK
++⋅=++⋅=++⋅=
⋅=
6/)22( 432111 KKKKyy ++++=
41
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 (33) 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
42
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.
43
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.
44
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.
45
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.
46
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
Recommended