OpenGL任意角度观察物体

iskyshop 2009-11-05 09:12:52
刚刚接触OpenGL不久,用OpenGL构建一个物体,可以无限放大,想通过鼠标拖动变换任意角度来观察物体,这个怎么实现,求实例代码!
...全文
721 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
exceed_me 2011-08-20
  • 打赏
  • 举报
回复
Mark!
gzyyan249 2011-03-27
  • 打赏
  • 举报
回复
各种大牛 我也加你们吧
liuchacha 2009-11-23
  • 打赏
  • 举报
回复
弄懂原理比较重要吧,虚拟轨迹球http://viewport3d.com/trackball.htm
iskyshop 2009-11-23
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 fandh 的回复:]
留个MAIL,我给你发源代码!
[/Quote]
谢谢兄弟,我的Email是:erikchang@163.com
hhwei1985 2009-11-23
  • 打赏
  • 举报
回复
xuexi
wuhuwy 2009-11-23
  • 打赏
  • 举报
回复
帮顶!
fandh 2009-11-23
  • 打赏
  • 举报
回复
留个MAIL,我给你发源代码!
chopinyoung 2009-11-20
  • 打赏
  • 举报
回复
在OnMove函数中 通过Piont前后的差 来计算旋转的角度 以参数的形式传递给OpenGL Funcation

ChopinYoung

QQ:963528468(chopin)

WuHan University
VR_Lab 2009-11-18
  • 打赏
  • 举报
回复
加我QQ,我给你一个程序,你看了就知道怎样做了。726436079
VR_Lab 2009-11-18
  • 打赏
  • 举报
回复
如你所愿:
class CVector3
{
public:

// 缺省构造函数
CVector3() {}

// 用户构造函数
CVector3(float X, float Y, float Z)
{
x = X; y = Y; z = Z;
}

// 定义矢量之间的'+'法
CVector3 operator+(CVector3 vVector)
{
// 返回结果
return CVector3(vVector.x + x, vVector.y + y, vVector.z + z);
}

// 定义矢量之间的'-'法
CVector3 operator-(CVector3 vVector)
{
// 返回矢量相减的结果
return CVector3(x - vVector.x, y - vVector.y, z - vVector.z);
}

// 定义矢量与数的'*'法
CVector3 operator*(float num)
{
// 返回结果
return CVector3(x * num, y * num, z * num);
}

// 定义矢量与数的'/'法
CVector3 operator/(float num)
{
// 返回结果
return CVector3(x / num, y / num, z / num);
}

float x, y, z;
};
forcal 2009-11-11
  • 打赏
  • 举报
回复
fcglFollowMouse函数应加到所绘制的图形的前面,代码更改如下:

gleDrawScene[HFor("Scene")],stop();      //设置场景绘制函数后退出

//让图形随鼠标移动。factor为比例因子,factor越大则移动幅度越大。
fcglFollowMouse(factor:x,y,xx,yy,xxx,yyy,static,fcglFollowMouse,xMouse,yMouse)=
{
if[gleGetMouseMsg(WM_LBUTTONDOWN,&x,&y),fcglFollowMouse=1,xMouse=x,yMouse=y],
gleGetWindowSize[&xxx,&yyy],
if[fcglFollowMouse,gleGetMouseMsg(WM_MOUSEMOVE,&xx,&yy),gleAngle[1,gleAngle(1)+(yy-yMouse)/yyy*factor],gleAngle[2,gleAngle(2)+(xx-xMouse)/xxx*factor]],
if[gleGetMouseMsg(WM_LBUTTONUP,&xx,&yy),fcglFollowMouse=0],
glRotated[gleAngle(1),1,0,0], //使图象沿X轴旋转
glRotated[gleAngle(2),0,1,0], //使图象沿Y轴旋转
glRotated[gleAngle(3),0,0,1] //使图象沿Z轴旋转
};

f(x,y)=sin[sqrt(x*x+y*y)];

initScene()= //定义初始化函数
{
gleAngle(90,180,90) //设置重置视图初始位置
};

