OpenGL如何使用gluUnProject函数得到线解集?

浏览:432672 回答:2
我才接触OpenGL编程没多久,我想得到鼠标点击窗口后对应2D点的3D射线,大家都说用gluUnProjectint函数,但是没有如何使用的例子,MSDN上也只是简单的参数说明,也没有例子,望哪位知晓的讲解一下,万分感谢

原型:
gluUnProject(
GLdouble winx,
GLdouble winy,
GLdouble winz, // 这个Z不知道做什么用的,2D窗口坐标的Z坐标?
const GLdouble modelMatrix[16],
const GLdouble projMatrix[16],
const GLint viewport[4],
GLdouble *objx,
GLdouble *objy,
GLdouble *objz
);
出来后得到了objx,objy,objz,其中objz好象是近剪裁的大小,而这三个值是视点坐标系里的,问题是:

1、如何转换到世界坐标系呢?
2、只有一个点怎么确定一条线呀?

---------------------------------------------------------------


// 获取光标位置的模型坐标。 2002.11.18.
CVector3 WINAPI GetMouseModelCoordinate(CVRRoomView* pView, CPoint point)
{
GLfloat fdepth;
GLdouble ObjectX, ObjectY, ObjectZ;
GLint iViewPort[4];
GLdouble dProjMatrix[16];
GLdouble dModelMatrix[16];
POINT iScreen;
int iScrToWinX, iScrToWinY;
long iError;
CVector3 pp;

CClientDC ClientDC(pView);
wglMakeCurrent(ClientDC.m_hDC, pView->m_hGLContext); //使 RC 与当前 DC 相关联
glGetIntegerv(GL_VIEWPORT, iViewPort);
glPushMatrix();
glGetDoublev(GL_MODELVIEW_MATRIX, dModelMatrix);
glGetDoublev(GL_PROJECTION_MATRIX, dProjMatrix);
::GetCursorPos(&iScreen);
iScrToWinX = iScreen.x-point.x;
iScrToWinY = iScreen.y-point.y;
glReadPixels(point.x, iViewPort[3]-point.y, 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &fdepth);
gluUnProject((GLdouble)point.x, (GLdouble)(iViewPort[3]-point.y), (GLdouble)fdepth, dModelMatrix, dProjMatrix, iViewPort, &ObjectX, &ObjectY, &ObjectZ);
if(ObjectX>=pView->m_pDoc->m_dModelMinX&&ObjectX<=pView->m_pDoc->m_dModelMaxX&&
ObjectY>=pView->m_pDoc->m_dModelMinY&&ObjectY<=pView->m_pDoc->m_dModelMaxY&&
ObjectZ>=pView->m_pDoc->m_dModelMinZ&&ObjectZ<=pView->m_pDoc->m_dModelMaxZ)
{
pp.x = ObjectX;
pp.y = ObjectY;
pp.z = ObjectZ;
}
else
{
pp.x = pView->m_pDoc->m_pRoamParameter->dMouseModelX;
pp.y = pView->m_pDoc->m_pRoamParameter->dMouseModelY;
pp.z = pView->m_pDoc->m_pRoamParameter->dMouseModelZ;
}
// pView->m_pDoc->m_pRoamParameter->dMouseModelX = (double)ObjectX;
// pView->m_pDoc->m_pRoamParameter->dMouseModelX = (double)ObjectY;
// pView->m_pDoc->m_pRoamParameter->dMouseModelX = (double)ObjectZ;
glPopMatrix();
iError = glGetError();
if(iError!=GL_NO_ERROR)
{
// Errinfo = gluErrorString(iResultCode);
::MessageBox(NULL, (LPCTSTR)gluErrorString(iError), "提示13:", MB_OK);
}
wglMakeCurrent(ClientDC.m_hDC, NULL);//释放 RC,以便其它 DC 进行绘图
return pp;
}
邀请回答 我来回答

全部回答

