HTML5技术

Web3D编程总结——3D碰撞检测初探 - ljzc002

字号+ 作者:H5之家 来源:博客园 2016-02-05 18:00 我要评论( )

自己动手写一个方法比分析他人的写的方法困难很多,由此而来的对程序的进一步理解也是分析别人的代码很难得到的。 一、先来几张效果图: 1、场景中有两个半径为1的球体,蓝色线段从球心出发指向球体的正向 2、物体被选中后改变纹理图片和透明度,可以使用w、

自己动手写一个方法比分析他人的写的方法困难很多,由此而来的对程序的进一步理解也是分析别人的代码很难得到的。

一、先来几张效果图:

1、场景中有两个半径为1的球体,蓝色线段从球心出发指向球体的“正向”

2、物体被选中后改变纹理图片和透明度,可以使用“w、s、a、d、空格、ctrl”控制物体相对于物体的正向“前、后、左、右、上、下”移动,按住按键时间越长移动速度越快,绿色线段由球心指向物体运动方向,速度越快露出物体表面的部分越长,按“g”停止所有移动,再次点击物体取消选中状态。

3、可以选取多个物体同时移动。

4、两物体发生碰撞后停止移动,红色线段由物体球心指向运动方向上遇到的第一个其他物体

 二、碰撞检测原理:

借用THREE.Raycaster来进行碰撞检测,因为Raycaster不能检测到物体的“内表面”,所以使用反射法。

三、程序实现:

完整程序代码可以在下载查看,其中包括详细注释,这里解释一下几个比较重要的段落。

1、绘制示意物体运动情况的线段

.line2;.line3;vector2=.line1=.line2=this.createLine2(this.object3D.position,this.object3D.position,0x00ff00,this.planetGroup,"line2"); 7 this.line3=this.createLine2(this.object3D.position,this.object3D.position,0xff0000,this.planetGroup,"line3");

 其中点vector2由向量v0乘以2加上this.object3D.position得到,作为直线line1的结束点。注意v0后的“.clone()”如果去掉则v0本身也会应用这些变化,最终变得与vector2相同。

line2和line3被初始化为一个点。

这里建立的“line”对象并没有碰撞检测功能,纯粹是用来看的。 

1 if (this.speedw != 0 || this.speeda != 0||this.speedc!=0) vector4=new THREE.Vector3(0,this.speedc*1000,0); 4 var vector3=(this.v1.clone().multiplyScalar(this.speeda*1000)).add(this.v0.clone().multiplyScalar(this.speedw*1000)).add(vector4); 5 var vector5=vector3.clone().normalize().multiplyScalar(this.size); 6 this.vector3=vector3.clone().add(vector5); .testCollision();( { 14 this.object3D.position.add(this.v0.clone().multiplyScalar(this.speedw)); 15 this.object3D.position.add(this.v1.clone().multiplyScalar(this.speeda)); } { 20 this.speeda=0; 21 this.speedc=0; 22 this.speedw=0; currentlyPressedKeys[65]=false; 25 currentlyPressedKeys[68]=false; 26 currentlyPressedKeys[87]=false; 27 currentlyPressedKeys[83]=false; 28 currentlyPressedKeys[32]=false; 29 currentlyPressedKeys[17]=false; 30 } 31 }

 根据物体的运动情况更新line2的方向和长度。在这里vector3由物体在各个方向上的速度分量组合而成,vector5负责把vector3调整为适合显示的长度,this.vector3和vector3是不同的对象,表示line2一个端点的位移。

updateLine2更新line2的端点,表现出速度的变化。我们可以看到它的两个端点位置参数是(0,0,0)和一个向量而不是前面图中的球心位置和“球心位置加向量得到的点”,这体现出了Three.js父子物体间的相对性。(简单的碰撞示例原本不需要使用子物体,我是不是自讨苦吃?)

该示例延续自上一篇中的太阳系模型,物体间的关系如下图:

planetOrbitGroup和planetGroup是“Object3D”对象,这种“物体”没有大小、颜色属性只有位置和姿态属性(默认位于父物体的原点),“Mesh”和“Line”多重继承于Object3D具有顶点(geometry)、纹理(material)属性。

planetOrbitGroup是Scene的子物体位于世界坐标系原点,planetGroup是planetOrbitGroup的子物体强制定位于世界坐标系x=3处,globeMesh和line2是planetGroup的子物体默认位于planetGroup的原点。

当planetOrbitGroup移动时(改变this.object3D.position),这个移动效果会被它所有的后代对象继承,所以我们把line2的一个顶点设为(0,0,0)后会自动继承它所有祖先元素的移动效果(this.object3D.position+(3,0,0))。

2、基于射线的碰撞测试

raycaster.far=intersects = raycaster.intersectObjects(scene.children,true);

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 使用Docker分分钟启动常用应用 - 编程玩家

    使用Docker分分钟启动常用应用 - 编程玩家

    2017-04-10 14:00

  • 我,编程和大学 - 外婆的彭湖湾

    我,编程和大学 - 外婆的彭湖湾

    2017-04-09 17:04

  • 做开发十年,我总结出了这些开发经验 - 腾讯云技术社区

    做开发十年,我总结出了这些开发经验 - 腾讯云技术社区

    2017-03-25 15:00

  • 初学编程一周的感想 - 陈老仁

    初学编程一周的感想 - 陈老仁

    2017-03-20 10:01

网友点评