65.9K
CodeProject 正在变化。 阅读更多。
Home

Editor3D:一个带有C#交互式3D编辑器的Windows.Forms渲染控件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.97/5 (152投票s)

2021年2月4日

CPOL

10分钟阅读

viewsIcon

288550

downloadIcon

8019

一个易于使用的 3D 控件,可以在几分钟内集成到应用程序中

下载Zip文件 (源代码 + 已编译的Exe) - 897 KB - 版本 2024年6月15日

特点

  • 新内容BUG修复:绘制表面网格中缺失的表面点。
  • 新演示“表面缺失”展示了如何绘制带有缺失点的曲面图。
  • 用户鼠标操作可100%自定义。
  • 轴图例也可以绘制在主轴的末端。
  • X轴和Y轴可以镜像。
  • 可选择是否包含Z轴的零值。
  • 增加了用户操作的撤销/重做缓冲区。
  • BUG修复:绘制选定的多色线条
  • 该控件已完全重写(4100行代码,文件大小170 KB!)
  • 用户可以在按住ALT键的同时用鼠标选择3D对象。
  • 用户可以用鼠标在3D空间中移动点或对象。
  • 回调提供对用户操作和对象选择的完全控制。
  • 3D对象可以即时添加、修改和删除。
  • 新演示“动画”展示了如何动态更改3D对象的属性。
  • 当3D编辑器获得键盘焦点时,边框颜色会改变。
  • 缩放时,线宽和散点大小会随之调整。
  • 可配置为仅使用左键或中键进行所有移动。
  • 支持绘制3D对象。添加了示例“金字塔”和“球体”。
  • 渲染速度优化到极致。
  • BUG修复:有时Z轴会绘制在3D对象上方而不是后方。
  • 当鼠标悬停在3D点上时显示工具提示。
  • 调整3D控件大小时调整3D对象的大小。
  • 完全重写以允许同时显示多个图表。
  • 每个图表的独立配色方案。
  • 曲面图也可以绘制为网格。
  • 用户消息可以绘制到控件中。
  • 添加了散点方块和三角形。
  • 将屏幕截图复制到图像。
  • 通过编程设置Rho、Theta、Phi。
  • 绘制散点图。
  • 坐标系现在也支持负值。
  • 用于System.Windows.Forms应用程序的通用即用型3D图表控件。
  • 派生自UserControl。
  • 目标:Framework 4(Visual Studio 2010或更高版本)。
  • 显示3维函数或二进制数据(X、Y、Z值)。
  • 由经验丰富的程序员编写的非常干净和可重用的代码。
  • 所有代码都在一个C#文件中,代码行数少于1200行。
  • 可选的函数编译器允许输入字符串形式的公式。
  • 可选的坐标系,带有栅格线和标签。
  • 可选的多种配色方案。
  • 用户可以使用鼠标或3个可选的TrackBar进行旋转、升高和缩放。
  • 也可以使用鼠标滚轮进行缩放,但仅当3D图表获得焦点时。
  • 整个代码经过优化以达到最大可能的速度。
  • 可选的图例在左上角向用户显示当前的旋转角度。
  • 可选的图例在左下角显示用户自定义的轴文本。
  • 多边形之间的黑线可以关闭。
  • 3D输入数据的自动归一化,有3个选项。

为什么是这个项目?

我正在编写一个ECU调整软件HUD ECU Hacker,需要一个3D查看器来显示校准表。

我在网上搜索了一个即用型3D控件,但找不到符合我需求的。
像Helix Toolkit这样庞大的3D软件项目(220 MB)对于我的小项目来说过于臃肿。

250美元到2900美元的商业3D软件也不是一个选择。

WPF 3D Chart (来自Jianzhong Zhang)

我在Codeproject上找到了WPF 3D Chart

