Как нарисовать определенные области Model3DGroup другим цветом и как добавить визуальные фигуры в Model3DGroup - PullRequest
1 голос
/ 27 ноября 2011

Я могу нарисовать Model3DGroup нужным мне цветом, используя

Material material = new DiffuseMaterial(new SolidColorBrush(Colors.White));
GeometryModel3D model = new GeometryModel3D(mesh, material);

(следующий этот учебник)

для установки цвета GeometryModel3D, который я включаю в Model3DGroup.

У меня есть приложение, в котором я должен разместить карту на местности в 3D (местность полностью плоская), карта не является изображением, и у меня есть подробные данные о точках фигур, которые я хочу нарисовать, и У меня также есть объекты DrawingVisual всех форм, которые я хочу проецировать на трехмерную поверхность. В режиме 2D я рисую их на пользовательском холсте (производном от Canvas), куда я добавляю их, используя

myCanvas.addVisualChild(item);
myCanvas.addLogicvalChild(item);

Мой вопрос заключается в том, как «рисовать» или рисовать фигуры, линии и т. Д. На трехмерных предметах? Эти формы не полностью покрывают местность. Я попытался использовать класс Viewport2DVisual3D и попытался поместить холст на трехмерную поверхность (простой холст с кнопкой), используя следующий код:

Canvas testCanvas = new Canvas();
testCanvas.Background = Brushes.Green;
Button b1 = new Button();
b1.Content = "Hello there";
Canvas.SetTop(b1, 50);
Canvas.SetLeft(b1, 50);
Canvas.SetZIndex(b1, 2);
testCanvas.Children.Add(b1);

testVisual3d.Visual = testCanvas; // testVisual3d is a Viewport2DVisual3D declared in xaml

Но проблема в том, что я не могу понять, как Canvas или любой Visual "заполняет" класс Viewport2DVisual3D, потому что:

  1. Кнопка полностью заполнила холст.
  2. Пустые области холста (Canvas.SetTop (b1, 50)) не видны.
  3. Понятия не имею о размере холста, связанном с размером объекта Viewport2DVisual3D, поскольку кнопка всегда полностью заполняет объект.

Также я не могу использовать Viewport2DVisual3D везде, так как мне также приходится создавать модели зданий и т. Д., Когда я проецирую карту на трехмерную местность, поэтому мне придется рисовать области модели здания (которая будет Model3DGroup). ) иначе, чтобы дать реалистичные эффекты, но если мне удастся спроецировать карту на Viewport2DVisual3D, это решит множество проблем, поскольку я смогу напрямую проецировать все фигуры, включая сетку, на объект или ландшафт Viewport2DVisual3D.

Я использую .NET 4.0 и C #.

Пожалуйста, помогите.

Обновление

Использование этого кода решает начальную проблему размера и пространства холста:

Canvas testCanvas = new Canvas();
testCanvas.Background = Brushes.Green;
Button b1 = new Button();
b1.Width = 120;
b1.Height = 25;

testCanvas.Width = 200;
testCanvas.Height = 200;

b1.Content = "Hello there";
Canvas.SetTop(b1, 50);
Canvas.SetLeft(b1, 50);
Canvas.SetZIndex(b1, 2);
testCanvas.Children.Add(b1);

testVisual3d.Visual = testCanvas;

Размер Viewport2DVisual3D составляет

Positions="0,0,0 0,0,30 30,0,30 30,0,0"

И холст изменяет размеры, чтобы соответствовать границам Viewport2DVisual3D, но будет ли он работать с классом, производным от Canvas, в котором фигуры были непосредственно добавлены с использованием Canvas.AddVisualChild и Canvas.AddLogicalChild, я еще не попробовал это.

А также остается оригинальный вопрос рисования на Model3DGroup, как это сделать?

Ответы [ 3 ]

1 голос
/ 30 октября 2014

Это может быть немного поздно, но у меня были проблемы с очень похожей проблемой. Хотя вышеприведенное прекрасно работает для меньших сеток, как только вы попадаете в сотни и тысячи (или более) треугольников, оно становится медленным. Альтернатива, которую я реализовал, использует унифицированный материал для всех сеток / коллекций, но использует линейную градиентную кисть, чтобы назначить материалу градиентный цвет (остановки и цвета устанавливаются по мере необходимости для того, чего вы пытаетесь достичь). Затем с помощью координат текстуры можно установить цвет данного треугольника (все три координаты текстуры будут одной и той же точкой, если вы хотите иметь сплошной цвет). Этот подход работает намного лучше и более эффективен для больших сеток (10 Кб и более), требующих только дополнительное время для настройки кисти и назначения текстурных координат. Тот же / аналогичный подход также может быть использован для изменения цвета треугольника посредством тестирования попаданий или аналогичного, при котором предоставляются только вершины треугольника (индекс) и исходная сетка (таким образом, предоставляется индекс координат текстуры, которые требуют обновления)

0 голосов
/ 20 сентября 2016

Итак, вот код, который я использовал (с некоторыми изменениями, адаптируясь по мере необходимости).Это в VB, портирование на C # должно быть простым.Обратите внимание, что это копия-вставка из какого-то существующего проекта, поэтому некоторые элементы могут быть не такими четкими, как они могли бы быть ... извините за ленивость ...

