wpf.net-coretexture-mappingviewport3d

WPF Viewport3D TextureCoordinates


I want to render a cube with a texture mapped over it. This is my Texture:

enter image description here

The areas with text "Empty" should not be used.

This is my Viewport3D:

<Viewport3D>
  <Viewport3D.Camera>
    <PerspectiveCamera FarPlaneDistance="100" LookDirection="22,-10,-10" UpDirection="0,1,0" NearPlaneDistance="1" Position="-20,15,15" FieldOfView="60"/>
  </Viewport3D.Camera>
  <Viewport3D.Children>
    <ModelVisual3D>
      <ModelVisual3D.Content>
        <DirectionalLight Color="White" Direction="-2,-3,-1"/>
      </ModelVisual3D.Content>
    </ModelVisual3D>
    <ModelVisual3D>
      <ModelVisual3D.Content>
        <DirectionalLight Color="White" Direction="2,3,1"/>
      </ModelVisual3D.Content>
    </ModelVisual3D>
    <ModelVisual3D>
      <ModelVisual3D.Content>
        <GeometryModel3D>
          <GeometryModel3D.Geometry>
            <MeshGeometry3D

               Positions="
               0,0,0   8,0,0   0,8,0   8,8,0
               0,0,0   0,0,8   0,8,0   0,8,8
               0,0,0   8,0,0   0,0,8   8,0,8
               8,0,0   8,8,8   8,0,8   8,8,0
               0,0,8   8,0,8   0,8,8   8,8,8
               0,8,0   0,8,8   8,8,0   8,8,8"

               TriangleIndices="
               0,2,1       1,2,3
               4,5,6       6,5,7                                  
               8,9,10      9,11,10                                  
               12,13,14    12,15,13
               16,17,18    19,18,17
               20,21,22    22,21,23"

               TextureCoordinates="
               0.5,0       0,0.25    0.25,0     1,0.5
               0.25,0.25   0,0.25    0.25,0     0,0  ">

            </MeshGeometry3D>
          </GeometryModel3D.Geometry>
          <GeometryModel3D.Material>
            <DiffuseMaterial>
              <DiffuseMaterial.Brush>
                <ImageBrush ImageSource="cube.png"/>
              </DiffuseMaterial.Brush>
            </DiffuseMaterial>
          </GeometryModel3D.Material>
        </GeometryModel3D>
      </ModelVisual3D.Content>
    </ModelVisual3D>
  </Viewport3D.Children>
</Viewport3D>

The result:

enter image description here

First I wanted to try to get only the front side. I only got as far as showing the first rectangle. Unfortunately I can't manage to select another rectangle and it's mirrored too.


