Convirtiendo controles 2-D en 3-D en WPF

Bien, hola qué tal de nuevo? Ok en la sección de Preguntas y Respuestas Tere pregunta cómo poder manipular un TextBox en Expression Blend como si un objeto 3-D se tratara.

Bien pues aquí les explico 3 formas en las que se puede hacer, casi lo mismo(porque no en todos es tan sencillo).

Bueno, primero entender que como su nombre lo dice, la función de “Make Image 3D” funciona solo para convertir imágenes en objetos 3-D, no para otro tipo de controles, por lo tanto:

Forma # 1:

Vamos a crear un nuevo proyecto, insertamos un textbox:

13d

Acto seguido, teniendo el TextBox seleccionado, lo convertimos en un VisualBrush:

23d

Le pones el nombre que desees, y ya lo tendrás disponible para usarlo.

Posteriormente, lo que tienes que hacer es insertar una imagen, y convertirla en 3-D:

33d

Vale, ahora que tienes una imagen 3-D, tienes que agregarle como material el VisualBrush que has creado anteriormente al modelo:

43d

Por si no lo alcanzas a ver, el elemento al que modificamos el material se encuentra en :

ViewPort3D->ModelContainer->Content->Model (Cuadro Rojo)

el cual te mostrará en las propiedades un BackMaterial y un Material(Cuadro amarillo), una vez seleccionado el mismo, te mostrará los Brushes que pudes agregarle, en la seccion de hasta la derecha, se encuentran tus propios Brushes, en el cual estará el que has creado hace un momento, al momento de seleccionarlo automáticamente la imagen obtendrá una “copia” de lo que esté pasando en el TextBox original, con esto podrás mover la imagen como si fuera un objeto tridimensional, pero…. hay un pequeño problema…..

NO PUEDES ESCRIBIR SOBRE ÉL; ¿Porqué? Pues porque es una simple imágen. Esto sirve principalmente para animar labels, texblocks, etc; pero si lo que quisieras es escribir realmente en el textbox, lo puedes hacer con la siguiente forma:

 

Forma # 2:

Para esta forma, requieres bajar las 3D Tools for the Windows Presentation Foundation, misma que fue creada por el equipo 3D de WPF.

Bien, voy a crear un nuevo proyecto, agrego una referencia a la DLL que se encuentra dentro de la carpeta que acabo de descargar con el nombre de 3DTools.dll

63d

53d

Ahora agregas una referencia al assembly desde el código XAML:

73d

NOTA: Para los que no saben que acabo de hacer, estoy creando una referencia a la DLL que agregué, paso a paso quiero decir:

xmlns = xml namespace; o sease que estoy creando una referencia a un espacio de nombres.

xmlns:local = Estoy nombrando de alguna forma mi acceso al assembly, en este caso local, aunque pudo haber sido cualquier otro.

“clr-namespace:_3dTools; = clr-namespace es la sintaxis para ubicar un espacio de nombres

assembly=3DTools”  = Es el ensamblado o la librería que acabamos de agregar, y donde se encuentra _3dTools.

Bien, ahora, procedemos a escribir el código que empezará a crear en sí los objetos 3D:

83d

<Window.Resources> 
    <MeshGeometry3D x:Key=”3dMesh”
        Positions=”-1,1,0 -1,-1,0 1,-1,0 1,1,0″
        TextureCoordinates=”0,0 0,1 1,1 1,0″
        TriangleIndices=”0 1 2 0 2 3″/> 
    <RotateTransform3D x:Key=”3dTransform”>
      <RotateTransform3D.Rotation>
        <AxisAngleRotation3D Angle=”45″ Axis=”0 1 1″ />
      </RotateTransform3D.Rotation>
    </RotateTransform3D> 
    <Grid Background=”White” x:Key=”3dMaterial”>
      <Grid.RowDefinitions>
        <RowDefinition Height=”*”/>
        <RowDefinition Height=”*”/>
        <RowDefinition Height=”*”/>
      </Grid.RowDefinitions> 
      <TextBox Grid.Row=”0″>Demo con WPF 3D Tools</TextBox>
      <Slider Grid.Row=”1″ />
      <Button Grid.Row=”2″ Width=”60″ Height=”25″>Aceptar</Button> 
    </Grid> 
  </Window.Resources>

