three.jsを利用して3Dモデルのピッキングを実装しました。
下記はプログラムの一部です。
. . . .on("mousemove", containerId, function(e){ e.preventDefault(); var rect = e.target.getBoundingClientRect(); ns.mouse.x = ( (e.clientX - rect.left) / ns.width ) * 2 - 1; ns.mouse.y = - ( (e.clientY - rect.top) / ns.height ) * 2 + 1; }) . . . picking : function() { ns.raycaster.setFromCamera( ns.mouse, ns.camera ); var intersects = ns.raycaster.intersectObjects( ns.models.children, true ); if (!!ns.status.picked) { ns.fn._picking.setColor(ns.status.SELECTED); } if ( intersects.length > 0 ) { ns.vmarker = intersects[ 0 ].point; if ( ns.status.INTERSECTED != intersects[ 0 ].object.parent ) { if ( !ns.status.SELECTED || (ns.status.SELECTED && ns.status.SELECTED != ns.status.INTERSECTED) ) { ns.fn._picking.setColor(ns.status.INTERSECTED); } ns.status.INTERSECTED = intersects[ 0 ].object.parent; if (!ns.status.picked && ns.status.INTERSECTED != ns.status.SELECTED) { ns.fn._picking.setColor(ns.status.INTERSECTED,0x0000ff); } } if (!!ns.status.picked) { ns.fn._picking.select(ns.status.INTERSECTED); } } else { ns.vmarker = null; if ( !ns.status.SELECTED || (ns.status.SELECTED && ns.status.SELECTED != ns.status.INTERSECTED) ) { ns.fn._picking.setColor(ns.status.INTERSECTED); } ns.status.INTERSECTED = null; if (!!ns.status.picked) { ns.fn._picking.select(null); } } ns.status.picked = false; },
ただ、この実装では非常に大きいモデルの場合、実際のマウス位置と3D空間上のマウス位置で誤差が生じてしまい、期待した動作となりません。
次回以降、原因を考察していきたいと思います。
・そもそも、実装が間違っている?
・mousemoveイベントでの計算値の誤差
・three.js、raycaster等のバグ?