Справка по материалам WPF 3d ImageBrush - PullRequest
1 голос
/ 16 ноября 2009

Я пытаюсь применить материал к моей 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, но у меня НЕТ ИДЕИ, как получить этот тип координаты от щелчка мышью пользователя ...

когда я делаю:

e.MouseDevice.GetPosition (ShardsViewPort3D);

, который дает мне нормальные X / Y-поля щелчка мыши ...

Спасибо за любую помощь, которую вы можете оказать!

1 Ответ

3 голосов
/ 16 ноября 2009

Звучит так, будто вы хотите двигать материал по вашей геометрии, когда вы нажимаете на нее. Вот как это сделать:

Используйте проверку удара, чтобы перевести ваши координаты 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 из вашего обратного вызова, как только вы действовали на перетаскиваемом меше.

...