2017-08-12 13 views
0

以下の最小限の例では(three.min.jsのURLを変更することを忘れないでください)、ウィンドウでhtmlファイルを開きます。あなたは(非正規の)四面体を見るべきです。離れてから以来RayCasterは、複製されたジオメトリで遅く作成されたメッシュを検出しません。

raycaster.intersectObjects(scene.children,false); 

:キャンバスの上にマウスを移動するときは、コードでこの行でテストシーンオブジェクトのすべてのオブジェクトとマウスにカメラからの光線の交点の数が表示されます

var material = new THREE.MeshLambertMaterial({ color: 0xd8f8b0, side: THREE.DoubleSide }); 

今すぐクリックしてください:それは無限の線が交差し、私は両面材料を選択しているので、されている顔の数をカウントするのでligthsは、四面体は、それはほとんどが0または2が言うだけさチェックボックス。他の四面体がその場で作成され、その幾何学は第1のメッシュの幾何学的形状のクローンである。

geom2 = geom.clone();

私は、頂点のすべての座標に1を加えて新しいgeomをオフセットしました。ただし、レイキャスターは、新しいオブジェクトと交差するほとんどのレイの0に答えます。バグがありますか、何かを忘れたり、誤解したりしましたか?

ジオメトリがクローンでない場合(clone = falseに変更する; min.jsの上にある場合)、ジオメトリは機能します。

Three.jsバージョン:R86

最小限の例

htmlファイル:

<!DOCTYPE html> 
<html> 

<head> 
<meta charset="utf-8"> 
<script src="three.min.js"></script> 
</head> 

<body> 
<div style="text-align: center;"> 
<canvas id="ze-canvas" width="800" height="600"></canvas> 
<p> 
<input type="checkbox" id="filBox"> click me 
<p> 
<span id="info-text"></span> 
<p> 
<script src="min.js"></script> 
<script>visualiseur("ze-canvas","info-text","filBox");</script> 
</div> 
</body> 
</html> 

ファイルmin.js

var visualiseur = function(canvas_name,info_name,box_name) { 
    var clone = true; 

    var canvas = document.getElementById(canvas_name); 
    var cbox = document.getElementById(box_name); 
    var textInfo = document.getElementById(info_name); 

    cbox.checked = false; 

    var camera = new THREE.PerspectiveCamera(33, canvas.width/canvas.height, 0.1, 1000); 
    camera.position.set(-2,4,8); 
    camera.lookAt(new THREE.Vector3(0,0,0)); 

    var scene = new THREE.Scene(); 

    scene.add(new THREE.AmbientLight(0xffffff, .3)); 
    var light1 = new THREE.PointLight(0xCCffff, .7, 0, 2); 
    var light2 = new THREE.PointLight(0xffffCC, .7, 0, 2); 
    light1.position.set(50, -50, 20); 
    light2.position.set(-50, 150, 60); 
    scene.add(light1); 
    scene.add(light2); 

    var material = new THREE.MeshLambertMaterial({ color: 0xd8f8b0, side: THREE.DoubleSide }); 

    var makeGeom = function(geom) { 
    geom.vertices.push(new THREE.Vector3(0,0,0)); 
    geom.vertices.push(new THREE.Vector3(0,0,1)); 
    geom.vertices.push(new THREE.Vector3(0,1,0)); 
    geom.vertices.push(new THREE.Vector3(1,0,0)); 
    geom.faces.push(new THREE.Face3(0,1,2)); 
    geom.faces.push(new THREE.Face3(1,3,2)); 
    geom.faces.push(new THREE.Face3(0,2,3)); 
    geom.faces.push(new THREE.Face3(0,3,1)); 
    geom.computeFlatVertexNormals(); 
    } 

    var geom = new THREE.Geometry(); 
    makeGeom(geom); 
    var mesh = new THREE.Mesh(geom,material); 
    scene.add(mesh); 

    var renderer = new THREE.WebGLRenderer({ canvas : canvas, antialias: true}); 

    var render = function() { 
    renderer.render(scene, camera); 
    } 

    function getMousePos(evt) { 
    var rect = canvas.getBoundingClientRect(); 
    return { 
     x: evt.clientX - rect.left, 
     y: evt.clientY - rect.top 
    }; 
    } 

    var raycaster = new THREE.Raycaster(); 

    canvas.onmousemove = function(e) { 
    render(); 
    var p=getMousePos(e); 
    p.x = p.x/canvas.width*2 - 1; 
    p.y = -p.y/canvas.height*2 + 1; 
    raycaster.setFromCamera(new THREE.Vector2(p.x,p.y), camera); 
    var intersects = raycaster.intersectObjects(scene.children,false); 
    textInfo.innerHTML=intersects.length+" intersections"; 
    } 

    var done=false; 

    cbox.onclick = function(e) { 
    if(done) return; 
    done = true; 
    var geom2; 
    if(clone) { 
     geom2 = geom.clone(); 
    } 
    else { 
     geom2 = new THREE.Geometry(); 
     makeGeom(geom2); 
    } 
    geom2.vertices.forEach(function(v) { 
     v.x += 1; 
     v.y += 1; 
     v.z += 1; 
    }); 
    geom2.verticesNeedUpdate=true; 
    geom2.computeFlatVertexNormals(); 
    scene.add(new THREE.Mesh(geom2,material)); 
    render(); 
    } 

    render(); 
} 