Scene()= //场景绘制函数
{
if[gleIsInitScene(),initScene()], //需要初始化场景时,就执行初始化函数
glClear[],
glColor3d[1,0,0], //设置颜色
gleAxesAngle[], //显示坐标和旋转角度
glLoadIdentity[],
glTranslated[0,0,-20],
glColor3d[0,1,0], //设置颜色
fcglFollowMouse[2], //通过鼠标拖动变换任意角度来观察物体
fgPlot3d[HFor("f"),-5,5,-5,5,FG_NOMESH] //绘制二元函数图形
};
forcal 2009-11-11
  • 打赏
  • 举报
回复
通过鼠标拖动变换任意角度来观察物体的完整Forcal代码:

gleDrawScene[HFor("Scene")],stop();      //设置场景绘制函数后退出

//让图形随鼠标移动。factor为比例因子,factor越大则移动幅度越大。
fcglFollowMouse(factor:x,y,xx,yy,xxx,yyy,static,fcglFollowMouse,xMouse,yMouse)=
{
if[gleGetMouseMsg(WM_LBUTTONDOWN,&x,&y),fcglFollowMouse=1,xMouse=x,yMouse=y],
gleGetWindowSize[&xxx,&yyy],
if[fcglFollowMouse,gleGetMouseMsg(WM_MOUSEMOVE,&xx,&yy),gleAngle[1,gleAngle(1)+(yy-yMouse)/yyy*factor],gleAngle[2,gleAngle(2)+(xx-xMouse)/xxx*factor]],
if[gleGetMouseMsg(WM_LBUTTONUP,&xx,&yy),fcglFollowMouse=0],
glRotated[gleAngle(1),1,0,0], //使图象沿X轴旋转
glRotated[gleAngle(2),0,1,0], //使图象沿Y轴旋转
glRotated[gleAngle(3),0,0,1] //使图象沿Z轴旋转
};

f(x,y)=sin[sqrt(x*x+y*y)];

initScene()= //定义初始化函数
{
gleAngle(90,180,90) //设置重置视图初始位置
};

Scene()= //场景绘制函数
{
if[gleIsInitScene(),initScene()], //需要初始化场景时,就执行初始化函数
glClear[],
glColor3d[1,0,0], //设置颜色
gleAxesAngle[], //显示坐标和旋转角度
glLoadIdentity[],
glTranslated[0,0,-20],
glColor3d[0,1,0], //设置颜色
glRotated[gleAngle(1),1,0,0], //使图象沿X轴旋转
glRotated[gleAngle(2),0,1,0], //使图象沿Y轴旋转
glRotated[gleAngle(3),0,0,1], //使图象沿Z轴旋转
fgPlot3d[HFor("f"),-5,5,-5,5,FG_NOMESH],
fcglFollowMouse[2] //通过鼠标拖动变换任意角度来观察物体
};


OpenFC(升级中,目前代码高亮功能有闪烁)下载:http://xoomer.virgilio.it/forcal/xiazai/forcal9/openfc32w.rar

楼主看看是不是你想实现的功能。
iskyshop 2009-11-10
  • 打赏
  • 举报
回复
自己顶起来,等待高手回复!
fandh 2009-11-09
  • 打赏
  • 举报
回复
CVector3里面,肯定有X,Y,Z
iskyshop 2009-11-09
  • 打赏
  • 举报
回复
这个问题重复问了很多,都没有得到一个很好的答案,希望这个帖子能够得到高手的指点,最后我会总结出一个完善的答案贴出来!
iskyshop 2009-11-08
  • 打赏
  • 举报
回复
感谢楼上兄弟提供的资料!尤其感谢二楼的,代码里CVector3是怎么构造的,希望能够给出详细的代码,不甚感谢!
forcal 2009-11-06
  • 打赏
  • 举报
回复
一段Forcal代码,也是用opengl实现的,帮助你理解:

	//让图形随鼠标移动。factor为比例因子,factor越大则移动幅度越大。factor=0进行初始化。
