为什么 TextureCoordinates 对于 Viewport2DVisual3D 可以按预期工作,而对于 GeometryModel3D 却不能? [英] Why does TextureCoordinates work as expected for a Viewport2DVisual3D, but not for a GeometryModel3D?

查看:19
本文介绍了为什么 TextureCoordinates 对于 Viewport2DVisual3D 可以按预期工作,而对于 GeometryModel3D 却不能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在 3ds Max 中创建的模型.该模型是一个简单的矩形.它的纹理具有重叠的纹理坐标——模型应该并排显示图像文件的右半部分两次.我将此模型导出为 .obj,并使用 Microsoft Expression Blend 将其转换为 XAML.

I have a model that I created in 3ds Max. The model is a simple rectangle. Its texture has overlapping texture coordinates--the model should display the right half of the image file twice, side-by-side. I exported this model as an .obj, and converted it to XAML using Microsoft Expression Blend.

我从混合中取出 MeshGeometry3D,并使用两种方法将其添加到 Viewport3D:

I took the MeshGeometry3D from blend, and added it to a Viewport3D using two methods:

  1. 使用带有 LabelViewport2DVisual3D 作为它的 Visual.将 Label 的背景设置为纹理图像.使用此方法,一切都按预期进行.
  2. 使用 ModelVisual3DGeometryModel3D 作为它的 Content.将 GeometryModel3D 的材质设置为使用图像作为画笔的 DiffuseMaterial.使用此方法,MeshGeometry3DTextureCoordinates 似乎以不同的方式解释.
  1. Use a Viewport2DVisual3D with a Label as its Visual. Set the Label's background to the texture image. Using this method, everything works as expected.
  2. Use a ModelVisual3D with a GeometryModel3D as its Content. Set the GeometryModel3D's material to a DiffuseMaterial that uses the image as its brush. Using this method, the TextureCoordinates of the MeshGeometry3D appear to be interpreted differently.

下面提供了完整的代码.除了 InitializeComponent() 外,代码隐藏为空:

The full code is provided below. The code-behind is empty except for InitializeComponent():

<Window x:Class="TestTextureCoordinates.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid.Resources>
        <MeshGeometry3D x:Key="geometry"
                        Normals="0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1 0,0,1"
                        Positions="113.8997,102.4171,0 148.9045,102.4171,0 148.9045,148.41161,0 113.8997,148.41161,0 184.5722,102.4171,0 184.5722,148.41161,0 148.9045,148.41161,0 148.9045,102.4171,0"
                        TextureCoordinates="0.50639999,0.9995 1.0065,0.9995 1.0065,0.00050002337 0.50639999,0.00050002337 1.0022,0.9995 1.0022,0.00050002337 0.5,0.00050002337 0.5,0.9995"
                        TriangleIndices="0 1 2 0 2 3 4 5 6 4 6 7"/>
        <ImageBrush x:Key="brush" ImageSource="img/test.jpg" />
    </Grid.Resources>

    <Viewport3D>
        <Viewport3D.Camera>
            <PerspectiveCamera Position="195,125,210" LookDirection="0,0,-1" />
        </Viewport3D.Camera>

        <ModelVisual3D>
            <ModelVisual3D.Content>
                <AmbientLight Color="White" />
            </ModelVisual3D.Content>
        </ModelVisual3D>

        <!-- The first model, using a Viewport2DVisual3D. This works as intended. -->
        <Viewport2DVisual3D Geometry="{StaticResource geometry}">
            <Viewport2DVisual3D.Visual>
                <Label Background="{StaticResource brush}" />
            </Viewport2DVisual3D.Visual>
            <Viewport2DVisual3D.Material>
                <DiffuseMaterial Viewport2DVisual3D.IsVisualHostMaterial="True" />
            </Viewport2DVisual3D.Material>
        </Viewport2DVisual3D>

        <!-- The second model, using a ModelVisual3D and GeometryModel3D. The TextureCoordinates do not work as intended. -->
        <ModelVisual3D>
            <!-- We apply a transform to offset this model from the first model. -->
            <ModelVisual3D.Transform>
                <TranslateTransform3D OffsetX="90" />
            </ModelVisual3D.Transform>
            <ModelVisual3D.Content>
                <GeometryModel3D Geometry="{StaticResource geometry}">
                    <GeometryModel3D.Material>
                        <DiffuseMaterial Brush="{StaticResource brush}" />
                    </GeometryModel3D.Material>
                </GeometryModel3D>
            </ModelVisual3D.Content>
        </ModelVisual3D>
    </Viewport3D>
</Grid>

这是test.jpg:

这是最终的结果.左边是 Viewport2DVisual3D,它看起来和 3ds Max 中的一样.右侧是 ModelVisual3D,它似乎以不同的方式解释了 TextureCoordinates.

Here is the final result. On the left is the Viewport2DVisual3D, which looks the same as it does in 3ds Max. On the right is the ModelVisual3D, which appears to be interpreting the TextureCoordinates differently.

这是怎么回事?由于我正在开发的软件的其他要求,我无法使用 Viewport2DVisual3D.如何让 GeometryModel3D 正确解释 TextureCoordinates?

What's going on here? Due to other requirements of the software I am working on, I cannot use a Viewport2DVisual3D. How can I make a GeometryModel3D interpret the TextureCoordinates correctly?

推荐答案

我只需将 ImageBrush 上的 ViewportUnits 设置为 Absolute:

I just had to set ViewportUnits on the ImageBrush to Absolute:

<ImageBrush x:Key="brush" ImageSource="img/test.jpg" ViewportUnits="Absolute" />

请参阅这篇文章 来自 WPF3D 团队博客:

See this post from the WPF3D team blog:

如果您没有将 TileBrush.ViewportUnits 设置为 BrushMappingMode.Absolute,则您的纹理坐标将相对于几何体的边界框.例如,假设您只想将 v 中的一半纹理映射到网格.在其他 API 中,您只需将坐标范围从 0.0 -> 0.5.如果您在 WPF3D 中这样做而不将 ViewportUnits 设置为 Absolute,它仍然会映射整个事物.基本上任何时候您不想要整个纹理的一个副本,您都需要设置绝对.

If you don't set TileBrush.ViewportUnits to BrushMappingMode.Absolute, your texture coordinates will be relative to the bounding box of your geometry. For example, let's say you only want half of your texture in v to be mapped to the mesh. In other APIs, you would just range your coordinate from 0.0 -> 0.5. If you do that in WPF3D without setting ViewportUnits to Absolute, it'll still map the entire thing. Essentially any time you don't want one copy of the entire texture you'll want to set Absolute.

这篇关于为什么 TextureCoordinates 对于 Viewport2DVisual3D 可以按预期工作,而对于 GeometryModel3D 却不能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