C#:如何将3D X Y和Z位置转换为2D X和Y位置?

C#:如何将3D X Y和Z位置转换为2D X和Y位置?

问题描述:

我想要的是将3D位置转换为2D位置的某种功能,C#:如何将3D X Y和Z位置转换为2D X和Y位置?

Private Function Get2DPoint(ByRef x As Short, ByRef y As Short, ByRef z As Short) 

    Dim newX = x + z '< Some fancy math 
    Dim newY = y + z '< Some fancy math 

    Dim temp = {newX, newY} 
    Return temp 

End Function 

在线资源,我已签,但我无法理解(我没有复制从页面的信息,因为他们已经启动并运行了很长一段时间,并有在上述页面的大量的信息。):

请不要告诉我,我应该使用预先存在的库。我已经阅读了很多关于这个问题的问题,并且使用了像OpenGL这样的东西。或者其他图书馆不是我想要做的。

我一直在寻找相当长的一段时间,我真的没有更接近理解如何做到这一点,任何和所有的帮助将不胜感激。

如果我忘记提供任何信息,请让我知道,在此先感谢。

注:

  1. 我使用Visual Studio 2015年的Visual Basic编程,但是如果给予的任何代码的例子是在它的罚款:C++,C#,Python和Lua的。或其他类似的编程语言。

  2. 我本来想发布更多的链接,但我没有所需的10+声望。

一切顺利,约瑟夫·富特

+0

什么是您的3D位置?你想要2D位置代表什么,投影在视图矩阵上的相同3D位置? –

+0

好吧,让我们说我的立方体在0,0,0,每个角落距离0,0,0为10个单位。至于视图矩阵,我不太确定那是什么,也许你可以解释一下吗? –

+0

当从一个certine位置观察一个3D物体时,有很少的东西会被计数,物体的位置(您的立方体),相机位置,相机的外观矢量,相机“上”矢量以及相机视角和比率。当你告诉我你在哪里以及物体在哪里时,想想它,但是如果你直视它,并且如果你站立颠倒或者你的眼睛视野有多大,你就不会告诉我。 –

随着你linked example所示,您需要定义一个class你的立方体,在空间中的点class,你照相机的class和矩形中的class它已经存在了System.Drawing.Rectangle

Class Diagram

我不会从C#代码翻译成VB.net SI这可以很容易地完成,这是你的工作:)但我会解释它是如何工作的

首先你需要初始化你想绘制的立方体,然后,你需要定义你想要的起源在您的案例中,3D空间位于您的PictureBox中,可以说您要将(0,0,0)点的立方体中间位于PictureBox中间的中间位置:

//Point is also a System.Drawing type. 
Point origin = new Point(picCube.Width/2, picCube.Height/2); 

现在您只需要随时渲染图片即可。在这个例子中,渲染本身在接收我们刚刚计算的原点的Cubeclass内完成,在示例中,向量始终是Y轴

所有的方法的第一被定义具有以下签名:

//Gets the origin on the PictureBox to be displayed (middle of the PictureBox). 
//Returns the rendered picture. 
public Bitmap drawCube(Point drawOrigin) 

接着,3个变量的声明:

  • 临时三维原点。
  • 临时的2D起源。
  • 24个2D点的数组要绘制(立方体将被绘制为4个四边形 - 每边将绘制两次 - 一次为每一个四边形,这是在本例中一种不好的做法)

这是代码:

PointF[] point3D = new PointF[24]; //Will be actual 2D drawing points 
Point tmpOrigin = new Point(0, 0); 
Math3D.Point3D point0 = new Math3D.Point3D(0, 0, 0); //Used for reference 

然后,摄像机的Z位置相对于被定义为屏幕分辨率,以保持立方体不弄乱:

//Screen is another System.Drawing class. 
//Called "zoom" in the example. 
double baseCameraZ = Screen.PrimaryScreen.Bounds.Width/1.5; 

接下来,根据空间中的立方体的宽度,高度和深度计算立方体的点数(同样,由于它们是按每个面绘制的,所以它们有24个而不是8个),并且相应地调整cameraZ的位置,立方将适合:

 //Just filling a 24 length array of Point3D, you can see in the example their exact order. 
     //note that the order matters mostly so each face's vertexes will be together in the array - one after another. 
     Math3D.Point3D[] cubePoints = fillCubeVertices(width, height, depth); 

     //Calculate the camera Z position to stay constant despite rotation    
     Math3D.Point3D anchorPoint = (Math3D.Point3D)cubePoints[4]; //anchor point 
     double cameraZ = -(((anchorPoint.X - cubeOrigin.X) * baseCameraZ)/cubeOrigin.X) + anchorPoint.Z; 

     //That's the actual camera of the cube - read the example itself for more info. 
     camera1.Position = new Math3D.Point3D(cubeOrigin.X, cubeOrigin.Y, cameraZ); 

下一个功能做transformations over the points using matrices - 你不必了解它是如何工作,但你应该想读一点关于它,它的作用是基本应用旋转立方体并将其定位在相对于原点的3D空间中的固定位置:

//Apply Rotations, moving the cube to a corner then back to middle 
cubePoints = Math3D.Translate(cubePoints, cubeOrigin, point0); 
cubePoints = Math3D.RotateX(cubePoints, xRotation); //The order of these 
cubePoints = Math3D.RotateY(cubePoints, yRotation); //rotations is the source 
cubePoints = Math3D.RotateZ(cubePoints, zRotation); //of Gimbal Lock 
cubePoints = Math3D.Translate(cubePoints, point0, cubeOrigin); 

下一条代码转换空间立方体,他们的结果2D图像中属于的3D点,也存在的情况下的特殊检查点落在相机(这是if句话背后)。再次,如果你想忠实地理解它,你需要了解一些基本Linear Algebra

的最后一件事将是绘制使用Graphics的整体形象:

Rectangle bounds = getBounds(point3D); 
bounds.Width += drawOrigin.X; 
bounds.Height += drawOrigin.Y; 

Bitmap tmpBmp = new Bitmap(bounds.Width, bounds.Height); 
using (Graphics g = Graphics.FromImage(tmpBmp)) 
{ 
    //Back Face 
    g.DrawLine(Pens.Black, point3D[0], point3D[1]); 
    g.DrawLine(Pens.Black, point3D[1], point3D[2]); 
    g.DrawLine(Pens.Black, point3D[2], point3D[3]); 
    g.DrawLine(Pens.Black, point3D[3], point3D[0]); 

    //Front Face 
    g.DrawLine(Pens.Black, point3D[4], point3D[5]); 
    g.DrawLine(Pens.Black, point3D[5], point3D[6]); 
    g.DrawLine(Pens.Black, point3D[6], point3D[7]); 
    g.DrawLine(Pens.Black, point3D[7], point3D[4]); 

    //... Four more faces ... 
} 

现在,所有你需要做的是返回呈现的位图。

注意,在这个例子中,设计不一定是最好的,因为每个对象绘制本身,并不知道ZBuffer和场景中的其他对象,也,本示例使用int!而非float S IN的所有的坐标变量,这会使您失去很多准确性 - 在使用3D渲染器时不应该这样做。

Here is a good source学习在C#和C++最佳实践3D渲染的基础。