fcglFollowMouse(factor:x,y,xx,yy,xxx,yyy:fcglFollowMouse,xMouse,yMouse)=
{
if[!factor,fcglFollowMouse=0,return(0)],
if[gleGetMouseMsg(WM_LBUTTONDOWN,&x,&y),fcglFollowMouse=1,xMouse=x,yMouse=y],
gleGetWindowSize[&xxx,&yyy],
if[fcglFollowMouse,gleGetMouseMsg(WM_MOUSEMOVE,&xx,&yy),gleAngle[1,gleAngle(1)+(yy-yMouse)/yyy*factor],gleAngle[2,gleAngle(2)+(xx-xMouse)/xxx*factor]],
if[gleGetMouseMsg(WM_LBUTTONUP,&xx,&yy),fcglFollowMouse=0],
glRotated[gleAngle(1),1,0,0], //使图象沿X轴旋转
glRotated[gleAngle(2),0,1,0], //使图象沿Y轴旋转
glRotated[gleAngle(3),0,0,1] //使图象沿Z轴旋转
};


gleAngle(i)说明:获得由键盘操纵的旋转角度

在OpenFcGl32.dll中设置了三个可由键盘操纵的数,这三个数可由函数gleAngle[i]获得,使用这三个数并与函数glRotated[...]配合可使图象产生旋转。

Shift + →:使gleAngle[1]值增加;
Shift + ←:使gleAngle[1]值减少;
Shift + ↑:使gleAngle[2]值增加;
Shift + ↓:使gleAngle[2]值减少;
Shift + PageUp: 使gleAngle[3]值减少;
Shift + PageDown:使gleAngle[3]值增加;
Shift + Home:使gleAngle[i]值为0。

在每一个绘图单元前加上以下代码,可用键盘操纵图象沿X、Y、Z轴旋转:
glRotated[gleAngle(1),1,0,0]; //使图象沿X轴旋转。
glRotated[gleAngle(2),0,1,0]; //使图象沿Y轴旋转。
glRotated[gleAngle(3),0,0,1]; //使图象沿Z轴旋转。

在以上代码中是获得鼠标位置使gleAngle(i)改变。gleAngle(i,x)将gleAngle(i)设置为x。

仅作参考。
wuhuwy 2009-11-06
  • 打赏
  • 举报
回复
帮顶,楼主应该多早一些源代码来看看
fandh 2009-11-06
  • 打赏
  • 举报
回复
一般是有限放大与缩小!在一定的范围内放大缩小(也就是比例的问题)。
任意角度来观察物体,就是旋转了,通过鼠标不停的旋转来改变视点!
这些,用opengl都能实现,建议楼主看点opengl方面的书籍与例子吧!不难的!
VR_Lab 2009-11-05
  • 打赏
  • 举报
回复
给你个代码:
void CalculateFrameRate()
{
static float framesPerSecond = 0.0f; // 保存帧率
static float lastTime = 0.0f; // 最好帧显示的时刻
static char strFrameRate[50] = {0}; // 窗口标题字符串

static float frameTime = 0.0f;

// 获得当前系统时间
float currentTime = timeGetTime() * 0.001f;

// 获得时间间隔
g_FrameInterval = currentTime - frameTime;
frameTime = currentTime;

// 帧计数器递增
++framesPerSecond;

// 时间是否超过1秒
if( currentTime - lastTime > 1.0f )
{
// 设置当前时间
lastTime = currentTime;

// 打印标题
sprintf(strFrameRate, "地形模拟 当前帧率:每秒 %d 帧", int(framesPerSecond));

// 设置窗口标题
SetWindowText(g_hWnd, strFrameRate);

// 帧计数器复位
framesPerSecond = 0;
}
}


