游戏开发论坛

 找回密码
 立即注册
搜索
查看: 1217|回复: 0

虚拟场景漫游碰撞检测时如何选择视点

[复制链接]

4

主题

16

帖子

16

积分

新手上路

Rank: 1

积分
16
发表于 2006-9-7 14:49:00 | 显示全部楼层 |阅读模式
     自己的毕业研究课题的一部分,在一个由很多粒子构成的粒子系统大场景中进行漫游。漫游时采用平移、旋转来实现漫游效果,按下“左右方向键”时绕Y轴旋转,按下“Page Up && Page Down”时绕X轴旋转,按下“上下方向键”时延Z轴前后移动,整体实现思路和NeHe指导书中的一个例子相似。
    为了增强真实感,我加入了碰撞检测,目的是使视点移动时如果碰到粒子,就不再移动。实现时采用八叉树划分空间,根据视点坐标(X,Y,Z)的取值寻找对应的空间,然后和该空间中的粒子作碰撞检测。这些代码已经设计成功。我专门设计了一些测试数据,算法和程序没有问题。
    关键的地方是选择什么样的坐标(X,Y,Z)来进行碰撞检测,因为漫游时操作有旋转和平移。旋转时相当于视点(人的头部)转动,但是位置不变,不需要碰撞检测。平移时相当于视点(人的头部)前后移动,需要进行碰撞检测。我就把程序中移动时的目的坐标代入八叉树代码中进行碰撞检测,但是实现后的效果很不好,有时进入物体内部也没出现进入提示,没有进入物体内部反而出现了进入提示。
    关键代码如下:
//漫游所用变量
GLfloat xtrans = -x_pos;
GLfloat ztrans = -z_pos;
GLfloat ytrans = -walkbias-0.25f;
GLfloat sceneroty = 360.0f - y_rot;
......
if (freeroar) //自由漫游
{
glRotatef(lookupdown,1.0f,0,0);//X轴,PageUp、PageDown控制
glRotatef(sceneroty,0,1.0f,0);//Y轴,左、右键控制
glTranslatef(xtrans, ytrans, ztrans);//视点平移,上、下键控制
......
        if (nChar==VK_UP)
        {        
                //用临时变量保存将要移动到的位置
                tx_pos =x_pos-(float)sin(heading*piover180) * 0.5f;
                tz_pos =z_pos-(float)cos(heading*piover180) * 0.5f;
                if (walkbiasangle >= 359.0f)
                {
                        twalkbiasangle = 0.0f;
                }
                else
                {
                        twalkbiasangle=walkbiasangle+10;
                }
                twalkbias = (float)sin(twalkbiasangle *

piover180)/2.0f;
               
                if (!OctreeCheck(-tx_pos,-twalkbias-0.25f,-tz_pos))
                //如果移动的位置不在粒子内部,则移动到该位置
                //if (!OctreeCheck(0.0,0.0,0.0))
                {
                        x_pos =tx_pos;
                        z_pos =tz_pos;
                        walkbiasangle = twalkbiasangle;
                        walkbias = twalkbias;
                }
                else
                {
                        MessageBox("发生碰撞");
                }
               
        }

        if (nChar==VK_DOWN)
        {
                //用临时变量保存将要移动到的位置
                tx_pos =x_pos+(float)sin(heading*piover180) * 0.5f;
                tz_pos =z_pos+(float)cos(heading*piover180) * 0.5f;
                if (walkbiasangle >= 359.0f)
                {
                        twalkbiasangle = 0.0f;
                }
                else
                {
                        twalkbiasangle=walkbiasangle-10;
                }
                twalkbias = (float)sin(twalkbiasangle *

piover180)/2.0f;
               
                if (!OctreeCheck(-tx_pos,-twalkbias-0.25f,-tz_pos))
                //if (!OctreeCheck(0.0,0.0,0.0))
                //如果移动的位置不在粒子内部,则移动到该位置
                {
                        x_pos =tx_pos;
                        z_pos =tz_pos;
                        walkbiasangle = twalkbiasangle;
                        walkbias = twalkbias;
                }
                else
                {
                        MessageBox("发生碰撞");
                }
        }
    请高手给予指点,不胜感激!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-25 07:21

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表