它非常快,因为WPF使用硬件加速。
图形处理器可以渲染必须由三角形组成的三维表面。
但渲染线条很困难。每条线都必须定义为两个三角形。
我需要线条来绘制坐标系。
我还需要线条来显示3D表面上的离散值。
我希望数据表中的每个值都表示为3D对象上的一个多边形。
顶部的屏幕截图显示了一个包含22行17列数据表的表示。
我发现用WPF实现这个太复杂了。
将WPF控件集成到Windows.Forms应用程序中需要额外的T作。请参阅这篇文章

Plot 3D (来自Michal Brylka)

然后我在Codeproject上找到了Plot 3D
这更符合我的需求,但代码不可重用,并且存在许多问题。

这是Codeproject或Github上许多作者从未完成、有bug且功能缺失的项目之一。
没有有效的方法来旋转3D对象。你必须指定3D观察者坐标而不是旋转角度,这是一个完全错误的设计。
修复后,我发现旋转会在某些角度产生丑陋的绘图伪影。
原因是多边形没有按正确的顺序渲染。
由于错误的编程,代码性能很差。例如,在OnPaint()中,他每次创建100个画笔,然后又将它们释放。
代码只为公式设计,无法从数据表中分配固定值。

Editor3D (来自Elmü)

我最终从头重写了Plot 3D,修复了bug并添加了许多缺失的功能。
结果是一个UserControl,您可以将其不变地复制到您的项目中,并在几分钟内使其工作。
我的控件的功能已在上面列出。
由于我的代码不使用硬件加速,所以您显示的多边形数量决定了绘图速度。
您可以毫无问题地用鼠标实时旋转和提升演示中的3D对象,没有任何延迟。
但是,如果您想渲染更多的多边形,速度显然会变慢。
为了我的目的,我需要不到2000个多边形,这允许用鼠标进行实时旋转。
下载ZIP文件,然后运行已编译的EXE文件,试玩一下,您就会看到速度。

演示:曲面填充

在这里您看到的是一个包含22x17个值的表格数据,以带有坐标系的3D曲面显示。

int[,] s32_Values = new int[,]
{
    { 9059,   9634, 10617, 11141, ....., 15368, 15368, 15368, 15368, 15368 }, // row 1
    { 9684,  10387, 11141, 11796, ....., 15794, 15794, 15794, 15794, 15794 }, // row 2
    .........
    { 34669, 34210, 33653, 33096, ....., 27886, 26492, 25167, 25167, 25167 }, // row 21
    { 34767, 34210, 33718, 33096, ....., 27984, 26492, 25167, 25167, 25167 }  // row 22
};

int s32_Cols = s32_Values.GetLength(1);
int s32_Rows = s32_Values.GetLength(0);

cColorScheme i_Scheme = new cColorScheme(me_ColorScheme);
cSurfaceData i_Data   = new cSurfaceData(e_Mode, s32_Cols, s32_Rows, Pens.Black, i_Scheme);

for (int C=0; C<i_Data.Cols; C++)
{
    for (int R=0; R<i_Data.Rows; R++)
    {
        int s32_RawValue = s32_Values[R,C];

        double d_X = C * 640.0; // X must be related to colum
        double d_Y = R *   5.0; // Y must be related to row
        double d_Z = s32_RawValue / 327.68;

        String s_Tooltip = String.Format("Speed = {0} rpm\nMAP = {1} kPa\n"
                                       + "Volume Eff. = {2} %\nColumn = {3}\nRow = {4}", 
                                         d_X, d_Y, Editor3D.FormatDouble(d_Z), C, R);

        cPoint3D i_Point = new cPoint3D(d_X, d_Y, d_Z, s_Tooltip, s32_RawValue);

        i_Data.SetPointAt(C, R, i_Point);
    }
}

editor3D.Clear();
editor3D.Normalize = eNormalize.Separate;
editor3D.AxisY.Mirror = true;
editor3D.AxisX.LegendText = "Engine Speed (rpm)";
editor3D.AxisY.LegendText = "MAP (kPa)";
editor3D.AxisZ.LegendText = "Volume Efficiency (%)";
editor3D.AddRenderData(i_Data);

