Texture Coordinates and Visuals on 3D surfaces

Posted Thursday, April 13, 2006 9:24 AM by mhodnick

One of the capabilities that WPF provides is the ability to render 2D visual elements on 3D surface. For example, you can place panels, text blocks, images, or even videos on the surface of a thin box or "screen" (think video carousel), or even on a sphere or cylinder if desired. In order to put visual elements on your 3D objects, you need to use texture coordinates in your mesh geometry.

Texture coordinates map the Cartesian positions of your 3D mesh to the Cartesian positions of your visual element. The easiest way to explain this is with an example. Let's say you have a 3D model that defines a plane that is centered about the X,Y,Z origin:

Plane Coordinates
A plane's mesh geometry.

Now let's say you have a visual element (e.g. a text block or image) that you want to use as the material for your plane. The visual element's positions are defined by the X,Y coordinate convention used in images - that is, the positive Y axis points "down":

Visual Coordinates
A visual's coordinates.

To get the image or text block on to the plane mesh, the plane mesh needs to define how its 3D positions map to conventional 2D coordinates used in images. Basically we will need this mapping:

3D Plane Position 2D Visual Coordinate
(-1,-1) (0,1)
(1,-1) (1,1)
(1,1) (1,0)
(-1,1) (0,0)

When you define a mesh using WPF, the order in which you add positions, triangle indices, normals, and texture coordinates is important. As you add positions to the mesh, the index of the position in the mesh's Positions collection equal the indices of the points in the mesh's TextureCoordinates collection.

The XAML for the plane's mesh geometry would look like this if you define the positions starting from the (-1,-1) position and work your way counter-clockwise. The triangles defined in the mesh are { (-1,-1) (1,-1) (1,1) } and { (-1,-1) (1,1) (-1,1) }:


<GeometryModel3D 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <GeometryModel3D.Geometry>
    <MeshGeometry3D >
      <MeshGeometry3D.Positions>
        <Point3D X="-1" Y="-1" Z="0"/>
        <Point3D X="1" Y="-1" Z="0"/>
        <Point3D X="1" Y="1" Z="0"/>
        <Point3D X="-1" Y="1" Z="0"/>
      </MeshGeometry3D.Positions>
      <MeshGeometry3D.TextureCoordinates>
        <Point X="0" Y="1"/>
        <Point X="1" Y="1"/>
        <Point X="1" Y="0"/>
        <Point X="0" Y="0"/>
      </MeshGeometry3D.TextureCoordinates>
      <MeshGeometry3D.TriangleIndices>
        0,1,2 0,2,3
      </MeshGeometry3D.TriangleIndices>
      <MeshGeometry3D.Normals>
        <Vector3D X="0" Y="0" Z="1"/>
        <Vector3D X="0" Y="0" Z="1"/>
        <Vector3D X="0" Y="0" Z="1"/>
        <Vector3D X="0" Y="0" Z="1"/>
        <Vector3D X="0" Y="0" Z="1"/>
        <Vector3D X="0" Y="0" Z="1"/>
      </MeshGeometry3D.Normals>
    </MeshGeometry3D>
  </GeometryModel3D.Geometry>
</GeometryModel3D>    
    

With this mesh, a 2D visual now has a mapping for its coordinates against the 3D surface.

Now all you need to do is add the visual to the surface as a VisualBrush for the material:


<GeometryModel3D.Material>
  <MaterialGroup>
    <DiffuseMaterial>
      <DiffuseMaterial.Brush>
        <SolidColorBrush Color="Gray"/>
      </DiffuseMaterial.Brush>
    </DiffuseMaterial>
    <DiffuseMaterial>
      <DiffuseMaterial.Brush>
        <VisualBrush>
          <VisualBrush.Visual>
            <TextBlock 
                Margin="5" 
                Foreground="Black" 
                HorizontalAlignment="Left" 
                VerticalAlignment="Center" 
                TextAlignment="Center" 
                FontWeight="Bold" 
                FontSize="8pt">
                The Melvins
            </TextBlock>
          </VisualBrush.Visual>
        </VisualBrush>
      </DiffuseMaterial.Brush>
    </DiffuseMaterial>
  </MaterialGroup>
</GeometryModel3D.Material>
    

This will generate a very simple (and very "raw") model with text:

Visual Brush Screenshot
A 3D surface with a VisualBrush

While texture coordinates are a fundamental part of decorating 3D models with graphics or placing complex UI layouts on a 3D surface, they can be overlooked by the developer who is diving in to 3D modeling for the first time. In real 3D models, geometries will be more complex and mapping texture coordinates won't be as simple as the four corners of a plane... and in all likelyhood a designer will be doing that dirty work for you in a 3D modeling tool. However, I think it's always good to have an understanding of what's happening "under the hood" so that you can make better decisions about how to go about your work. Hopefully this example will help you as you create interesting user interfaces in WPF.

Filed under:

Comments

# re: Texture Coordinates and Visuals on 3D surfaces

Wednesday, August 16, 2006 9:08 AM by dreckgos

the visuals drawn canot have events attached can they? i mean... If you put a list on 3d object like this, you won't be able to select items; am I right?

# re: Texture Coordinates and Visuals on 3D surfaces

Wednesday, March 07, 2007 12:38 PM by Kurt

This looks like a great way to add special effects such as zooming, lighting, and tilting to a 2D game. However, as dreckgos points out, it would only work if the game doesn't require point-and-click type stuff on the game board (e.g, it uses the keyboard or relies on a different panel to host the interactive controls).

There is a workaround that I found, however, from the WPF team: http://blogs.msdn.com/wpf3d/archive/2006/12/12/interacting-with-2d-on-3d-in-wpf.aspx

# WPF 3D - Blender Helps You Getting Productive

Monday, April 16, 2007 11:12 AM by Come Get Some...Thoughts On Software Technology

The last few days I played around with the 3d capabilities of the Windows Presentation Foundation (WPF).

# re: Texture Coordinates and Visuals on 3D surfaces

Monday, April 16, 2007 3:25 PM by mhodnick

The 3DTools components will take care of being able to interact with 2D visuals on 3D:

http://www.codeplex.com/3DTools

# WPF 3D: Google maps on a sphere, or &#8216;The World&#8217; &laquo; Hungry for Knowledge

Pingback from  WPF 3D: Google maps on a sphere, or &#8216;The World&#8217; &laquo; Hungry for Knowledge