jeje, parece un poco complicado, pero trataré de explicar un poco:

Empiezo definiendo dentro de los Recursos de la aplicación (Window.Resources), en primer lugar, un mashGeometry3D(Geometría de malla), el cual será el encargado de darle forma a mi objeto 3D, esto lo hago con positions(Posiciones Vertex de mi malla), TextureCoordinates(Sirve para definir las coordenadas de mi textura) y TriangleIndices(Indices Triangulares); estos son los recursos base  para definir la textura de mi objeto 3D. Posteriormente Hago un RotateTransform3D para voltear un poco mi objeto 3D, y agrego una serie de elementos(Grilla, dentro de la misma un textbox, un slider y un botón). Como puedes darte cuenta, a cada uno de los elementos que ligaremos les hemos puesto un x:Key, que servirá para referenciarlos (3dMes, 3dTransform y 3dMaterial)

Ahora, el código en sí de la aplicación:

93d

<Grid> 
    <local:TrackballDecorator>
    <local:Interactive3DDecorator> 
      <Viewport3D Width=”450″ Height=”225″> 
        <Viewport3D.Camera>
          <PerspectiveCamera Position=”0, 0, 4″  FieldOfView=”75″ />
        </Viewport3D.Camera> 
        <ModelVisual3D>
          <ModelVisual3D.Content>
            <DirectionalLight Color=”White” Direction=”0,0,-1″ />
          </ModelVisual3D.Content>
        </ModelVisual3D> 
        <local:InteractiveVisual3D
            Transform=”{StaticResource 3dTransform}”
            Geometry=”{StaticResource 3dMesh}”
            Visual=”{StaticResource 3dMaterial}” />
      </Viewport3D> 
    </local:Interactive3DDecorator>
    </local:TrackballDecorator> 
  </Grid>

Aquí, lo que estamos haciendo es, en primer lugar:

<local:TrackballDecorator> = Ingresamos a los métodos de nuestra clase Tools3D, este principalmente nos sirve para hacer un zoom in y zoom out, además de hacer rotación a voluntad del objeto.

<local:Interactive3DDecorator> = Sirve para interactuar con los elementos de nuestro modelo 3D

<Viewport3D… =  Definimos un Viewport3D, así como el que se crea cuando convertimos una imagen en 3D

<Viewport3D.Camera> = Agregamos una cámara

<PerspectiveCamera = Posicionamos la camara

<ModelVisual3D Creamos nuestro modelo 3D

<ModelVisual3D.Content = En nuestro caso, lo estamos usando para agregar una luz

<local:InteractiveVisual3D
            Transform=”{StaticResource 3dTransform}”
            Geometry=”{StaticResource 3dMesh}”
            Visual=”{StaticResource 3dMaterial}” />

Hacemos un binding de cada una de las propiedades de nuestro objeto interactivo 3D, uno al Transform, otro a la malla que definimos, y el último al material 3D(este último contendrá nuestros controles).

Y bien, luego luego aparece en el diseñador el aspecto que nuestra aplicación tiene, y al cual al correrlo, se observa así:

103d

He seleccionado el texto para que veas que efectivamente funciona, ahora puedes de igual manera acercar o alejar el objeto, y rotarlo a tu gusto:

113d

Si no quieres que aparezca cortado el control, lo único que tienes que hacer es poner en falsa la propiedad “CliptoBounds”:

123d

Forma # 3:

Bien, hemos usado una DLL en la forma anterior, sin embargo, con el Framework 3.5 se incluye un control para colocar objetos 2D dentro de objetos 3D,  su nombre es Viewport2DVisual3D; para lo que tendremos que agregar otro espacio de nombres:

xmlns:d=”http://schemas.microsoft.com/expression/blend/2008″

Seguiremos con el proyecto anterior para que te des una idea mas clara de como funciona esto. Primero borra todas las referencias de código que empiecen con <local: …/>, menos la de <local:InteractiveVisual3D.

