查看: 1836|回复: 0
打印 上一主题 下一主题

Away3D学习笔记-空间点捕捉

[复制链接]

435

主题

2

听众

6371

积分

高级设计师

Rank: 6Rank: 6

纳金币
6372
精华
0

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2012-8-30 10:13:32 |只看该作者 |倒序浏览
项目的基本技术要求,就是能捕捉用户在舞台上点击的3D坐标。
首先这涉及侦听MouseDown事件,如果Scene来侦听,当舞台上没东西时,是不会触发鼠标事件的,因此只能用Stage来侦听,而stage侦听的鼠标坐标是舞台的相对坐标,这里就需要一系列换算。
基本思路就是:将舞台坐标先换算为View3D的坐标,再通过Camera与该点的连线与坐标平面相交来计算点。
舞台坐标换View坐标可以以View的MouseX,MouseY属性为参数,调用Camera的unproject来计算。计算相交这部分代码不用自己写,Away3D的Plane3D对象封装了相关函数。因此代码很简洁:




?

   
        
            
            1
            
            
            
            private function onmd(e:MouseEvent):void<BR>        {<BR>           var pllane3D = new Plane3D();<BR>         pl.fromNormalAndPoint(new Vector3D(0, 0, -1), new Vector3D());<BR>          var v:Vector3D = camera.unproject(view.mouseX, view.mouseY)<BR>         v=v.add(camera.position);<BR>           var p:Vector3D = pl.getIntersectionLineNumbers(v, camera.position);<BR>     }<BR>
            
            
        
   




pl.fromNormalAndPoint是创建一个虚拟平面,第一个参数是平面法向,(0,0,-1)就是面向屏幕的面,第二个参数是平面上一点,直接默认在零点即可。
camera.unproject是调用Camera对象的投影方法得到一个坐标值,但这个值是相对于Camera的坐标,所以再加上Camera的坐标就成了绝对坐标。
pl.getIntersectionLineNumbers,函数名字有点长,参数是两个点,两点确定一条直线,返回的就是虚拟平面上的点了。
还有一种简单粗暴但有效的办法确定点,那就是创建一个真实的平面做坐标平面,然后监听平面的MouseDown事件,通过事件参数里的SceneX,SceneY,SceneZ来得到空间坐标,这种办法绝对不会错,唯一的问题就是如果平面被别的物体挡住了,MouseDown事件就失效了。
通过实验比较发现,这两种办法确定下来的点的坐标很相似,但后者正好比前者的坐标大了整1.2倍。造成这个诡异误差的原因不明,所以只好手工把前者产生的坐标扩大1.2倍使用了。



?

   
        
            
            1
            
            
            
            p.scaleBy(1.2);<BR>
            
            
        
   




然后我试图从坐标原点画一条线到鼠标点击位置:



?

   
        
            
            1
            
            
            
            var lineSegment = new LineSegment();<BR>l.end = new Vertex(0,0,p.z);<BR>l.start = new Vertex(p.x, p.y,p.z);<BR>l.material = new WireframeMaterial(0xff0000);<BR>scene.addChild(l);<BR>
            
            
        
   




问题更诡异了,终点居然比我鼠标点的位置还要长,重新检查两种方法得到的坐标值,发现那个倍数已经变成了1.15。
为了确认那个倍数到底是不是常数,于是我调整Camera位置,focus,zoom值继续实验。发现引起误差的原因来自于focus值,解决办法是让focus无限接近0,为了弥补focus过小导致物体太远,再把zoom放大相应倍数。Away3D里focus默认是100,zoom默认是10。这里我设focus为0.1,zoom就是10000。
在实际应用中,要获得某个物体的某个面上的点除了用传统的监听MouseDown外,也可以利用直线和面交点的办法,在创建Plane3D对象时,将物体上某个面的法向量和一个点作为参数。法向量和点用如下方法获取:




?

   
        
            
            1
            2
            
            
            
            view.hitManager.elementVO  as FaceVO).face.normal;
            view.hitManager.elementVO  as FaceVO).face.v0.position;
            
            
        
   




View.hitManage用于获取当前点击的一系列属性,类似于MouseEvent3D对象,用于非MouseEvent3D事件。上面两行代码第一行获取法向量,第二行获取被点击面上的一个点,v0是vertexs类,position是vector3D类。
分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2024-12-1 05:09 , Processed in 0.090815 second(s), 32 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部