WPF 3d ImageBrush材质帮助

时间:2009-11-16 02:37:22

标签: wpf 3d material

我试图在运行时将材质应用到我的GeometryModel3D,如下所示:

        var model3D = ShardModelVisual.Content as GeometryModel3D;
        var materialGroup = model3D.Material as MaterialGroup;

        BitmapImage image;
        ResourceLoader.TryLoadImage("pack://application:,,,/AnzSurface;component/path file/img.png", out image, ".png");
        var iceBrush = new ImageBrush(image);
        var grp = new TransformGroup();
        grp.Children.Add(new ScaleTransform(0.25, 0.65, 0.5, 0.5));
        grp.Children.Add(new TranslateTransform(0.0, 0.0));
        iceBrush.Transform = grp;
        var iceMat = new DiffuseMaterial(iceBrush);
        materialGroup.Children.Add(iceMat);

一切正常,材料也会添加。

我不明白的是我如何将用户点击屏幕上的地图映射到需要应用于TranslateTransform的偏移量。

即。此刻,x:-0.25沿X轴向后移动材料,但我没有IDEA如何从用户鼠标点击中获得该类型的坐标...

当我这样做时:

e.MouseDevice.GetPosition(ShardsViewPort3D);

给我正常的X / Y鼠标点击...

感谢您提供任何帮助!

1 个答案:

答案 0 :(得分:3)

当您点击它时,听起来想要在几何体上滑动材质。方法如下:

使用点击测试将鼠标点击的X / Y坐标转换为RayMeshGeometry3DHitTestResult,如earlier answer中所述。这将为您提供被击中的MeshGeometry3D,被击中的三角形的顶点以及该三角形上的相对位置。

VertexIndex1中查找每个顶点索引(VertexIndex2VertexIndex2MeshGeometry3D.TextureCoordinates)以获取纹理坐标。这将为您提供三个(u,v)对作为Point对象。将每个(u,v)对乘以命中测试结果(VertexWeight1VertexWeight2VertexWeight3)中的相应权重,并将这些对添加到一起,即:

uMouse = u1 * VertexWeight1 + u2 * VertexWeight2 + u3 * VertexWeight3
vMouse = v1 * VertexWeight1 + v2 * VertexWeight2 + v3 * VertexWeight3

现在您有一个点(uMouse,vMouse)指示您的素材在鼠标点击的位置。

如果您希望纹理上的特定点移动到鼠标单击的确切位置,只需从材料中位置的(u,v)坐标中减去单击鼠标的(uMouse,vMouse)想要出现在鼠标下,并将其设置为TranslateTransform。如果要处理拖动,请将计算(uMouse,vMouse)存储在拖动开始的位置和拖动开始时的变换,然后在拖动过程中将新变换计算为:

translate = (uMouse,vMouse) - (uMouseDragStart, vMouseDragStart) + origTranslate

在代码中,您将把它写为Point添加。我在这个解释中将其拼写为(u,v)因为我认为如果我这样做会更容易理解。实际上,计算代码(uMouse,vMouse)看起来更像是这样:

var uv1 = hit.MeshHit.TextureCoordinates[hit.VertexIndex1];
var uv2 = hit.MeshHit.TextureCoordinates[hit.VertexIndex2];
var uv3 = hit.MeshHit.TextureCoordinates[hit.VertexIndex3];

var uvMouse = new Vector(
  uv1.X * hit.VertexWeight1 + uv2.X * hit.VertexWeight2 + uv3.X * hit.VertexWeight3)
  uv1.Y * hit.VertexWeight1 + uv2.Y * hit.VertexWeight2 + uv3.Y * hit.VertexWeight3);

并且在拖动期间更新变换的代码将如下所示:

...
var translate = translateAtDragStart + uvMouse - uvMouseAtDragStart;
... = new TranslateTransform(translate.X, translate.Y);

你必须根据具体情况进行调整。

请注意,您可以多次调用HitTest回调,从最近的网格开始并向后移动。它甚至可以通过2D命中调用,例如,如果2D对象位于Viewport3D的前面。因此,您需要检查每次点击以查看它是否真的是您想要的,例如在拖动过程中您希望继续检查被拖动的网格上的位置,即使它不再是最重要的。一旦你对拖动的网格采取了行动,就从你的回调中返回HitTestResultBehavior.Stop