Private Sub RefreshRHDisplay()
        'global/input data is RHTris which is a List(of Point3D())
        'updates the data on the display with the available data
        Dim v, f, i As Integer

        'clear geometry
        Group3D_RH.Children.Clear() 'is a Model3DGroup object

        'define lights
        Dim _L As Model3DGroup = GetLighting() 'defines the lighting

        'mesh items
        Dim mesh As New MeshGeometry3D

        'group of items
        Dim geomGroup As New Model3DGroup

        'materials
        Dim mat As MaterialGroup  'the foreground/front material
        Dim bmat As MaterialGroup 'the background/back material

        Dim MatGroup As New MaterialGroup
        Dim ColBrush As Brush = New SolidColorBrush(_bodyCol) : ColBrush.Opacity = 1.0F
        Dim LightBrush As Brush = New SolidColorBrush(Colors.White) : LightBrush.Opacity = 0.3
        Dim _diffuseMaterial As New DiffuseMaterial(ColBrush)
        Dim _specularMaterial As New SpecularMaterial(LightBrush, 300.0F)
        MatGroup.Children.Add(_diffuseMaterial)
        MatGroup.Children.Add(_specularMaterial)

        mat = MatGroup

        MatGroup = New MaterialGroup
        Dim bColBrush As Brush = New SolidColorBrush(Colors.DarkGray) : bColBrush.Opacity = 1.0F
        _diffuseMaterial = New DiffuseMaterial(bColBrush)
        MatGroup.Children.Add(_diffuseMaterial)
        MatGroup.Children.Add(_specularMaterial)

        bmat = MatGroup

        Dim vPts(0) As Point

        'distinguish between direct (uniform color) and colorize mode
        If chkColorize.IsChecked Then 'COLORIZE MODE

'Note: the gradient stop ends at 0.9, this is purely so that I can assign a special color after that.
            Dim gsp As New GradientStopCollection({New GradientStop(Colors.Red, 0.0),
                                                   New GradientStop(Colors.Orange, 0.15),
                                                   New GradientStop(Colors.Yellow, 0.3),
                                                  New GradientStop(Colors.Green, 0.45),
                                                  New GradientStop(Colors.Blue, 0.6),
                                                  New GradientStop(Colors.Indigo, 0.75),
                                                   New GradientStop(Colors.Violet, 0.9)
                                                  })
            Dim lBrsh As New LinearGradientBrush(gsp, New Point(0, 1), New Point(0.9, 1))

            'define random locations for the textures
            ReDim vPts(RHTris.Count - 1)
            Dim rnd As New Random(CInt(Now.Ticks Mod Integer.MaxValue))
            For v = 0 To RHTris.Count - 1
                vPts(v) = New Point(rnd.NextDouble, 1)
            Next

            'replace the default material with the linear gradient
            mat.Children.Clear()
            mat.Children.Add(New DiffuseMaterial(lBrsh))


        End If

        'add all vertices
        For v = 0 To RHTris.Count - 1
            mesh.Positions.Add(RHTris.Item(v)(0))
            mesh.Positions.Add(RHTris.Item(v)(1))
            mesh.Positions.Add(RHTris.Item(v)(2))
        Next
        'add all triangles
        v = 0
        For f = 0 To RHTris.Count - 1
            'If .isVisible Then 'true by def of _visList
            Dim v0, v1, n As Vector3D
            v0 = Point3D.Subtract(RHTris.Item(f)(1), RHTris.Item(f)(0))
            v1 = Point3D.Subtract(RHTris.Item(f)(2), RHTris.Item(f)(0))
            n = Vector3D.CrossProduct(v0, v1)
            mesh.Normals.Add(n)
            mesh.Normals.Add(n)
            mesh.Normals.Add(n)
            mesh.TriangleIndices.Add(v)
            mesh.TriangleIndices.Add(v + 1)
            mesh.TriangleIndices.Add(v + 2)
            v += 3
        Next

        If chkColorize.IsChecked Then 'define the texture coordinates that define the color through the linear gradient brush
            For v = 0 To RHTris.Count - 1
                For i = 0 To 2
                    mesh.TextureCoordinates.Add(vPts(v)) 'add same three points for each location
                Next
            Next
        End If

        'body mesh has been defined, create body and add to visual
        Dim geo As New GeometryModel3D
        geo.Geometry = mesh
        geo.Material = mat
        geo.BackMaterial = bmat


        'combine to group
        geomGroup.Children.Add(geo)

        'add to scene
        Group3D_RH.Children.Add(geomGroup)

        'add lights back in
        Group3D_RH.Children.Add(_L)

    End Sub

Некоторые основные комментарии приведены по порядку: данные находятся в коллекции RHTris, которая является переменной типа List (of Point3D ()), которая содержит три местоположения.Цвет, назначенный каждому из них, является материалом по умолчанию или случайным цветом (если установлен флажок chkColorize).Sub также применяет данные к Group3D_RH, который является объектом Model3DGroup.Подход использует либо сплошной материал, либо (постоянную) текстуру, имеющую цвет с градиентом (проходящий через все доступные цвета).Назначение цвета - определить точку (2D-точку) для координат текстуры.Если каждой точке треугольника назначена одна и та же точка, тогда треугольник в конечном итоге будет иметь одинаковый цвет (на основе его координат вдоль градиента цвета) ... Надеюсь, это хотя бы иллюстрирует подход ...

0 голосов
/ 29 ноября 2011

После небольшого эксперимента у меня есть ответ, простой способ - установить цвет каждого треугольника при определении сетки. В WPF необходимо установить цвет материала при объединении треугольника (MeshGeometry3D) и материала при определении нового GeometryModel3D.

(из это учебник)

Material material = new DiffuseMaterial(
        new SolidColorBrush(Colors.DarkKhaki)); //Set color here
    GeometryModel3D model = new GeometryModel3D(
        mesh, material);

Я новичок в 3D и еще не изучил концепцию материалов.

Если кто-то знает другой путь, пожалуйста, напишите здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...