(2)
默认 最新
wusheng999000
::GetCursorPos(&iScreen);
iScrToWinX = iScreen.x-point.x;
iScrToWinY = iScreen.y-point.y;
这三句怎么没有见到你在程序中用上呀:
if(ObjectX>=pView->m_pDoc->m_dModelMinX&&ObjectX<=pView->m_pDoc->m_dModelMaxX&&
ObjectY>=pView->m_pDoc->m_dModelMinY&&ObjectY<=pView->m_pDoc->m_dModelMaxY&&
ObjectZ>=pView->m_pDoc->m_dModelMinZ&&ObjectZ<=pView->m_pDoc->m_dModelMaxZ)
{
pp.x = ObjectX;
pp.y = ObjectY;
pp.z = ObjectZ;
}
else
{
pp.x = pView->m_pDoc->m_pRoamParameter->dMouseModelX;
pp.y = pView->m_pDoc->m_pRoamParameter->dMouseModelY;
pp.z = pView->m_pDoc->m_pRoamParameter->dMouseModelZ;
}
这个ifelse语句说明意思?
2009年8月3日
评论 点赞
wusheng999000
我也在做opengl用射线法拾取项目,我用gluUnProject进行屏幕坐标到模型坐标转换总是不准确,我的代码如下
我用vc++建立单文档应用程序GLTable,在视口CGLTableView中加载OpenGL库用于三维图形的绘制,客户区用CSplitterWnd类把客户区分为两栏,左栏用于显示树形导航条右栏用于显示绘图区。在DrawScene中首先设置观察模式用SetViewMode函数,然后绘制网格图元(就是由一些坐标点连线组成)。响应鼠标右键单击消息OnRButtonDown通过gluUnProject完成拾取,单拾取的结果就是不正确,请高手指点,我的QQ号是52135230opengl中拾取部分感兴趣的请和我交流。具体代码如下:
void CGLTableView::SetViewMode()
{
// 观察点
glMatrixMode(GL_PROJECTION);
glLoadIdentity();

//
设置视口变换

glViewport(0,0,m_ClientRect.right,m_ClientRect.bottom);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(m_ClientRect.right<=m_ClientRect.bottom)


glOrtho(-1.0*SceneZoom,SceneZoom,-1.0*SceneZoom*m_ClientRect.bottom/m_ClientRect.right,SceneZoom*m_ClientRect.bottom/m_ClientRect.right,-1.0*SceneDepth,SceneDepth);

else



glOrtho(-1.0*SceneZoom*m_ClientRect.right/m_ClientRect.bottom,SceneZoom*m_ClientRect.right/m_ClientRect.bottom,-1.0*SceneZoom,SceneZoom,-1.0*SceneDepth,SceneDepth);//SceneZoom
为图形缩放比例

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(cos(s_angle),0.0,sin(s_angle),0,0,0,0,1,0);

}
void CGLTableView:
{

CMainFrame *pMainfrm=(CMainFrame*)AfxGetMainWnd();


//
清除颜色缓冲区和深度缓冲区


glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


glLoadIdentity();
//
重置当前的模型观察矩阵


SetViewMode();

if(pMainfrm->m_bShowCoordin)

DrawAxis(1.0);//
绘制坐标系


CGLTableDoc* pDoc = GetDocument();


DrawGrid2D();


glFinish();


SwapBuffers(m_pDC->GetSafeHdc());

}
/************************************************
* 函数说明:响应鼠标右键点击事件,用于模型中网格点的拾取人机交互
*************************************************/
void CGLTableView:
{

// TODO: Add your message handler code here and/or call default



float f_distance;


float f_mindistance=100000;


int biaohao=0;



GLdouble
posX,
posY,
posZ;


GetOGLPos(point.x, point.y, &posX, &posY, &posZ);


//CMainFrame *pMainfrm=(CMainFrame*)AfxGetMainWnd();


CGLTableDoc* pDoc = GetDocument();



f_distance=(pDoc->Index_Point2D.f_x-posX)*(pDoc->Index_Point2D.f_x-posX)


+(pDoc->Index_Point2D.f_y-posY)*(pDoc->Index_Point2D.f_y-posY)


+(0.0f-posZ)*(0.0f-posZ);


if(f_mindistance>f_distance)


{


f_mindistance=f_distance;


biaohao=i;


}


}



CMenu mn1;


mn1.CreatePopupMenu();


CString ss;


CString fmt="%-8s = %-12.4g";

#ifdef __FA_VAS

fmt="%-8s = %-11.3f";

#endif

#ifdef _FA_ENG

ss.Format("%-8s = %-d","NODE",biaohao);


//ss.Format("%-8s = %-d","NODE",pDoc->Index_Point2D[biaohao-1].i_index);

#else

ss.Format("%-8s = %-d","
节点号",biaohao);


//ss.Format("%-8s = %-d","
节点号",pDoc->Index_Point2D[biaohao-1].i_index);

#endif

mn1.AppendMenu(MF_STRING,-1,ss);


ClientToScreen(&point);


//MarkedNode(nodescreen);


mn1.TrackPopupMenu(0,point.x,point.y,this);



mn1.DestroyMenu();


CView:

}
void CGLTableView::GetOGLPos(int x, int y, double * posX, double * posY, double * posZ)
{

GLint viewport[4];


GLdouble
modelview[16];


GLdouble projection[16];


GLfloat winX, winY, winZ;


//glGetFloatv(GL_MODELVIEW_MATRIX,(GLfloat*)modelview);


glPushMatrix();


glGetDoublev( GL_MODELVIEW_MATRIX, modelview );


glGetDoublev( GL_PROJECTION_MATRIX, projection );


glGetIntegerv( GL_VIEWPORT, viewport );



winX = (float)x;


winY = (float)viewport[3] - (float)y;


glReadPixels( x, int(winY), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &winZ );



gluUnProject( winX, winY, winZ, modelview, projection, viewport, posX, posY, posZ);


glPopMatrix();

}

希望能够给出指点,多谢!
2009年8月3日
评论 点赞

没解决?试试专家一对一服务

换一批
    App下载
    技术邻APP
    工程师必备
    • 项目客服
    • 培训客服
    • 平台客服

    TOP