2012-08-18 5 views
6

Ich brauche etwas Hilfe, um mit THREE.Frustum Objekt umzugehen.Berechnen Sie nahe/fernen Ebene Vertices mit THREE.Frustum

Mein Problem:

Ich brauche Nah-/Fern-Ebene Eckpunkte zu berechnen; Ich habe einen Blick auf diese Tutorials genommen

  1. http://www.lighthouse3d.com/tutorials/view-frustum-culling/view-frustums-shape/
  2. http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-extracting-the-planes/

und ich habe diese Funktion skizzierte Implementierung genau (hoffentlich) das Verfahren erklärt (nur oben links zu bekommen

 // Near Plane dimensions 
     hNear = 2 * Math.tan(camera.fov/2) * camera.near; // height 
     wNear = hNear * camera.aspect; // width 

     // Far Plane dimensions 
     hFar = 2 * Math.tan(camera.fov/2) * camera.far; // height 
     wFar = hFar * camera.aspect; // width 

getVertices : function() { 
     var p = camera.position.clone(); 
     var l = getCurrentTarget(); // see below 
     var u = new THREE.Vector3(0, 1, 0); 

     var d = new THREE.Vector3(); 
     d.sub(l, p); 
     d.normalize(); 

     var r = new THREE.Vector3(); 
     r.cross(u, d); 
     r.normalize(); 

     // Near Plane center 
     var dTmp = d.clone(); 
     var nc = new THREE.Vector3(); 
     nc.add(p, dTmp.multiplyScalar(camera.near)); 

     // Near Plane top-right and top-left vertices 
     var uTmp = u.clone(); 
     var rTmp = r.clone(); 
     var ntr = new THREE.Vector3(); 
     ntr.add(nc, uTmp.multiplyScalar(hNear/2)); 
     ntr.subSelf(rTmp.multiplyScalar(wNear/2)); 

     uTmp.copy(u); 
     rTmp.copy(r); 
     var ntl = new THREE.Vector3(); 
     ntl.add(nc, uTmp.multiplyScalar(hNear/2)); 
     ntl.addSelf(rTmp.multiplyScalar(wNear/2)); 

     // Far Plane center 
     dTmp.copy(d); 
     var fc = new THREE.Vector3(); 
     fc.add(p, dTmp.multiplyScalar(camera.far)); 

     // Far Plane top-right and top-left vertices 
     uTmp.copy(u); 
     rTmp.copy(r); 
     var ftr = new THREE.Vector3(); 
     ftr.add(fc, uTmp.multiplyScalar(hFar/2)); 
     ftr.subSelf(rTmp.multiplyScalar(wFar/2)); 

     uTmp.copy(u); 
     rTmp.copy(r); 
     var ftl = new THREE.Vector3(); 
     ftl.add(fc, uTmp.multiplyScalar(hFar/2)); 
     ftl.addSelf(rTmp.multiplyScalar(wFar/2)); 

getCurrentTarget : function() { 
     var l = new THREE.Vector3(0, 0, -100); 
     this.camera.updateMatrixWorld(); 
     this.camera.matrixWorld.multiplyVector3(l); 
     return l; 
    } 

Dies scheint aber ...

zu arbeiten:/rechts Ecken, können die Kamera unter der Annahme, nur und rechts) Blick nach links

Meine Frage:

Kann ich das gleiche Ergebnis in einem eleganteren (vielleicht korrekteren) Weg mit einem THREE.Frustum-Objekt erhalten?

Antwort

5

Three.Frustum wird Ihnen nicht wirklich helfen - es ist eine Reihe von Flugzeugen. Die gute Nachricht ist, dass Ihre Lösung korrekt erscheint, aber es gibt einen einfacheren Weg, darüber nachzudenken.

Die obere rechte Ecke des nahen Ebene ist ein Punkt im Kameraraum mit diesen Koordinaten:

var ntr = new THREE.Vector3(wNear/2, hNear/2, -camera.near); 

Ihre Definition von wNear und hNear verwenden, die richtig sind.

nun dafür sorgen, dass camera.matrixWorld aktualisiert wird, können Sie diesen Punkt zu Welt konvertieren Koordinaten wie folgt:

camera.updateMatrixWorld(); 
ntr.applyMatrix4(camera.matrixWorld); 

Nun drehen die Zeichen, die anderen drei Ecken zu bekommen, und dann die Berechnung für das weit wiederholen Ebene.

Sehen Sie, Sie hatten es richtig gemacht; Sie haben nur einen komplizierteren Weg genommen. :-)

BEARBEITEN: aktualisiert auf three.js r.66

+0

Vielen Dank! Ich habe mein Leben vergeblich verkompliziert :-) Diese Lösung ist einfacher und funktioniert besser! – Skarafaz

+0

Ich versuche grundsätzlich das Gleiche zu tun, um zu vermeiden, Partikel außerhalb des sichtbaren Raums zu platzieren, aber es sieht nicht so aus, als würde das Richtige passieren. http://jsfiddle.net/cZb66/ ist ein Beispiel dafür, was ich meine. Ich habe erwartet, dass die Eckfelder an den Ecken des Bildschirms sind, aber sie sind nicht .... –

+0

@ChrisMorgan Sie müssen einen neuen Beitrag machen, wenn Sie eine Frage haben. – WestLangley