我可以使用
以我想要的颜色绘制Model3DGroupMaterial material = new DiffuseMaterial(new SolidColorBrush(Colors.White));
GeometryModel3D model = new GeometryModel3D(mesh, material);
(关注this教程)
设置我在Model3DGroup中包含的GeometryModel3D的颜色。
我有一个应用程序,我必须在3D地形上放置地图(地形完全平坦),地图不是图像,我有我想要绘制的形状点的详细数据,以及我还有想要在3D表面上投影的所有形状的DrawingVisual对象。在2D模式下,我在自定义画布上绘制它们(从Canvas派生),然后使用
添加它们myCanvas.addVisualChild(item);
myCanvas.addLogicvalChild(item);
我的问题是如何在3D项目上“绘画”或绘制形状和线条等?这些形状不能完全覆盖地形。我尝试使用Viewport2DVisual3D类,并尝试使用以下代码在3D表面(带按钮的简单画布)上放置画布:
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类,因为:
此外我无法在任何地方使用Viewport2DVisual3D,因为当我将地图投影到3D地形时,我还必须创建建筑物等模型,因此我将不得不绘制建筑模型的区域(这将是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上最初的绘画问题仍然存在,怎么做?
答案 0 :(得分:1)
这可能有点晚了,但我遇到了一个非常类似的问题。虽然上面的工作对于较小的网格很好,但是一旦你进入成百上千(或更多)三角形,它就会变慢。我实现的替代方法是为所有网格/集合使用统一材质,但使用线性渐变画笔为材质指定渐变颜色(根据需要设置的停止和颜色,以实现您想要实现的目标)。然后通过使用纹理坐标,可以设置给定三角形的颜色(如果您想要纯色,则所有三个纹理坐标都是相同的点)。这种方法效果更好,对于大网格(10k及以上)更有效,只需要额外的时间来设置画笔和指定纹理坐标。相同/相似的方法也可用于通过命中测试或类似方法改变三角形的颜色,从而仅提供三角形的顶点(索引)和源网格(因此提供需要更新的纹理坐标的索引)
答案 1 :(得分:0)
经过一些实验,我得到答案,简单的方法是在定义网格时设置每个三角形的颜色。在WPF中,需要的是在定义新的GeometryModel3D时组合三角形(MeshGeometry3D)和材质时设置材质颜色。
(来自this教程)
Material material = new DiffuseMaterial(
new SolidColorBrush(Colors.DarkKhaki)); //Set color here
GeometryModel3D model = new GeometryModel3D(
mesh, material);
我是3D的初学者,我还没有探索过材料的概念。
如果有人知道其他方式,请在此处发帖。
答案 2 :(得分:0)
所以我在这里使用了一些代码(经过一些修改,根据需要进行调整)。这是在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(Point3D())类型的变量,包含三个位置。分配给每个的颜色是默认材质或随机颜色(如果选中chkColorize)。 Sub还将数据应用于Group3D_RH,Group3D_RH是Model3DGroup对象。 该方法使用固体材料或具有渐变颜色的(常量)纹理(遍历当时可用的所有颜色)。然后,颜色的分配用于定义纹理坐标的点(2D点)。如果三角形的每个点具有相同的点,则三角形最终具有均匀的颜色(基于其沿着颜色梯度的坐标)...... 希望这至少说明了这种方法......