// 下面的函数的功能是计算个矢量的叉积,即求与两个矢量都垂直的矢量
CVector3 Cross(CVector3 vVector1, CVector3 vVector2)
{
CVector3 vNormal;

// 计算垂直矢量
vNormal.x = ((vVector1.y * vVector2.z) - (vVector1.z * vVector2.y));
vNormal.y = ((vVector1.z * vVector2.x) - (vVector1.x * vVector2.z));
vNormal.z = ((vVector1.x * vVector2.y) - (vVector1.y * vVector2.x));

// 返回结果
return vNormal;
}


// 下面的函数的功能是求矢量的长度
float Magnitude(CVector3 vNormal)
{
return (float)sqrt( (vNormal.x * vNormal.x) +
(vNormal.y * vNormal.y) +
(vNormal.z * vNormal.z) );
}


// 下面的函数的功能是将矢量单位化
CVector3 Normalize(CVector3 vVector)
{
// 获得矢量的长度
float magnitude = Magnitude(vVector);

vVector = vVector / magnitude;

return vVector;
}


// 下面的函数是类CCamera的构造函数
CCamera::CCamera()
{
CVector3 vZero = CVector3(0.0, 0.0, 0.0); // 初始化摄像机位置
CVector3 vView = CVector3(0.0, 1.0, 0.5); // 初始化摄像机方向
CVector3 vUp = CVector3(1.0, 0.0, 0.0); // 初始化摄像机的向上方向

m_vPosition = vZero;
m_vView = vView;
m_vUpVector = vUp;
}


// 设置摄像机的位置、方向
void CCamera::PositionCamera(float positionX, float positionY, float positionZ,
float viewX, float viewY, float viewZ,
float upVectorX, float upVectorY, float upVectorZ)
{
CVector3 vPosition = CVector3(positionX, positionY, positionZ);
CVector3 vView = CVector3(viewX, viewY, viewZ);
CVector3 vUpVector = CVector3(upVectorX, upVectorY, upVectorZ);

m_vPosition = vPosition;
m_vView = vView;
m_vUpVector = vUpVector;
}


// 下面的函数的功能是通过鼠标设置视点
void CCamera::SetViewByMouse()
{
POINT mousePos;
int middleX = SCREEN_WIDTH >> 1;
int middleY = SCREEN_HEIGHT >> 1;
float angleY = 0.0f;
float angleZ = 0.0f;
static float currentRotX = 0.0f;

// 获得鼠标的当前位置
GetCursorPos(&mousePos);

// 如果鼠标位于窗口的正中央,则返回
if( (mousePos.x == middleX) && (mousePos.y == middleY) ) return;

// 设置鼠标的位置为窗口正中央
SetCursorPos(middleX, middleY);

// 计算角度
angleY = (float)( (middleX - mousePos.x) ) / 500.0f;
angleZ = (float)( (middleY - mousePos.y) ) / 500.0f;

currentRotX -= angleZ;

if(currentRotX > 1.0f)
currentRotX = 1.0f;
else if(currentRotX < -1.0f)
currentRotX = -1.0f;
// 旋转观察方向
else
{
CVector3 vAxis = Cross(m_vView - m_vPosition, m_vUpVector);
vAxis = Normalize(vAxis);

RotateView(angleZ, vAxis.x, vAxis.y, vAxis.z);
RotateView(angleY, 0, 1, 0);
}
}


// 下面的函数的功能是将摄像机的观察方向绕某个方向轴旋转一定的角度
void CCamera::RotateView(float angle, float x, float y, float z)
{
CVector3 vNewView;

// 获得观察方向矢量
CVector3 vView = m_vView - m_vPosition;

// 计算角度的cos和sin值
float cosTheta = (float)cos(angle);
float sinTheta = (float)sin(angle);

// 计算新的观察点坐标X
vNewView.x = (cosTheta + (1 - cosTheta) * x * x) * vView.x;
vNewView.x += ((1 - cosTheta) * x * y - z * sinTheta) * vView.y;
vNewView.x += ((1 - cosTheta) * x * z + y * sinTheta) * vView.z;

// 计算新的观察点坐标Y
vNewView.y = ((1 - cosTheta) * x * y + z * sinTheta) * vView.x;
vNewView.y += (cosTheta + (1 - cosTheta) * y * y) * vView.y;
vNewView.y += ((1 - cosTheta) * y * z - x * sinTheta) * vView.z;

// 计算新的观察点坐标Z
vNewView.z = ((1 - cosTheta) * x * z - y * sinTheta) * vView.x;
vNewView.z += ((1 - cosTheta) * y * z + x * sinTheta) * vView.y;
vNewView.z += (cosTheta + (1 - cosTheta) * z * z) * vView.z;
m_vView = m_vPosition + vNewView;
}