editor3D.Selection.Callback       = OnSelectEvent;
editor3D.Selection.HighlightColor = Color.FromArgb(90, 90, 90); // gray
editor3D.Selection.MultiSelect    = true;
editor3D.Selection.Enabled        = true;
editor3D.Invalidate();

 

当您使用不相关的X、Y和Z离散值时(如本例),请确保使用参数eNormalize.Separate单独归一化X、Y和Z值,因为轴的范围不同。

网格中的每个点都分配有一个工具提示,显示X、Y、Z、行、列和原始值。

此演示允许用户在按住ALT键的同时选择网格中的多个多边形或点。
然后,在按住ALT + CTRL键的同时,可以用鼠标修改所选点的Z值。
选择和移动在用户定义的回调中处理:OnSelectEvent()

镜像轴

System.Windows.Forms 3D Editor Control in C#

使用演示“曲面填充”来测试“镜像X”和“镜像Y”复选框。

 

演示:数学回调

System.Windows.Forms 3D Editor Control in C#

或者您可以编写一个C#回调函数,根据给定的X和Y值计算Z值。

cColorScheme i_Scheme = new cColorScheme(me_ColorScheme);
cSurfaceData i_Data   = new cSurfaceData(ePolygonMode.Fill, 49, 33, Pens.Black, i_Scheme);

delRendererFunction f_Callback = delegate(double X, double Y)
{
    double r = 0.15 * Math.Sqrt(X * X + Y * Y);
    if (r < 1e-10) return 120;
    else           return 120 * Math.Sin(r) / r;
};

i_Data.ExecuteFunction(f_Callback, new PointF(-120, -80), new PointF(120, 80));

editor3D.Clear();
editor3D.Normalize = eNormalize.MaintainXYZ;
editor3D.AddRenderData(i_Data);
editor3D.Invalidate();

在X轴从-120到+120,Y轴从-80到+80上显示一个调制正弦函数。
49列和33行点会产生48列和32行多边形(总共1536个)。

当您使用函数时,请确保使用参数eNormalize.MaintainXYZ,以防止X、Y和Z值之间的关系失真。

 

演示:数学公式

System.Windows.Forms 3D Editor Control in C#

或者您可以让用户输入一个将在运行时编译的字符串公式。

cColorScheme i_Scheme = new cColorScheme(me_ColorScheme);
cSurfaceData i_Data   = new cSurfaceData(ePolygonMode.Fill, 41, 41, Pens.Black, i_Scheme);

String s_Formula = "7 * sin(x) * cos(y) / (sqrt(sqrt(x * x + y * y)) + 0.2)";
delRendererFunction f_Function = FunctionCompiler.Compile(s_Formula);
i_Data.ExecuteFunction(f_Function, new PointF(-7, -7), new PointF(7, 7));

editor3D.Clear();
editor3D.Normalize = eNormalize.MaintainXYZ;
editor3D.AddRenderData(i_Data);
editor3D.Invalidate();

 

演示:散点图

System.Windows.Forms 3D Editor Control in C#

 

cColorScheme i_Scheme = new cColorScheme(me_ColorScheme);
cScatterData i_Data   = new cScatterData(i_Scheme);

for (double P = -22.0; P < 22.0; P += 0.1)
{
    double d_X = Math.Sin(P) * P;
    double d_Y = Math.Cos(P) * P;
    double d_Z = P;
    if (d_Z > 0.0) d_Z /= 3.0;

    cPoint3D i_Point = new cPoint3D(d_X, d_Y, d_Z, "Scatter Point");
    i_Data.AddShape(i_Point, eScatterShape.Circle, 3, null);
}
 
