我试图在运行时将材质应用到我的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鼠标点击...
感谢您提供任何帮助!
答案 0 :(得分:3)
当您点击它时,听起来想要在几何体上滑动材质。方法如下:
使用点击测试将鼠标点击的X / Y坐标转换为RayMeshGeometry3DHitTestResult
,如earlier answer中所述。这将为您提供被击中的MeshGeometry3D
,被击中的三角形的顶点以及该三角形上的相对位置。
在VertexIndex1
中查找每个顶点索引(VertexIndex2
,VertexIndex2
,MeshGeometry3D.TextureCoordinates
)以获取纹理坐标。这将为您提供三个(u,v)对作为Point对象。将每个(u,v)对乘以命中测试结果(VertexWeight1
,VertexWeight2
,VertexWeight3
)中的相应权重,并将这些对添加到一起,即:
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
。