// 下面的函数的功能是向左向右移动摄像机
void CCamera::StrafeCamera(float speed)
{
// Add the strafe vector to our position
m_vPosition.x += m_vStrafe.x * speed;
m_vPosition.z += m_vStrafe.z * speed;

// Add the strafe vector to our view
m_vView.x += m_vStrafe.x * speed;
m_vView.z += m_vStrafe.z * speed;
}

// 下面的函数的功能是根据一定的速度前后移动摄像机
void CCamera::MoveCamera(float speed)
{
// 获得当前摄像机方向
CVector3 vVector = m_vView - m_vPosition;
vVector = Normalize(vVector);

m_vPosition.x += vVector.x * speed; // 移动摄像机的位置坐标X
m_vPosition.y += vVector.y * speed; // 移动摄像机的位置坐标Y
m_vPosition.z += vVector.z * speed; // 移动摄像机的位置坐标Z
m_vView.x += vVector.x * speed; // 摄像机X方向移动
m_vView.y += vVector.y * speed; // 摄像机Y方向移动
m_vView.z += vVector.z * speed; // 摄像机Z方向移动
}


// 下面的函数的功能是根据不同的按键,移动摄像机
void CCamera::CheckForMovement()
{
// 获得当前帧率
float speed = kSpeed * g_FrameInterval;

// 是否按下UP箭头键或'W'键
if(GetKeyState(VK_UP) & 0x80 || GetKeyState('W') & 0x80) {

// 移动摄像机
MoveCamera(speed);
}

// 是否按下DOWN键或'S'键
if(GetKeyState(VK_DOWN) & 0x80 || GetKeyState('S') & 0x80) {

// 移动摄像机
MoveCamera(-speed);
}

// 是否按下LEFT箭头键或'A'键
if(GetKeyState(VK_LEFT) & 0x80 || GetKeyState('A') & 0x80) {

// 移动摄像机
StrafeCamera(-speed);
}

// 是否按下RIGHT箭头键或'D'键
if(GetKeyState(VK_RIGHT) & 0x80 || GetKeyState('D') & 0x80) {

// 移动摄像机
StrafeCamera(speed);

}
if (GetKeyState(VK_SPACE)&0x80)
{
UpAndDown(speed);
}
}


// 下面的函数的功能是更新摄像机方向
void CCamera::Update()
{
// 初始化变量
CVector3 vCross = Cross(m_vView - m_vPosition, m_vUpVector);

// 规范化矢量
m_vStrafe = Normalize(vCross);

// 移动摄像机方向
SetViewByMouse();

// 判断是否有按键
CheckForMovement();

// 计算帧率
CalculateFrameRate();
}


// 下面的函数的功能是设置投影变换
void CCamera::Look()
{
// 根据摄像机的位置、方向和上下方向设置投影变换
gluLookAt(m_vPosition.x, m_vPosition.y, m_vPosition.z,
m_vView.x, m_vView.y, m_vView.z,
m_vUpVector.x, m_vUpVector.y, m_vUpVector.z);
}

void CCamera::UpAndDown(float speed)
{
m_vPosition.x += m_vStrafe.x * speed;
m_vPosition.z += m_vStrafe.z * speed;

// Add the strafe vector to our view
m_vView.x += m_vStrafe.x * speed;
m_vView.z += m_vStrafe.z * speed;
/*
m_vPosition.y+=speed*m_vStrafe.y;
m_vView.y +=speed*m_vStrafe.y;*/


}
加载更多回复(1)

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