editor3D.Clear();
editor3D.Normalize = eNormalize.Separate;
editor3D.AddRenderData(i_Data);
editor3D.Invalidate();

 

演示:散点形状

System.Windows.Forms 3D Editor Control in C#

此演示显示负值用红色方块表示,正值用绿色三角形表示。
此图中的每个点由4个双精度浮点数组成:X、Y、Z和一个值。
该值定义方块或三角形的大小,而X、Y、Z定义位置。
该值显示在工具提示中。

选择了4个形状(蓝色),可以用鼠标在3D空间中移动。

double[,] d_Values = new double[,]
{
    // Value  X        Y      Z
    {   0.39, 0.0051,  0.133, 0.66 },
    {   0.23, 0.0002,  0.114, 0.87 },
    {   1.46, 0.0007,  0.077, 0.72 },
    {  -1.85, 0.0137,  0.053, 0.87 },
    ......
}

// A ColorScheme is not needed because all points have their own Brush
cScatterData i_Data = new cScatterData(null);

for (int P = 0; P < d_Values.GetLength(0); P++)
{
    double d_Value = d_Values[P, 0];
    int s32_Radius = (int)Math.Abs(d_Value) + 1;

    double X = d_Values[P,1];
    double Y = d_Values[P,2];
    double Z = d_Values[P,3];

    eScatterShape e_Shape = (d_Value < 0) ? eScatterShape.Square : eScatterShape.Triangle;
    Brush         i_Brush = (d_Value < 0) ? Brushes.Red          : Brushes.Lime;

    String s_Tooltip = "Value = " + Editor3D.FormatDouble(d_Value);
    cPoint3D i_Point = new cPoint3D(X, Y, Z, s_Tooltip, d_Value);

    i_Data.AddShape(i_Point, e_Shape, s32_Radius, i_Brush);
}

editor3D.Clear();
editor3D.Normalize = eNormalize.Separate;
editor3D.AddRenderData(i_Data);
editor3D.Invalidate();

 

演示:嵌套图表

System.Windows.Forms 3D Editor Control in C#

此演示展示了如何同时显示两个图表。
它还展示了如何将消息作为图例添加到用户(左下角)。
此演示演示了单点选择。用户一次只能选择一个点。

const int POINTS = 8;
cSurfaceData i_Data1 = new cSurfaceData(ePolygonMode.Lines, POINTS, POINTS, new Pen(Color.Orange, 3), null);
cSurfaceData i_Data2 = new cSurfaceData(ePolygonMode.Lines, POINTS, POINTS, new Pen(Color.Green,  2), null);

for (int C=0; C<POINTS; C++)
{
    for (int R=0; R<POINTS; R++)
    {
        double d_X = (C - POINTS / 2.3) / (POINTS / 5.5); // X must be related to colum
        double d_Y = (R - POINTS / 2.3) / (POINTS / 5.5); // Y must be related to row
        double d_Radius = Math.Sqrt(d_X * d_X + d_Y * d_Y);
        double d_Z = Math.Cos(d_Radius) + 1.0;

        String  s_Tooltip = String.Format("Col = {0}\nRow = {1}", C, R);
        cPoint3D i_Point1 = new cPoint3D(d_X, d_Y, d_Z,       s_Tooltip + "\nWrong Data");
        cPoint3D i_Point2 = new cPoint3D(d_X, d_Y, d_Z * 0.6, s_Tooltip + "\nCorrect Data");

        i_Data1.SetPointAt(C, R, i_Point1);
        i_Data2.SetPointAt(C, R, i_Point2);
    }
}

cMessgData i_Mesg1 = new cMessgData("Graph with error data",   7,  -7, Color.Orange);
cMessgData i_Mesg2 = new cMessgData("Graph with correct data", 7, -24, Color.Green);

