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等のバグ?