Звучит так, будто вы хотите двигать материал по вашей геометрии, когда вы нажимаете на нее. Вот как это сделать:
Используйте проверку удара, чтобы перевести ваши координаты X / Y от щелчка мыши в RayMeshGeometry3DHitTestResult
, как описано в моем предыдущем ответе . Это даст вам 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), которая указывает, где на вашем материале была нажата ваша мышь.
Если вы хотите, чтобы конкретная точка на вашей текстуре переместилась точно туда, где была нажата мышь, просто вычтите (uMouse, vMouse), где была нажата мышь, из координаты (u, v) местоположения в материале, который вы хотите появиться под мышью, и установите это как свой TranslateTransform. Если вы хотите обработать перетаскивание, сохраните вычисленное значение (uMouse, vMouse), где началось перетаскивание, и преобразование с момента начала перетаскивания, а затем по мере перетаскивания вычислите новое преобразование как:
translate = (uMouse,vMouse) - (uMouseDragStart, vMouseDragStart) + origTranslate
В коде вы напишете это как дополнение к Точке. Я объяснил это как (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
из вашего обратного вызова, как только вы действовали на перетаскиваемом меше.