editor3D.Clear();
editor3D.Normalize = eNormalize.MaintainXY;
editor3D.AddRenderData (i_Data1, i_Data2);
editor3D.AddMessageData(i_Mesg1, i_Mesg2);
editor3D.Selection.MultiSelect = false;
editor3D.Selection.Enabled     = true;
editor3D.Invalidate();

 

演示:金字塔

System.Windows.Forms 3D Editor Control in C#

此演示展示了一个由线条组成的简单3D对象。
通常线条以纯色绘制。
但此演示以彩虹方案的颜色分50部分渲染垂直线。

cLineData i_Data = new cLineData(new cColorScheme(me_ColorScheme));

cPoint3D i_Center  = new cPoint3D(45, 45, 40, "Center");
cPoint3D i_Corner1 = new cPoint3D(45, 25, 20, "Corner 1");
cPoint3D i_Corner2 = new cPoint3D(25, 45, 20, "Corner 2");
cPoint3D i_Corner3 = new cPoint3D(45, 65, 20, "Corner 3");
cPoint3D i_Corner4 = new cPoint3D(65, 45, 20, "Corner 4");

// Add the 4 vertical lines which are rendered as 50 parts with different colors
cLine3D i_Vert1 = i_Data.AddMultiColorLine(50, i_Center, i_Corner1, 4, null);
cLine3D i_Vert2 = i_Data.AddMultiColorLine(50, i_Center, i_Corner2, 4, null);
cLine3D i_Vert3 = i_Data.AddMultiColorLine(50, i_Center, i_Corner3, 4, null);
cLine3D i_Vert4 = i_Data.AddMultiColorLine(50, i_Center, i_Corner4, 4, null);

// Add the 4 base lines with solid color
cLine3D i_Hor1 = i_Data.AddSolidLine(i_Corner1, i_Corner2, 8, null);
cLine3D i_Hor2 = i_Data.AddSolidLine(i_Corner2, i_Corner3, 8, null);
cLine3D i_Hor3 = i_Data.AddSolidLine(i_Corner3, i_Corner4, 8, null);
cLine3D i_Hor4 = i_Data.AddSolidLine(i_Corner4, i_Corner1, 8, null);

editor3D.Clear();
editor3D.Normalize = eNormalize.Separate;
editor3D.AxisZ.IncludeZero = false;
editor3D.AddRenderData(i_Data);
editor3D.Invalidate();

包含Z值为零

System.Windows.Forms 3D Editor Control in C#

使用演示“金字塔”来测试复选框“包含零Z值”。
金字塔的Z值范围从20到40。
您可以选择Z轴的底部是0还是20。

 

演示:球体

System.Windows.Forms 3D Editor Control in C#

此演示展示了另一个使用多边形渲染的3D对象。
如果您曾使用过其他3D库(WPF、Direct3D),您会知道所有表面都必须渲染为三角形。
但我的库允许传递任意数量角的(最少3个)多边形。
这个椭圆球体包含一个顶部和底部有50个角的圆形多边形。

The code of this demo is a bit longer.
Have a look into the source code.

 

修改3D对象

System.Windows.Forms 3D Editor Control in C#

在演示应用程序中,通过“点选择”复选框,您可以选择要选择点还是线条。
按住ALT键并单击金字塔的一个点以选择它。一个绿色圆圈将其标记为已选中。
然后按住ALT + CTRL键,用鼠标在3D空间中拖动选定的点。

所有这些都在选择回调中处理,您可以100%控制所有用户操作。

选择回调

void DemoPyramid()
{
    .....
    editor3D.Selection.HighlightColor = Color.Green;
    editor3D.Selection.Callback       = OnSelectEvent;
    editor3D.Selection.MultiSelect    = true;
    editor3D.Selection.Enabled        = true;
    .....
}

