我试图在没有OpenGL的环境中复制OpenGL行为时遇到问题.
基本上我需要从我的程序创建的行列表创建一个SVG文件.这些线是使用一个ostique投影创建的.
我确定这些行是正确计算的,因为如果我尝试使用OpenGL上下文与正投影并将结果保存到图像中,图像是正确的.
当我使用没有OpenGL的完全相同的行时,会出现这个问题.
我已经复制了OpenGL投影和查看矩阵,并且我像这样处理每个线点:
3D_output_point = projection_matrix * view_matrix * 3D_input_point
然后我计算它的屏幕(SVG文件)位置像这样:
2D_point_x = (windowWidth / 2) * 3D_point_x + (windowWidth / 2) 2D_point_y = (windowHeight / 2) * 3D_point_y + (windowHeight / 2)
我计算这个othographic投影矩阵:
float range = 700.0f; float l,t,r,b,n,f; l = -range; r = range; b = -range; t = range; n = -6000; f = 8000; matProj.SetValore(0,2.0f / (r - l)); matProj.SetValore(0,1,0.0f); matProj.SetValore(0,2,3,0.0f); matProj.SetValore(1,0.0f); matProj.SetValore(1,2.0f / (t - b)); matProj.SetValore(1,0.0f); matProj.SetValore(2,0.0f); matProj.SetValore(2,(-1.0f) / (f - n)); matProj.SetValore(2,0.0f); matProj.SetValore(3,-(r + l) / (r - l)); matProj.SetValore(3,-(t + b) / (t - b)); matProj.SetValore(3,-n / (f - n)); matProj.SetValore(3,1.0f);
和视图矩阵这样:
CVettore position,lookAt,up; position.AssegnaCoordinate(rtRay->m_pCam->Vp.x,rtRay->m_pCam->Vp.y,rtRay->m_pCam->Vp.z); lookAt.AssegnaCoordinate(rtRay->m_pCam->Lp.x,rtRay->m_pCam->Lp.y,rtRay->m_pCam->Lp.z); up.AssegnaCoordinate(rtRay->m_pCam->Up.x,rtRay->m_pCam->Up.y,rtRay->m_pCam->Up.z); up[0] = -up[0]; up[1] = -up[1]; up[2] = -up[2]; CVettore zAxis,xAxis,yAxis; float length,result1,result2,result3; // zAxis = normal(lookAt - position) zAxis[0] = lookAt[0] - position[0]; zAxis[1] = lookAt[1] - position[1]; zAxis[2] = lookAt[2] - position[2]; length = sqrt((zAxis[0] * zAxis[0]) + (zAxis[1] * zAxis[1]) + (zAxis[2] * zAxis[2])); zAxis[0] = zAxis[0] / length; zAxis[1] = zAxis[1] / length; zAxis[2] = zAxis[2] / length; // xAxis = normal(cross(up,zAxis)) xAxis[0] = (up[1] * zAxis[2]) - (up[2] * zAxis[1]); xAxis[1] = (up[2] * zAxis[0]) - (up[0] * zAxis[2]); xAxis[2] = (up[0] * zAxis[1]) - (up[1] * zAxis[0]); length = sqrt((xAxis[0] * xAxis[0]) + (xAxis[1] * xAxis[1]) + (xAxis[2] * xAxis[2])); xAxis[0] = xAxis[0] / length; xAxis[1] = xAxis[1] / length; xAxis[2] = xAxis[2] / length; // yAxis = cross(zAxis,xAxis) yAxis[0] = (zAxis[1] * xAxis[2]) - (zAxis[2] * xAxis[1]); yAxis[1] = (zAxis[2] * xAxis[0]) - (zAxis[0] * xAxis[2]); yAxis[2] = (zAxis[0] * xAxis[1]) - (zAxis[1] * xAxis[0]); // -dot(xAxis,position) result1 = ((xAxis[0] * position[0]) + (xAxis[1] * position[1]) + (xAxis[2] * position[2])) * -1.0f; // -dot(yaxis,eye) result2 = ((yAxis[0] * position[0]) + (yAxis[1] * position[1]) + (yAxis[2] * position[2])) * -1.0f; // -dot(zaxis,eye) result3 = ((zAxis[0] * position[0]) + (zAxis[1] * position[1]) + (zAxis[2] * position[2])) * -1.0f; // Set the computed values in the view matrix. matView.SetValore(0,xAxis[0]); matView.SetValore(0,yAxis[0]); matView.SetValore(0,zAxis[0]); matView.SetValore(0,0.0f); matView.SetValore(1,xAxis[1]); matView.SetValore(1,yAxis[1]); matView.SetValore(1,zAxis[1]); matView.SetValore(1,0.0f); matView.SetValore(2,xAxis[2]); matView.SetValore(2,yAxis[2]); matView.SetValore(2,zAxis[2]); matView.SetValore(2,0.0f); matView.SetValore(3,result1); matView.SetValore(3,result2); matView.SetValore(3,result3); matView.SetValore(3,1.0f);
从OpenGL和SVG输出中得到的结果是完全不同的,但是在两天内我无法提出解决方案.
这是OpenGL输出
这是我的SVG输出
正如你所看到的,它的旋转不是可靠的.
任何想法为什么?线点也是一样的,也是矩阵,希望.
正在创建的矩阵不正常.我的意思是,矩阵是错误的,我认为,因为OpenGL没有显示任何东西.
所以我试着做相反的,我在OpenGL中创建了矩阵,并用我的代码.结果更好,但还不完美.
现在我觉得我做了一些错误的将3D点映射到2D屏幕点,因为我得到的点在Y中被反转,我仍然有一些线不完全匹配.
这是我使用OpenGL矩阵和我以前的方法将3D点映射到2D屏幕空间(这是SVG,而不是OpenGL渲染):
这是从OpenGL获得的投影矩阵:
这就是我用这些矩阵和通过改变我的二维点Y坐标计算得到的结果,如bofjas所说:
看起来有些旋转丢失了.我的相机在X轴和Y轴都有30°的旋转,看起来它们的计算不正确.
现在我正在使用与OpenGL相同的矩阵.所以我认为当我将3D点映射到2D屏幕坐标时,我做了一些错误的计算.
解决方法
而不是调试自己的代码,您可以使用
transform feedback来使用OpenGL管道来计算线条的投影.而不是在屏幕上光栅化它们,您可以将它们捕获在内存缓冲区中,并直接保存到SVG中.设置它有点涉及,取决于您的OpenGL编码方法的确切设置,但它可能是一个更简单的解决方案.
根据你自己的代码,它看起来像是将x和y坐标混合在一起,或者是行主要和列主要矩阵.