分享
 
 
 

自己研究的一个场景物体剔除方法

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

场景剔除方法

首先将场景划分成N*M个等大的矩形区域,推荐正方形,每个区域有一个链表保存这个区域上的所有物体,然后用一个N*M的二维数组保存这些指针。进行视锥剔除的时候,首先根据摄象机的参数得到一个近似的三角形(三角形指的是可视区域在XZ平面上的投影区域),算出三角形三个顶点的坐标,然后利用三个顶点坐标可以算出在这个三角形内的,刚才划分的区域,然后将这些区域的链表拼接就得到了所有可见物体。

基于这个方法,区域之间有物体跨越的话,可以很方便的对这两个区域链表处理,保证剔除不出错。

原理简单,下面是代码实现

bool IsInTriangle2D(D3DXVECTOR2 p1,D3DXVECTOR2 p2,D3DXVECTOR2 p3,D3DXVECTOR2 p,float Precision)//判断点p是否在点p1,p2,p3的三角形内,Precision是允许的误差范围,值越大,表示允许超出三角形的距离越大

{

double a=p2.x-p1.x,b=p3.x-p1.x,c=p2.y-p1.y,d=p3.y-p1.y;

double u=(a*(p.y-p1.y)/c+p1.x-p.x)/(a*d/c-b);

double v=(b*(p.y-p1.y)/d+p1.x-p.x)/(b*c/d-a);

if(u=-Precision&&v=-Precision&&u+v

else

return false;

}

void CCuller::ViewCull()

{

if(!m_isCull)return;//是否打开剔除

PObjectList* pNode=m_pCulledObject;//保存剔除后的物体

if(pNode!=NULL)//每次剔除的时候先删除上次剔除保留的链表

{

while(pNode-m_pNext!=NULL)

{

pNode=pNode-m_pNext;

delete m_pCulledObject;

m_pCulledObject=pNode;

}

delete m_pCulledObject;

m_pCulledObject=NULL;

}

float Distance=m_pCamera-GetDistance();//获得摄象机的观察距离,求近似三角形

float Angle=m_pCamera-GetAngleH()-90;//这个不用管,只是我自己游戏中的一个角度转换问题

static D3DXVECTOR2 p1,p2,p3;

int StartX,StartZ,EndX,EndZ;

//根据摄象机算出可视范围近似三角形的三个顶点

p1.x=m_pCamera-GetPosition().x/CULL_RECT_WIDTH;//除以区域长宽的目的是将一个区域作为一个点来看

p1.y=m_pCamera-GetPosition().z/CULL_RECT_LONG;//可以理解我们划分的区域为一个像素,

p2.x=cos(AtoR(Angle+22.5))*Distance/CULL_RECT_WIDTH+p1.x;//观察范围的三角形也就是以这些像素表示的三角形了

p2.y=sin(AtoR(Angle+22.5))*Distance/CULL_RECT_LONG+p1.y;//这个不理解也不要紧,这些不是关键

p3.x=cos(AtoR(Angle-22.5))*Distance/CULL_RECT_WIDTH+p1.x;

p3.y=sin(AtoR(Angle-22.5))*Distance/CULL_RECT_LONG+p1.y;

//根据p1,p2,p3算出区域数组下标的范围

if(p1.x

{

StartX=p1.x;

EndX=p2.x;

if(StartXp3.x)

{

StartX=p3.x;

}

else

{

if(EndX

{

EndX=p3.x;

}

}

}

else

{

StartX=p2.x;

EndX=p1.x;

if(StartXp3.x)

{

StartX=p3.x;

}

else

{

if(EndX

{

EndX=p3.x;

}

}

}

if(p1.y

{

StartZ=p1.y;

EndZ=p2.y;

if(StartZp3.y)

{

StartZ=p3.y;

}

else

{

if(EndZ

{

EndZ=p3.y;

}

}

}

else

{

StartZ=p2.y;

EndZ=p1.y;

if(StartZp3.y)

{

StartZ=p3.y;

}

else

{

if(EndZ

{

EndZ=p3.y;

}

}

}

//确保范围没超出地图,确保观察范围超出地图范围不出错

if(StartX

{

StartX=0;

}

if(EndXCULL_SIZE_WIDTH)

{

EndX=CULL_SIZE_WIDTH;

}

if(StartZ

{

StartZ=0;

}

if(EndZCULL_SIZE_LONG)

{

EndZ=CULL_SIZE_LONG;

}

for(int i=StartZ;i

{

for(int j=StartX;j

{

if(Area[i][j]-m_pObject!=NULL)

{

D3DXVECTOR2 p,pp1,pp2,pp3;

p.x=j;

p.y=i;

pp1=p-p1;

pp2=p-p2;

pp3=p-p3;

if(IsInTriangle2D(p1,p2,p3,p,0.038))////判断该点是否在三角形中,小于0为在三角形中,大于0外不在三角形中

{

if(m_pCulledObject==NULL)

{

m_pCulledObject=new PObjectList();

m_pCulledObject-m_pObjectList=Area[i][j];//这个数组就是保存区域链表的数组Area[0][0]就保存的第0,0区域的链表

pNode=m_pCulledObject;

}

else

{

pNode-m_pNext=new PObjectList();

pNode=pNode-m_pNext;

pNode-m_pObjectList=Area[i][j];

}

}

}

}

}

}

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有