eInvalidate OnSelectEvent(eAltEvent e_Event, Keys e_Modifiers,
                          int s32_DeltaX, int s32_DeltaY, cObject3D i_Object)
{
    eInvalidate e_Invalidate = eInvalidate.NoChange;

    bool b_CTRL = (e_Modifiers & Keys.Control) > 0;

    if (e_Event == eAltEvent.MouseDown && !b_CTRL && i_Object != null)
    {
        i_Object.Selected = !i_Object.Selected; // toggle selection

        // After changing the selection status the objects must be redrawn.
        e_Invalidate = eInvalidate.Invalidate;
    }
    else if (e_Event == eAltEvent.MouseDrag && b_CTRL)
    {
        cPoint3D i_Project = editor3D.ReverseProject(s32_DeltaX, s32_DeltaY);

        foreach (cPoint3D i_Selected in editor3D.Selection.GetSelectedPoints(eSelType.All))
        {
            i_Selected.Move(i_Project.X, i_Project.Y, i_Project.Z);
        }

        // Set flag to recalculate the coordinate system, then Invalidate()
        e_Invalidate = eInvalidate.CoordSystem;
    }

    return e_Invalidate;
}

回调函数OnSelectEvent()接收多个参数。
请阅读函数Editor3D.SelectionCallback()的注释,其中有解释。
在第一个if()中,当鼠标在按住ALT键但未按CTRL键的情况下按下时,点/对象的选择会切换。
else if()中,当用户拖动点/对象时,鼠标的相对移动会被反向投影到3D空间中。
然后,这个X、Y、Z方向的3D移动会被添加到所选点的X、Y、Z坐标中。

您可以编写自己的回调函数,它会执行您想做的任何操作来操纵3D对象。
您可以更改3D对象的坐标、颜色、形状、大小、选择状态、工具提示等。

请注意状态栏,它显示所有鼠标事件。

System.Windows.Forms 3D Editor Control in C#

 

选择整个3D图形

您可以将自己的数据分配给任何3D对象的Tag属性。
此数据可以是List<cObject3D>或您项目中的任何类或结构。
当用户点击或拖动3D对象时调用回调函数时,您可以从Tag中获取数据。
以下代码演示了当用户点击由线条、形状和多边形组成的3D图形中的一个时,如何选择整个图形。

// Add all parts of your 3D figure to a list
List<cObject3D> i_Parts = new List<cObject3D>();
i_Parts.Add(i_MyLine1);
i_Parts.Add(i_MyLine2);
i_Parts.Add(i_MyShape1);
i_Parts.Add(i_MyPolygon1);
i_Parts.Add(i_MyPolygon2);

i_MyLine1.Tag    = i_Parts;
i_MyLine2.Tag    = i_Parts;
i_MyShape1.Tag   = i_Parts;
i_MyPolygon1.Tag = i_Parts;
i_MyPolygon2.Tag = i_Parts;

.....

editor3D.Selection.SinglePoints = false;

.....

private eInvalidate OnSelectEvent(eAltEvent e_Event, Keys e_Modifiers,
                                  int s32_DeltaX, int s32_DeltaY, cObject3D i_Object)
{
    bool b_CTRL = (e_Modifiers & Keys.Control) > 0;

    if (e_Event == eAltEvent.MouseDown && !b_CTRL &&
        i_Object != null && i_Object.Tag is List<cObject3D>)
    {
        bool b_Selected = !i_Object.Selected; // toggle selection
        foreach (cObject3D i_Part in (List<cObject3D>)i_Object.Tag)
        {
            i_Part.Selected = b_Selected;
        }
        return eInvalidate.Invalidate;
    }

    return eInvalidate.NoChange;
}

 

删除3D对象

System.Windows.Forms 3D Editor Control in C#

在演示“球体”中,您可以选择多边形并通过按下DEL键删除它们。

editor3D.KeyDown += new KeyEventHandler(OnEditorKeyDown);

void OnEditorKeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode != Keys.Delete)
        return;

    foreach (cObject3D i_Polygon in editor3D.Selection.GetSelectedObjects(eSelType.Polygon))
    {
        editor3D.RemoveObject(i_Polygon);
    }
    editor3D.Invalidate();
}

 

