Math 三维点到二维功能工作不正常
我已经研究这个话题一段时间了,现在我终于尝试自己去实现它了;但是,由于某些原因,3d点未正确转换为2d点,这意味着我的函数返回了错误的值。这可能来自两种不同的情况: 1) 我的数学不正确 2) 我的矩阵的值不正确 由于我正在反转和使用地址,我不确定矩阵。有没有可能有人检查我的数学,看看是不是数学不正确?在此功能上的任何帮助都将不胜感激。提前感谢您的建议Math 三维点到二维功能工作不正常,math,matrix,3d,2d,point,c#,Math,Matrix,3d,2d,Point,C#,我已经研究这个话题一段时间了,现在我终于尝试自己去实现它了;但是,由于某些原因,3d点未正确转换为2d点,这意味着我的函数返回了错误的值。这可能来自两种不同的情况: 1) 我的数学不正确 2) 我的矩阵的值不正确 由于我正在反转和使用地址,我不确定矩阵。有没有可能有人检查我的数学,看看是不是数学不正确?在此功能上的任何帮助都将不胜感激。提前感谢您的建议 private bool ConvertToScreen(Vector3 position3D, ref Point screenPoint)
private bool ConvertToScreen(Vector3 position3D, ref Point screenPoint)
{
// r is the right rotation (x-axis)
// u is the up rotation (y-axis)
// f is the forward rotation (z-axis)
// p is the position (transform)
Point returnPoint = new Point(300, 400);
// Set Values of Matrix
Matrix matrix = GetMatrix();
// Do the math calculations here
float xPrime = matrix.rX * position3D.x + matrix.rY * position3D.y + matrix.rZ * position3D.z + matrix.rW;
float yPrime = matrix.uX * position3D.x + matrix.uY * position3D.y + matrix.uZ * position3D.z + matrix.uW;
// Dont need zPrime
float wPrime = matrix.pX * position3D.x + matrix.pY * position3D.y + matrix.pZ * position3D.z + matrix.pW;
// If wPrime > 0 we can see the point
if (wPrime <= 0)
{
return false;
}
xPrime *= 1 / wPrime;
yPrime *= 1 / wPrime;
// Relative To Screen Center
xPrime = rect.left + 0.5f * xPrime * (rect.right - rect.left) + 0.5f;
yPrime = rect.top + 0.5f * yPrime * (rect.bottom - rect.top) + 0.5f;
returnPoint = new Point((int)xPrime, (int)yPrime);
screenPoint = returnPoint;
return true;
}
专用布尔变换器屏幕(矢量3位置3D,参考点屏幕点)
{
//r是右旋转(x轴)
//u是向上旋转(y轴)
//f为正向旋转(z轴)
//p是位置(变换)
点返回点=新点(300400);
//矩阵的集值
矩阵=GetMatrix();
//在这里做数学计算
float xPrime=matrix.rX*position3D.x+matrix.rY*position3D.y+matrix.rZ*position3D.z+matrix.rW;
float yPrime=matrix.uX*position3D.x+matrix.uY*position3D.y+matrix.uZ*position3D.z+matrix.uW;
//不需要zPrime
float wPrime=matrix.pX*position3D.x+matrix.pY*position3D.y+matrix.pZ*position3D.z+matrix.pW;
//如果wPrime>0,我们就可以看出这一点
如果(wPrime这个计算有几个步骤,我建议将它分成相应的部分,并对每个部分进行测试
模型到摄像机坐标-这是位置=(x,y,z)
点从模型坐标到摄像机坐标的旋转。这里我们假设摄像机的目标位于原点
local = rot * (position - target)
| x' | | rx ry rz | | x | | rx*x + ry*y + rz*z |
| y' | = | ux uy yz | * | y | = | ux*x + uy*y + uz*z |
| z' | | fx fy fz | | z | | fx*x + fy*y + fz*z |
透视投影-您需要定义目标和相机之间的距离,以及覆盖视图的模型大小。我们将其称为距离
和大小
。结果是视图坐标在x和y方向上都在0..1
之间变化
| vx | | (distance/size)*(x'/(distance+z')) |
| | = | | |
| vy | | (distance/size)*(y'/(distance+z')) |
这来自类似的三角形。如果x'=size
和z'=0
,则vx=1
。越大的z'
越小
像素坐标
在这里,您可以将视图坐标映射为像素。您的视口具有宽度和高度,您希望[0,0]
像素位于左上角,而[width-1,height-1]
位于右下角
width
+-------------------+
|(-1,1) : (1,1)|
| : |
| : (0,0) |
+- - - - -+- - - - -+ height
| : |
| : |
|(-1,-1) : (1,-1)|
+-------------------+
px = (width-1)*(vx+1.0)/2.0
py = (height-1)*(1.0-vy)/2.0
最后,我建议使用OOP编程(如果可能的话)将向量/矩阵数学分解为意图。
通过摄像机的公共静态矢量3(矢量3点、矢量3目标、矩阵3摄像机)
{
返回camera.Transpose()*(点目标);
}
公共静态矢量2透视图(矢量3点,双距离,双尺寸=1)
{
返回新矢量2(
(距离/大小)*(点X/(距离+点Z)),
(距离/大小)*(点Y/(距离+点Z));
}
公共静态点F像素(矢量2点、整数宽度、整数高度)
{
返回新的点F(
(浮动)((宽度-1)*(点X+1)/2),
(浮动)((高度-1)*(1点Y)/2));
}
静态无效dlg_Paint(对象发送器、PaintEventArgs e)
{
表格dlg=作为表格的发件人;
//设置摄影机旋转
Matrix3摄像机=Matrix3.Ry(0.67);
双倍距离=25;
双倍尺寸=20;
对于(int i=0;i您确定绘制2D点(0,0)
会在视口的中心创建一个点吗?此代码会转换为2D点,而不是像素。我以为我正在转换为像素坐标。您能给我指出正确的方向吗
返回视图投影矩阵?是r,u,f
方向向量吗?你称它们为旋转。我想,它们代表矩阵的各个列或行?相对于屏幕中心//下最后的+0.5f
看起来是错误的。相反,你应该用替换xPrime
和yPrime
ode>(xPrime+1)
和(yPrime+1)
。谢谢。所以我相信我得到的是二维坐标,这意味着我需要将二维坐标转换为像素坐标。谢谢你的详细回答。
public static Vector3 ThroughCamera(Vector3 point, Vector3 target, Matrix3 camera)
{
return camera.Transpose()*(point-target);
}
public static Vector2 Perspective(Vector3 point, double distance, double size=1)
{
return new Vector2(
(distance/size)*(point.X/(distance+point.Z)),
(distance/size)*(point.Y/(distance+point.Z)) );
}
public static PointF Pixel(Vector2 point, int width, int height)
{
return new PointF(
(float) ((width-1)*(point.X+1)/2),
(float) ((height-1)*(1-point.Y)/2) );
}
static void dlg_Paint(object sender, PaintEventArgs e)
{
Form dlg=sender as Form;
// Set camera rotation
Matrix3 camera=Matrix3.Ry(0.67);
double distance=25;
double size=20;
for(int i=0; i<10; i++)
{
for(int j=0; j<10; j++)
{
// this is the model points
Vector3 pt=new Vector3(5*(i-5), 5*(j-5), 0);
// these are the points through the camera
Vector3 pt_local=ThroughCamera(pt, Vector3.O, camera);
// these are the view coordinates
Vector2 pt_view=Perspective(pt_local, distance, size);
// these are the pixel coordinates
PointF px=Pixel(pt_view, dlg.ClientSize.Width, dlg.ClientSize.Height);
e.Graphics.DrawRectangle(Pens.Blue, px.X, px.Y, 1f, 1f);
}
}
}