为什么纹理坐标对于 Viewport2DVisual3D 可以按预期工作,但对于 GeometryModel3D 却不能?

发布于 2024-11-28 11:40:47 字数 3938 浏览 4 评论 0原文

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

我从 Blend 中获取了 MeshGeometry3D,并使用两种方法将其添加到 Viewport3D

  1. 使用 Viewport2DVisual3DLabel > 作为其视觉。将Label的背景设置为纹理图像。使用这种方法,一切都会按预期进行。
  2. 使用 ModelVisual3DGeometryModel3D 作为其内容。将 GeometryModel3D 的材质设置为使用图像作为画笔的 DiffuseMaterial。使用此方法,MeshGeometry3DTextureCooperatives 似乎会有不同的解释。

下面提供了完整的代码。除了 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,它似乎对 TextureCooperatives 的解释不同。

在此处输入图像描述

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

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.

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

  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.

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>

Here is test.jpg:

enter image description here

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.

enter image description here

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

清醇 2024-12-05 11:40:47

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

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

请参阅 这篇文章 (存档)来自 WPF3D 团队博客:

如果您未将 TileBrush.ViewportUnits 设置为 BrushMappingMode.Absolute,则纹理坐标将相对于几何体的边界框。例如,假设您只想将 v 中纹理的一半映射到网格。在其他 API 中,您只需将坐标范围设置为 0.0 -> 0.0 0.5。如果您在 WPF3D 中执行此操作而不将 ViewportUnits 设置为 Absolute,它仍然会映射整个事物。基本上,只要您不需要整个纹理的一份副本,您就需要设置绝对值。

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

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

See this post (archive) from the WPF3D team blog:

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文