之前的这篇文章
http://www.dreamfairy.cn/blog/index.php/2013/05/05/picking-object-in-stage3d.html
其中的公式可能有点难懂=.= , 而且有个bug, 即相机旋转后无法选择物体.
嘛~今天我们来换一种方式来实现,并且支持旋转的相机.
世界上代码,里面有注释
[cc lang=”actionscript3″]
/**
* 包围球射线检测
* param o 射线原点
* param d 射线角度
* param c 圆心
* param r 半径
*/
public static function RaySphereIntersect(o : Vector3D, d : Vector3D, c : Vector3D, r : Number) : Boolean
{
var intersect : Boolean;
var s : Number;
var l : Vector3D = c.subtract(o); //圆心到射线原点的距离
s = d.dotProduct(l); //以射线起点开始,以射线的方向步进和包围球的长度的距离
var ll : Number = l.length * l.length; //以射线的起点为圆心,以和包围球的距离为半径假设一个球形
var rr : Number = r * r;
if(s < 0 && ll > rr) return false; //s < 0 表示目标在射线之后, ll > rr 表示射线不在圆内
var mm : Number = ll – s*s; //圆心垂直于射线方向的长度
if(mm > rr) return false; //和射线构成的三角形不在圆内
var q : Number = Math.sqrt(rr – mm); //圆心垂直于射线方向的点到射线碰撞的圆表面点的距离
var t : Number; //射线起点和圆相交点的距离
if(ll > rr) //当射线在圆外
t = s – q;
else
t = s + q;
return true;
}
[/cc]
[cc lang=”actionscript3″]
stage.addEventListener(MouseEvent.CLICK, onClick);
private function onClick(e:MouseEvent) : void
{
//将鼠标点击位置偏移视口中央
var sceenX : Number = stage.mouseX;
var sceenY : Number = stage.mouseY;
var viewX : Number = (sceenX * 2 / stage.stageWidth) – 1;
var viewY : Number = (-sceenY * 2 / stage.stageHeight) + 1;
var ray : Ray = new Ray();
//将射线转换到相机所在空间
var viewMat : Matrix3D = m_camera.getViewMatrix().clone();
ray.origin = viewMat.transformVector(new Vector3D(0,0,0));
//将相机反转,相机的平移和旋转总是和世界坐标系相反的
viewMat.invert();
ray.direction = viewMat.deltaTransformVector(new Vector3D(viewX,viewY,1));
ray.direction.normalize();
//取出相机的缩放值
var scale : Vector3D = m_proj.decompose()[2];
//将射线转到目标所在空间
var cubeMesh : CubeMesh;
for each(cubeMesh in m_cubeList)
{
//相交检测
var cubePos : Vector3D = cubeMesh.transform.position;
cubePos.x *= scale.x;
cubePos.y *= scale.y;
cubePos.z *= scale.z;
if(Ray.RaySphereIntersect(ray.origin, ray.direction, cubePos, 2))
trace(“碰撞”, m_cubeList.indexOf(cubeMesh));
}
}
[/cc]
btw: 该来的总会来的,工作开始转向用cocos2d-x来制作手游了. stage3D这块还会继续研究的,只是成为副业了. o(︶︿︶)o 唉 真坑爹.