Solution

  • In this post

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/d71dacba-167a-4249-8817-1b3995103835/correctly-texture-mapping-a-cube

    Charles Petzold says

    A good part of Chapter 5 of my book "3D Programming for Windows" attacks the problem of covering a cube (and square cuboid) with a bitmap image in a reasonable way.

    Generally a good way to start is to draw (on a piece of paper) a rectangle that represents your image, and then to decide what part of that image should be positioned on what part of the cube. Since each point in the Positions collection maps to a point in the TextureCoordinates collection, you might find that what you're trying to do is topologically impossible.

    But if all else fails, you can always treat the cube as 6 separate squares, and do each square independently of the others.

    I went with his "brute force" suggestion and modified one of his examples from Chapter 5, using your bitmap. This is what the result looks like:

    Result

    For each face, I use a ViewBox to define just the part of the image used for that face. Here's the source code (note there are scrollbars you can use spin the image around and verify all sides look right):

    <DockPanel>
        <ScrollBar Name="horz"
                   DockPanel.Dock="Bottom"
                   Orientation="Horizontal"
                   Minimum="-180"
                   Maximum="180"
                   LargeChange="10"
                   SmallChange="1" /> 
    
        <ScrollBar Name="vert"
                   DockPanel.Dock="Right"
                   Orientation="Vertical"
                   Minimum="-180"
                   Maximum="180"
                   LargeChange="10"
                   SmallChange="1" /> 
    
        <Viewport3D>
            <Viewport3D.Camera>
                <PerspectiveCamera Position="-2 2 4" LookDirection="2 -2 -4" FieldOfView="60" />
            </Viewport3D.Camera>
            <Viewport3D.Children>
                <ModelVisual3D>
                    <ModelVisual3D.Content>
                        <Model3DGroup>
                            <AmbientLight Color="White" />
    
                            <!-- Unit cube: front -->
                            <GeometryModel3D>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D
                                        Positions="-0.5  0.5  0.5,  0.5  0.5  0.5,
                                                   -0.5 -0.5  0.5,  0.5 -0.5  0.5"
                                        TriangleIndices=" 0  2  1,  1  2  3"
                                        TextureCoordinates="0 0, 1 0, 0 1, 1 1" />
                                </GeometryModel3D.Geometry>
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial>
                                        <DiffuseMaterial.Brush>
                                            <ImageBrush ImageSource="cube.png" Viewbox="0.25,0.5,0.25,0.5" />
                                        </DiffuseMaterial.Brush>
                                    </DiffuseMaterial>
                                </GeometryModel3D.Material>
                                <GeometryModel3D.BackMaterial>
                                    <DiffuseMaterial Brush="Black"/>
                                </GeometryModel3D.BackMaterial>
                            </GeometryModel3D>
    
                            <!-- Unit cube: back -->
                            <GeometryModel3D>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D
                                    Positions=" 0.5  0.5 -0.5, -0.5  0.5 -0.5,
                                                0.5 -0.5 -0.5, -0.5 -0.5 -0.5"
                                    TriangleIndices=" 0  2  1,  1  2  3"
                                    TextureCoordinates="0 0, 1 0, 0 1, 1 1"/>
                                </GeometryModel3D.Geometry>
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial>
                                        <DiffuseMaterial.Brush>
                                            <ImageBrush ImageSource="cube.png" Viewbox="0.75,0.5,0.25,0.5" />
                                        </DiffuseMaterial.Brush>
                                    </DiffuseMaterial>
                                </GeometryModel3D.Material>
                                <GeometryModel3D.BackMaterial>
                                    <DiffuseMaterial Brush="Black"/>
                                </GeometryModel3D.BackMaterial>
                            </GeometryModel3D>
    
                            <!-- Unit cube: left -->
                            <GeometryModel3D>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D
                                    Positions="-0.5  0.5 -0.5, -0.5  0.5  0.5,
                                               -0.5 -0.5 -0.5, -0.5 -0.5  0.5"
                                    TriangleIndices=" 0  2  1,  1  2  3"
                                    TextureCoordinates="0 0, 1 0, 0 1, 1 1"/>
                                </GeometryModel3D.Geometry>
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial>
                                        <DiffuseMaterial.Brush>
                                            <ImageBrush ImageSource="cube.png" Viewbox="0,0.5,0.25,.5"   />
                                        </DiffuseMaterial.Brush>
                                    </DiffuseMaterial>
                                </GeometryModel3D.Material>
                                <GeometryModel3D.BackMaterial>
                                    <DiffuseMaterial Brush="Black"/>
                                </GeometryModel3D.BackMaterial>
                            </GeometryModel3D>
    
                            <!-- Unit cube: right -->
                            <GeometryModel3D>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D
                                    Positions=" 0.5  0.5  0.5,  0.5  0.5 -0.5,
                                                0.5 -0.5  0.5,  0.5 -0.5 -0.5"
                                    TriangleIndices=" 0  2  1,  1  2  3"
                                    TextureCoordinates="0 0, 1 0, 0 1, 1 1"/>
                                </GeometryModel3D.Geometry>
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial>
                                        <DiffuseMaterial.Brush>
                                            <ImageBrush ImageSource="cube.png" Viewbox="0.5,0.5,0.25,.5" />
                                        </DiffuseMaterial.Brush>
                                    </DiffuseMaterial>
                                </GeometryModel3D.Material>
                                <GeometryModel3D.BackMaterial>
                                    <DiffuseMaterial Brush="Black"/>
                                </GeometryModel3D.BackMaterial>
                            </GeometryModel3D>
    
                            <!-- Unit cube: top -->
                            <GeometryModel3D>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D
                                    Positions="-0.5  0.5 -0.5,  0.5  0.5 -0.5,
                                               -0.5  0.5  0.5,  0.5  0.5  0.5"
                                    TriangleIndices=" 0  2  1,  1  2  3"
                                    TextureCoordinates="0 0, 1 0, 0 1, 1 1"/>
                                </GeometryModel3D.Geometry>
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial>
                                        <DiffuseMaterial.Brush>
                                            <ImageBrush ImageSource="cube.png" Viewbox="0.25,0.0,0.25,.5" />
                                        </DiffuseMaterial.Brush>
                                    </DiffuseMaterial>
                                </GeometryModel3D.Material>
                                <GeometryModel3D.BackMaterial>
                                    <DiffuseMaterial Brush="Black"/>
                                </GeometryModel3D.BackMaterial>
                            </GeometryModel3D>
    
                            <!-- Unit cube: bottom. -->
                            <GeometryModel3D>
                                <GeometryModel3D.Geometry>
                                    <MeshGeometry3D
                                    Positions=" 0.5 -0.5 -0.5, -0.5 -0.5 -0.5,
                                                0.5 -0.5  0.5, -0.5 -0.5  0.5"
                                    TriangleIndices=" 0  2  1,  1  2  3"
                                    TextureCoordinates="0 0, 1 0, 0 1, 1 1"/>
                                </GeometryModel3D.Geometry>
                                <GeometryModel3D.Material>
                                    <DiffuseMaterial>
                                        <DiffuseMaterial.Brush>
                                            <ImageBrush ImageSource="cube.png" Viewbox="0.5,0.0,0.25,.5" />
                                        </DiffuseMaterial.Brush>
                                    </DiffuseMaterial>
                                </GeometryModel3D.Material>
                                <GeometryModel3D.BackMaterial>
                                    <DiffuseMaterial Brush="Black"/>
                                </GeometryModel3D.BackMaterial>
                            </GeometryModel3D>
                        </Model3DGroup>
                    </ModelVisual3D.Content>
                    <ModelVisual3D.Transform>
                        <Transform3DGroup>
                            <RotateTransform3D>
                                <RotateTransform3D.Rotation>
                                    <AxisAngleRotation3D Axis="0 1 0" Angle="{Binding ElementName=horz, Path=Value}" />
                                </RotateTransform3D.Rotation>
                            </RotateTransform3D>
                            <RotateTransform3D>
                                <RotateTransform3D.Rotation>
                                    <AxisAngleRotation3D Axis="1 0 0" Angle="{Binding ElementName=vert, Path=Value}" />
                                </RotateTransform3D.Rotation>
                            </RotateTransform3D>
                        </Transform3DGroup>
                    </ModelVisual3D.Transform>
                </ModelVisual3D>
            </Viewport3D.Children>
        </Viewport3D>
    </DockPanel>