演示动画

System.Windows.Forms 3D Editor Control in C#

此演示使用计时器更新50个散点圆和一个由5个多边形组成金字塔。
正弦波缓慢地上下扫动,并逐渐变化成彩虹的所有颜色。
金字塔围绕其自身轴旋转并上下浮动。

计时器每100毫秒调用此函数。

void ProcessAnimation()
{
    ms32_AnimationAngle ++;

    // ======== SCATTER =========

    cShape3D[]   i_AllShapes   = mi_SinusData.AllShapes;
    cColorScheme i_ColorScheme = mi_SinusData.ColorScheme;
    double       d_DeltaX      = 400.0 / i_AllShapes.Length;

    double d_X = -200.0;
    for (int S=0; S<i_AllShapes.Length; S++, d_X += d_DeltaX)
    {
        cShape3D i_Shape = i_AllShapes[S];

        i_Shape.Points[0].X =  d_X;
        i_Shape.Points[0].Y = -d_X;
        i_Shape.Points[0].Z = Math.Sin((ms32_AnimationAngle + d_X) / 50.0) * 50.0 + 50.0;

        i_Shape.Brush = i_ColorScheme.GetBrush(ms32_AnimationAngle * 10);
    }

    // ======== PYRAMID =========

    double d_Angle   = ms32_AnimationAngle / 30.0;
    double d_Sinus   = Math.Sin(d_Angle) * 50.0; // -50 ... +50
    double d_Cosinus = Math.Cos(d_Angle) * 50.0; // -50 ... +50
    double d_DeltaZ  = d_Sinus / 2.0;            // -25 ... +25

    // Top
    mi_Pyramid[0].X = -100.0;
    mi_Pyramid[0].Y = -100.0;
    mi_Pyramid[0].Z =   70.0 + d_DeltaZ;
    // Edge 1
    mi_Pyramid[1].X = -100.0 + d_Sinus;
    mi_Pyramid[1].Y = -100.0 + d_Cosinus;
    mi_Pyramid[1].Z =   40.0 + d_DeltaZ;
    // Edge 2
    mi_Pyramid[2].X = -100.0 + d_Cosinus;
    mi_Pyramid[2].Y = -100.0 - d_Sinus;
    mi_Pyramid[2].Z =   40.0 + d_DeltaZ;
    // Edge 3
    mi_Pyramid[3].X = -100.0 - d_Sinus;
    mi_Pyramid[3].Y = -100.0 - d_Cosinus;
    mi_Pyramid[3].Z =   40.0 + d_DeltaZ;
    // Edge 4
    mi_Pyramid[4].X = -100.0 - d_Cosinus;
    mi_Pyramid[4].Y = -100.0 + d_Sinus;
    mi_Pyramid[4].Z =   40.0 + d_DeltaZ;
}

 

工具提示

System.Windows.Forms 3D Editor Control in C#

当鼠标悬停在每个多边形角上时,会显示一个工具提示。
我用洋红色标记了球体背面部分的工具提示位置,用粉色标记了正面部分的工具提示位置。
如果您使用ePolygonMode.Fill,您也会看到不可见角的工具提示。
这意味着在右侧截图的一个矩形中,您可能会看到10个工具提示而不是4个。
修复这个问题需要检测一个角是否被一个多边形覆盖,这会极大地降低性能。
如果您觉得这很 confusing,我建议关闭工具提示。

editor3D.TooltipMode = eTooltip.Off;

 

演示:情人节

最后但同样重要的是
这个演示是2021年2月14日写的。

System.Windows.Forms 3D Editor Control in C#

 

祝您使用我的库愉快。请阅读代码中大量的注释!

Elmü

Editor3D:一个带有C#交互式3D编辑器的Windows.Forms渲染控件 - CodeProject - 代码之家
© . All rights reserved.