社区
游戏开发
帖子详情
opengl: 如何实现三维点的跟随mouse 移动?
kingwang
2000-09-03 10:40:00
假设使用的投影函数是:
glFrustum();
3x
...全文
363
2
打赏
收藏
opengl: 如何实现三维点的跟随mouse 移动?
假设使用的投影函数是: glFrustum(); 3x
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
2 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
gauss
2000-09-13
打赏
举报
回复
用glu库中的glProject和glUnproject或者可以,关于这个函数的详细用法就不说了。
不管你用的是什么投影方式,OpenGL都帮你处理了。
假设你在用MFC,
以下是我的一个MDI曲面编辑程序中的片断,
功能是按下左键从一堆点中找到一个点
拖动鼠标的同时被选中点跟着移动(如果刚才你有选中的话),
注意这种移动只是有限制的,
在例子中是沿着z方向移动,
释放左键就做点结束的事情
已经把一些无关的内容略作删除
写得不好,有点笨,希望对你有用吧。
void CBSView::BeginGL()
{
wglMakeCurrent(m_pDC->GetSafeHdc(),m_hRC);
}
void CBSView::EndGL()
{
wglMakeCurrent(NULL,NULL);
}
//置模视和投影矩阵
void CBSView::PrepareModelAndProjection()
{
CRect ClientRect;
GetClientRect(ClientRect);
glViewport(0,0,ClientRect.Width(),ClientRect.Height());
GLdouble gldAspect = (GLdouble) ClientRect.Width()/ (GLdouble) ClientRect.Height();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
gluLookAt(EyeX,EyeY,EyeZ,CenterX,CenterY,CenterZ,UpVectorX,UpVectorY,UpVectorZ);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPerspective(30.0, gldAspect, 1.0, 10.0);
}
void CBSView::FinishModelAndProjection()
{
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
//找到那个点
void CBSView::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
bLeftDown=TRUE;
SetCapture();
CBSDoc* pDoc=(CBSDoc*)GetDocument();
double Project[16];
double ModelView[16];
int ViewPort[4];
BeginGL();
PrepareModelAndProjection();
glGetDoublev(GL_PROJECTION_MATRIX,Project);
glGetDoublev(GL_MODELVIEW_MATRIX,ModelView);
glGetIntegerv(GL_VIEWPORT,ViewPort);
//Window坐标
double WinX;
double WinY;
double WinZ;
//WinZ的意义比较复杂,尤其是在透视方式的时候,我也不大清楚,看着办吧。
for(int i=0;i<=pDoc->N;i++){
for(int j=0;j<=pDoc->M;j++){
//逐点得到Window坐标再比较
if ( gluProject( pDoc->Points[i][j][0], pDoc->Points[i][j][1], pDoc->Points[i][j][2],
ModelView, Project, ViewPort,
&WinX , &WinY , &WinZ ) != GL_TRUE ){
TRACE("\n Point3dTo2d call gluProject failed ! " );
}
CRect ClientRect;
GetClientRect(ClientRect);
WinY=ClientRect.Height()-WinY;
if(abs(WinX-point.x)<=10 && abs(WinY-point.y)<=5){
//HitI和HitJ是找到点的索引
HitI=i;
HitJ=j;
bSelected=TRUE;
pDoc->bListBuilded=FALSE;
break;
}
}
}
FinishModelAndProjection();
EndGL();
CMDIGLPspView::OnLButtonDown(nFlags, point);
}
//一些无聊的事情
void CBSView::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CBSDoc* pDoc=(CBSDoc*)GetDocument();
ReleaseCapture();
bLeftDown=FALSE;
if(bSelected==TRUE){
bSelected=FALSE;
Invalidate(FALSE);
}
CMDIGLPspView::OnLButtonUp(nFlags, point);
}
void CBSView::OnMouseMove(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CBSDoc* pDoc=(CBSDoc*)GetDocument();
if(bSelected==TRUE && bLeftDown){
BeginGL();
PrepareModelAndProjection();
double Project[16];
double ModelView[16];
int ViewPort[4];
glGetDoublev(GL_PROJECTION_MATRIX,Project);
glGetDoublev(GL_MODELVIEW_MATRIX,ModelView);
glGetIntegerv(GL_VIEWPORT,ViewPort);
double WinX;
double WinY;
double WinZ;
//只想得到WinZ
if ( gluProject( pDoc->Points[HitI][HitJ][0], pDoc->Points[HitI][HitJ][1], pDoc->Points[HitI][HitJ][2],
ModelView, Project, ViewPort,
&WinX , &WinY , &WinZ ) != GL_TRUE ){
TRACE("\n call gluProject failed ! " );
}
CRect ClientRect;
GetClientRect(ClientRect);
//NewX和NewY是新的Window位置的值
double NewX=double(point.x);
double NewY=double(ClientRect.Height()-point.y);
double RealX;
double RealY;
double RealZ;
//得到新的实际坐标
if(gluUnProject(NewX,NewY,WinZ,ModelView,Project,ViewPort,&RealX,&RealY,&RealZ)!=GL_TRUE){
TRACE("\n call gluProject failed ! " );
};
//修改后重画就是了
pDoc->Points[HitI][HitJ][1]=RealY;
Invalidate(FALSE);
FinishModelAndProjection();
EndGL();
}
CMDIGLPspView::OnMouseMove(nFlags, point);
}
topdeveloper
2000-09-11
打赏
举报
回复
使用枚举变量定义方向,通过鼠标位置移动的变化值返回方向枚举值,用case语句做模型方向或摄像机视点的变化。
opengl
的太阳系模型
// 初始化
OpenGL
void InitGL(void) { glClearColor(0.0f, 0.0f, 0.0f, 0.5f); //设置黑色背景 glClearDepth(2.0f); // 设置深度缓存 glEnable(GL_DEPTH_TEST); //启动深度测试 glDepthFunc(GL_LEQUAL); //深度...
OpenGL
实现
在
三维
空间拖拽物体
最近本来想用
opengl
实现
一个3维形变平台,但是没想到在鼠标交互这里就遇到了麻烦。
opengl
中并没有很实用的能够处理鼠标拖拽3D物体的办法,而我又不想导入外部的交互框架把程序搞得很冗杂。害,那咋办嘛,只好自己从...
OpenGL
-自主高性能
三维
GIS平台架构与
实现
-第二季
OpenGL
-自主高性能
三维
GIS平台架构与
实现
/第二季:
实现
三维
GIS球体+ 高程数据章节名称DEM基础1DEM基础知识1.介绍基本的DEM知识2.什么是DEM,作用是什么2DEM数据1.如何获取/ 传统测量/激光扫描/无人机测量/
点
云数据/ 倾斜摄影2.如何使用/局部小规模(栅格数据,图片/tif),3. 组织方式4. 根据使用目的不同,介绍多种优化方法3DEM图层的
实现
原理14DEM数据结构定义struct V3U3N4顶
点
数据的生成和计算WGS84投影计算5wgs84 投影球体被切成一个个小圆弧,一共60个投影带,分别为01,02.........60WGS的最新版本为WGS 84(也称作WGS 1984、EPSG:4326),1984年定义、最后修订于2004年。接口定义坐标转换Wgs84 数据加载6瓦片编号计算生成算法1. 经纬度到大地坐标的转换2.大地坐标到经纬度坐标转换3. 根据经纬度获取瓦片编号框架重构7智能指针重构框架1. 基类定义(所有的类继承自基类),基类派生自 std::enbale_shared_from_this2.
实现
智能指针的动态转换接口3.
实现
向下转换4. 已有的类
实现
全部使用智能指针重构5. 任务系统(多线程加载任务)8引入图层(Layer)1. 介绍图层的概念以及重要性2. 图层类
实现
3. 修改框架(使用图层的方式重构框架)9Layer-bug排查(绘制过程中出现错位,偶发)1. 框架重构后遇到问题(绘制结果错误)2. 瓦片索引方式发生变化,多线程中引起内存问题3. 修改索引方式,解决绘制偶发错误问题10引入数据源(TileSource)1. 数据源的作用与设计目的2. 当前存在的问题,数据调度中存在问题3. 数据源(TileSource)类
实现
11数据格式管理(FormatMgr)1. 数据格式管理(FormatMgr) 提出的目的,需要解决的问题2. CELLFormat基类接口抽象3.
实现
几个标准格式类4. 修改框架流程,使用FormatMgr重构流程5. 扩展支持,后续支持任务格式数据加入系统12Task(任务)优化1. 任务中低耦合数据结构,目的是让Task更加的通用2. 修改任务读取代码与任务处理代码,完善处理流程DEM高程13DEM-数字高程定义1. 什么是数字化高程数据2. 当下GIS系统中有哪些常见的高程格式3. 课程体体系中使用的哪种格式4. 高程类定义以及
实现
,并加入到FormatMgr 管理系统中14高程瓦片数据读取1. 介绍GIS系统相关的工具(在数据转换)数据生成方面可以解决大量时间2. 自定义高程瓦片格式说明3. 自定义高程格式文件解析,并以智能对象的方式引入到系统中4. 完善框架代码,适配高程数据15高程瓦片文件的读取1.
实现
基本的读取算法2. 增加格式化组件,并加入到系统中3. 配置高程图层以及高程数据源,并加载数据,验证数据正确性16瓦片数据结构重构1.顶
点
生成2.UV坐标计算3.面数据生成17DEM重构绘制流程1. 修改绘制数据结构,去除无用字段2. 增加Mesh类,
实现
光栅数据转换成三角面数据,计算UV数据,提炼接口3. 修改系统调度,
实现
顶
点
数据,UV数据,以及面数据的生成与更新4. 按需更新数据,而不是每一帧更新18DEM-数据精度问题(CPU)1. 因为瓦片数据使用大地坐标作为系统输入,造成瓦片坐标很大,单浮
点
数据精度不够2. 使用局部坐标的方式解决单浮
点
精度问题3. 调整相机参数,解决投影矩阵数据计算深度精度问题4. 修改绘制shader
实现
对瓦片数据的绘制19DEM-数据精度问题(LogDepth)1. 使用对数深度(log depth )算法在GPU中 计算解决单浮
点
经纬计算问题2. 修改shader ,增加对(logDepth)算法支持3. 修改C++端代码,
实现
对shader数据的输入20DEM-数据结构优化1.当下使用CPU端数据通过接口的方式传递给GPU,速度慢2. 使用Instance 方式降低Vertex Buffer 的大小,优化渲染系统21DEM-GPU缓冲区优化1. 使用Vertex Buffer Object / Index Buffer Object / Instance 方式优化渲染系统2. 修改绘制接口,使用DrawElementsInstanceBaseInstance方式提升系统性能内存池与对象池22瓦片生成优化/对象池1. 相机
移动
过程中会频繁的建立与释放瓦片,对CPU有较大的消耗2. 引入内存池,避免频繁的内存申请与释放,降低CPU时间3. 改造智能指针对象,对象释放通知到内存管理,回收对象内存23改造任务系统支持对象池1. 任务系统是一个公用模块,被多个模块使用,避免频繁的内存操作,引起的内存碎片2.
实现
对象池,并应用到任务模块法线计算24法线计算1. 修改现有顶
点
结构,增加法线支持2. 修改shader,增加法线顶
点
输入,使用平行光光照模型3. 修改绘制流程,支持光照计算,使用探照灯作为光源输入25顶
点
法线计算/共享法线计算1. 增加数据结构保存顶
点
数据被多个面共享的次数2. 计算面法线,并累加到顶
点
法线中3. 根据顶
点
被面共享的次数做平均法线计算4. 修改流程,按需更新法线数据26法线数据压缩1. 法线数据使用3 * float 数据存储,大大的增加了系统的数据2.
实现
算法,将3 * float 数据压缩成4字节数据3. 改造绘制代码,支持压缩数据输入27GPU中计算产生法线数据(去掉CPU中计算)1. 引擎支持 Geometry Shader 阶段2. 编写 Geometry Shader,
实现
法线计算系统功能优化28重构CPU拾取流程1. 当下的拾取流程,只支撑二维数据拾取,无法准群的拾取
三维
数据2. Terrain中增加拾取接口,输入射线,输出拾取到顶
点
数据29绘制拾取结果1. 增加一个绘制
点
的方法,
实现
绘制代码2. 修改shader,增加logdepth3. 调试代码,花费了很多时间排查错误,最总排查到是因为uniform参数笔误写错造成。30任务系统完善,避免任务队列无线膨胀1. 任务系统中,没有限制队列的大小,生产者的能力远大于消费者的能力,造成任务队列膨胀2. 处理办法,限制生产者的生产能力,而不是限制任务队列大小(这种方式会造成业务逻辑异常复杂)3. 使用sleep休眠方式(这种方式是严重错误的)31如何避免瓦片数据抖动1. 产生瓦片抖动的原因 ? 分裂算法与回退算法中间没有过度2. 引入过度流程,避免内存抖动,参数因子是一个重要的数据,需要谨慎使用3. 有必要结合瓦片自身数据动态计算参数因子32瓦片数据管理-fepk文件格式支持-全球数据加载1. 支持fepk文件格式,增加fepk读取组件,适配fepk文件2. fepk管理数据方式:一般情况选择全球前10级别作为基础级别,因数据量不大(1G)左右,后续以8级作为基础级别,全球19级别数据被划分为 2^8 * 2^7(512 * 256)个块。每个块中包含了256 * 256 张小瓦片33fepk高程数据读取 34高程分裂处理当瓦片没有高程数据,那么子节
点
以及其他后代节
点
该如何共享父节
点
的数据35lesson-734-高程瓦片分裂处理(2)-算法
实现
高程数据分裂算法
实现
实现
对高程数据的切分,并对特殊数据进行处理36高程瓦片分裂处理(3)-问题排查 37高程瓦片分裂处理(4)-(后代节
点
更新问题)当一个瓦片高程数据更新后,他的儿子节
点
,孙子节
点
...该如何处理?38瓦片视锥裁剪错误高程数据更新后,没有技术计算瓦片包围盒信息,造成包围盒错误,进而引视锥计算错误39http支持1.引入三方库 Libcurl2.http类封装,支持http读取数据40fepk.server使用 生成
三维
地球41改造四叉树-统一使用经纬度输入42地形网络生成算法重构 43引入球体坐标系 44使用球体坐标改造瓦片 45多图层(加载标签数据) 课时截图:镜头拉近后,显示细节数据加载矢量SHP国界线数据:加载矢量
三维
白膜数据截图高程数据加载
点
云数据 加载倾斜摄影数据
OpenGL
基础16:视角
三种欧拉角: 俯仰角(Pitch):沿x轴旋转的角,从上往下看的角 偏航角(Yaw):沿y轴旋转的角,从左往右看的角 滚转角(Roll):沿z轴旋转的角(对于摄像机而言,一般不关心这个) 关于坐标轴: 自身坐标系:物体...
OpenGL
入门(三):图形随鼠标转动
函数功能:创建一个透视投影的矩阵,并且用这个矩阵乘以当前矩阵,这个函数的参数只定义近裁剪平面的左下角
点
和右上角
点
的
三维
空间坐标,即(left,bottom,-near)和(right,top,-near);最后一个参数far是远裁剪...
游戏开发
8,304
社区成员
23,682
社区内容
发帖
与我相关
我的任务
游戏开发
游戏开发相关内容讨论专区
复制链接
扫一扫
分享
社区描述
游戏开发相关内容讨论专区
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章