Lo que vas a hacer ahora, es cambiar esa referencia <local:InteractiveVisual3D , por un elemento Viewport2DVisual3D

        <Viewport2DVisual3D
            Transform=”{StaticResource 3dTransform}”
            Geometry=”{StaticResource 3dMesh}”
            Visual=”{StaticResource 3dMaterial}”>
        </Viewport2DVisual3D>
      </Viewport3D>

Ahora, lo único que falta es agregar el material en sí del objeto Viewport2DVisual3D:

<Viewport2DVisual3D.Material>
    <DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial=”true”/>
</Viewport2DVisual3D.Material>

Al final quedaría así:

<Viewport2DVisual3D
            Transform=”{StaticResource 3dTransform}”
            Geometry=”{StaticResource 3dMesh}”
            Visual=”{StaticResource 3dMaterial}”>
          <Viewport2DVisual3D.Material>
            <DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial=”true”/>
          </Viewport2DVisual3D.Material>
        </Viewport2DVisual3D>

Con esto obtienes un resultado muy parecido al anterior,

143d

con la pequeña gran diferencia de que no pudes hacer zoom in, zoom out, ni rotar a voluntad en tiempo de ejecución, para lo cual, si gustas puedes agregarle funcionalidad nuevamente poniendo tu ViewPort3D dentro del elemento:

<local:TrackballDecorator> , con su etiqueta de cierre respectivamente.

Bueno, eso es todo, aquí les dejo los proyectos creados con cada una de las formas antes descritas:

Forma 1: 3D_Forma_1.rar-download

Forma 2: 3D_Forma_2.rar-download

Forma 3: 3D_Forma_3.rar-download

Bien, espero que hayáis entendido los conceptos básicos, una vez hecha cualquiera de las formas anteriores, es posible mover nuestros controles a entera libertad en Blend, que es lo que me habían pedido, si queréis aprender al 100 les recomiendo que lean un libro relacionado al mismo, uno que les puedo recomendar es:

3D Programming for Windows

http://www.charlespetzold.com/3D/index.html

Salu2, y por favor Tere o los demás, si pueden hacerme un feedback lo agradecería mucho, Salu2 y éxito!

Héctor Pérez

8 comentarios sobre “Convirtiendo controles 2-D en 3-D en WPF

  1. Estimado Héctor, es verdad te estoy muy pero muy agradecida con los ejemplos que muestras para rotar en 3D un objeto como es TextBox en Blend, gran idea la de hacer una COPIA del TextBox y convertirla a imagen para poderla rotar, ahora abusando un poco de tu amabilidad te quiero hacer otra pregunta:

    -Es posible agrupar un conjunto de controles como: TextBox, Label, Button y hacer que los 3 al mismo tiempo se conviertan en imagen y poderlos rotar al mismo tiempo, cabe a clarar que cada control se usará de forma independiente y en tiempos distintos lo que necesito es que las COPIAS de los 3controles (las imagenes)las pueda rotar al mismo tiempo una ves que ya haya terminado de usar el TextBox y el Button.

    De antemano muchisimas GRACIAS por tu ayuda, y espero NO agobiarte con tantas preguntas.

    Sinceramente
    Teresa Francisco Sotelo

  2. Hola qué tal de nuevo? Por supuesto que pudes hacer eso, si es lo que te he entendido en la pregunta. Puedes agrupar los 3 objetos en una grilla, y ser la grilla la que conviertas en un VisualBrush, de esta forma será la grilla de la cual se obtendrá el “reflejo”. Luego pondrías el Visual Brush sobre una imágen, y al hacer el cambio en alguno de los controles originales se notará el cambio en la imágen. Espero haberte entendido bien🙂

    Salu2 y cualquier cosa ya sabes😉

  3. Hola de nuevo,

    Y sigo dando lata, ahora para preguntarte si podrias poner un ejemplo de cómo utilizar “FlowDocumentPageViewer”, graciotas y espero que con mi pregunta anterior NO te haya causado molestias, mil gracias y estamos en contacto, un fuerte abrazo desde México, Distrito Federal.

    Con aprecio
    Tere =D !!!

  4. Hola Héctor, estoy empezando con blend. No soy programador pero espero poder manejarme y poder construir sitios completos.

    He encontrado tu blog buscando tutoriales de blend y me ha gustado mucho lo que explicas.

    Un saludo cordial

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s