答えて

0

これはトリッキー1が、私でした解決策が見つかりました。要するに

:ちょうど頂点を変更した後

geom2.computeBoundingSphere(); 

を追加します。

ロングバージョン:解決方法は次のとおりです。 私はGeometry.jsのソースコードを見て、見逃していた可能性のあるジオメトリのすべてのメンバー関数や変数を調べ始めました。 私は最後にTHREE.jsでこれまで聞いたことがなかったこの境界ボックスと境界球のことに気付きました。 THREE.jsのドキュメンテーションのGeometryセクションを振り返ってみると、それらは言及されていますが、それらが何のために使われているかについての説明はありません。

自然に考えているのは、最初に線と箱/球との交差点を計算することによってグラフィックスカードの描画を高速化することです(これは私が速いと思います)。もし存在しなければ、全体をスキップすることができますオブジェクト。

これは誤った仮定であることが分かります。最小限の例では、第2四面体は、境界球が間違っていてもと表示されます。

さらに奇妙になりました。私は、ボックスをクリックすると、複製の直前と次のレンダリングパスの直後に、スクリプトに形状の境界ボックスと球体を記録させました。 境界ボックスが決して得られません。 最初のジオメトリの前後に境界球があります。 clone = trueの場合にのみ、レンダリング前の境界球が2番目にあります(作成時に境界球がないため)。 レンダリング後、両方のオブジェクトに境界球があります。

結論:境界球はレイキャスターによって使用されますが、レンダリングされることはありません。バウンディング球の中心を検査することによって

(これは私には驚きです)、私は)それはクローン化され、頂点が移動したときに、第2のジオメトリのバウンディング球が間違っていた、とは(レンダリングによって更新されていないことに気づきました。 オブジェクトが作成され、render()が呼び出されると、その境界球が作成され、正しいものとなります。ただし、頂点を変更してverticesNeedUpdateフラグをtrueに設定しても、境界球が更新されない場合は、手動でcomputeBoundingSphere()を呼び出す必要があります。

バウンディングボックスではなく、render()を呼び出すと、境界球が秘密に作成されるということは、はるかに困惑しています。

私はこのすべての理解何総括してみましょう:

  • バウンディング球はバウンディングボックスがで使用されている場合、私は無視レンダラ

  • をRaycasterが使用していないが、 (私は時間を費やしていませんでした)

  • 境界球が存在しない場合は、render()を呼び出すときに作成されます。存在する場合、ではなく、フラグverticesNeedUpdateがtrueに設定されている場合でもrender()を呼び出してが更新されません。

  • バウンディングボックスが(レンダリングによって作成されません)

これは設計された動作ですかこれはバグでしょうか?

関連する問題