Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF 3d -- understanding texture coordinates

Tags:

wpf

3d

textures

In my attempt to understand texture coordinates in WPF 3D, I started off with a very simple example: a single triangle, a linear-gradient brush, and texture coordinates, as follows:

        <Viewport3D>
        <ModelVisual3D>
            <ModelVisual3D.Content>
                <Model3DGroup>
                    <GeometryModel3D>

                        <!-- Geometry -->
                        <GeometryModel3D.Geometry>
                            <MeshGeometry3D 
                            Positions="10 10 0, 
                                       20 10 0, 
                                       15 15 0"
                            TriangleIndices="0 1 2"
                            TextureCoordinates="0.5 0.0,
                                                0.5 0.0,
                                                0.5 0.0" />
                        </GeometryModel3D.Geometry>

                        <!-- Foreground and background brushes -->
                        <GeometryModel3D.Material>
                            <DiffuseMaterial>
                                <DiffuseMaterial.Brush>
                                    <LinearGradientBrush StartPoint="0.5 0" EndPoint="0.5 1">
                                        <LinearGradientBrush.GradientStops>
                                            <GradientStop Color="Red" Offset="0.0"/>
                                            <GradientStop Color="Yellow" Offset="0.50"/>
                                            <GradientStop Color="Green" Offset="1.0"/>
                                        </LinearGradientBrush.GradientStops>
                                    </LinearGradientBrush>
                                </DiffuseMaterial.Brush>
                            </DiffuseMaterial>
                        </GeometryModel3D.Material>

                        <GeometryModel3D.BackMaterial>
                            <DiffuseMaterial Brush="Blue" />
                        </GeometryModel3D.BackMaterial>
                    </GeometryModel3D>

                    <!-- Lighting -->
                    <AmbientLight Color="White" />

                </Model3DGroup>
            </ModelVisual3D.Content>
        </ModelVisual3D>

        <!-- Camera -->
        <Viewport3D.Camera>
            <PerspectiveCamera Position="15 12 10"
                           LookDirection="0 0 -1"
                           UpDirection="0 1 0"
                           FieldOfView="90">
            </PerspectiveCamera>
        </Viewport3D.Camera>
    </Viewport3D>

What I'm expecting is a Red triangle, since all y-coordinates of the textures are 0.0, but what I get is a Green one! Can someone please explain this behavior, so that I can correct my understanding, and move on to larger models? Thanks!

like image 909
user2774635 Avatar asked Sep 13 '13 00:09

user2774635


2 Answers

Usually, texture coordinates are defined in the range [0, 1]. However, WPF allows you to use any multiple. But let's stay with the [0, 1] range for the beginning. Then the gradient you defined looks like this:

Gradient

If we change the texture coordinates to the following:

TextureCoordinates="0.5 0.0,
                    0.5 0.0,
                    0.5 1.0" 

then we get a nice gradient on the triangle:

Triangle

The texture coordinates are interpolated in the triangle and the appropriate colors are fetched from the gradient. The bottom left vertex has texture coordinate (0.5, 0), which is red in the gradient. The top vertex has texture coordinate (0.5, 1), which is green in the gradient.

As I said, texture coordinates can be used relatively. They are scaled by their bounding box. So we could also define the following coordinates to get the same result (scaled by 2 and shifted by (0.5, 0.5)):

TextureCoordinates="1.5 0.5,
                    1.5 0.5,
                    1.5 2.5"

And this is exactly the point, why you get a green triangle with your texture coordinates. Because all coordinates are the same, the bounding box is 0 units wide and 0 units high. There is just no reasonable way to fit an arbitrary texture coordinate into this degenerate bounding box. I can't tell why WPF chooses the green edge. Probably undefined behavior.

Concluding, always define proper texture coordinates that do not result in a degenerate bounding box.

You may have noticed that the alternative texture coordinates produce a bounding box with zero width. However, this is ok in this case, because the gradient does not change along the u-direction.

like image 114
Nico Schertler Avatar answered Nov 15 '22 09:11

Nico Schertler


See Daniel Lehenbauer's blog for a helpful description of the 2D to 3D mapping procedure in WPF.

like image 45
Rana Ian Avatar answered Nov 15 '22 08:11

Rana Ian