2012-04-03 9 views
3

Dies wurde möglicherweise bereits beantwortet, und wenn ja, zeigen Sie mich auf die Antwort. Ansonsten geht das hier.Java - Einfache Ebene des Einschlusses/Ausschlusses

Sie haben x Anzahl der Objekte im Raum, die Bounding-Koordinaten p0 und p1 haben. p0 und p1 sind jeweils 3-dimensionale Koordinaten und p0 hat immer die niedrigeren Werte - ob negativ oder positiv, und p1 hat immer die höheren Werte.

Jetzt haben Sie eine Ebene, die perfekt orthogonal zur Richtung der Kamera C ist, die eine Position (pC) und eine Überschrift (hC) hat. Diese Ebene kann dann als 90 Grad (pi/2 Radiant) von dem Gieren der Kamera (manchmal als "Heading" bezeichnet) und der Neigung definiert werden und sich bis zu den am weitesten definierten Grenzen in dem Raum erstrecken.

Da ich nicht mehr als 180 Grad FOV erlauben, muss alles, was vollständig hinter der Kamera liegt (hinter der Ebene des Ausschlusses) ausgeschlossen werden.

Gibt es eine einfache Möglichkeit, dies zu tun? Für diese Frage behandle ich nicht das Problem, gegen jedes Objekt im Raum zu prüfen; nehmen wir für unsere Frage an, dass es immer eine begrenzte Anzahl von Objekten gibt, die durch die Aufteilung des Raumes in irgendeiner Weise verwaltet werden, so dass die Objekte, gegen die wir uns wenden, immer "fragwürdig" sind.

Denken Sie auch daran, dass es nicht Punkte sind, sondern Punktepaare, die 3d-Begrenzungswürfel darstellen, es ist nicht genug, dass ein Punkt auf dieser oder jener Seite der Ebene liegt.

Ich habe das Gefühl, dass es eine einfache Möglichkeit gibt, dies zu tun, aber ich habe keine Computergrafik genommen. Ich wurde nie in die Mathematik eingeführt.

+0

ich zu einem besseren Ort für diese Frage vermuten in http://math.stackexchange.com würde (Math Forum) oder alternativ http://cs.stackexchange.com (CompSci forum) –

+0

Vielleicht, obwohl dies keine theoretische Frage ist, sondern eine praktische Frage. Es ist also keine mathematische Frage oder eine Frage der Informatik, sondern eine Java-Frage. Weil das Problem in Java gelöst werden muss! Ich habe es nur allgemein formuliert, um sicherzustellen, dass ich nicht die Antwort bekomme: "Sie repräsentieren diese auf die falsche Art und Weise ..." –

+0

Ein guter Punkt, aber wenn ein Algorithmus mathematisch definiert ist, dann können Sie ihn implementieren es in jeder Sprache, die Sie mögen. (Übrigens habe ich meinen Master-Abschluss in Computergrafik - vor 15 Jahren - aber kann mich an nichts Nützliches trotzdem erinnern :)) –

Antwort

1

Also hier ist, wie es geht.

Zuerst müssen Sie die acht Punkte in jeder Bounding Box in einer vorhersagbaren Weise speichern, zum Beispiel jedes Bit in einer Ganzzahl, die seine Position um die Mitte der Box darstellt. Was Sie tun können, ist 0x4 zu verwenden, um EAST (+ x) zu repräsentieren (Null in diesem Bit bedeutet WEST) 0x2, um NORTH darzustellen (Null in diesem Bit bedeutet SOUTH) und 0x1, um TOP darzustellen (Null in diesem Bit bedeutet BOTTOM). Jetzt können Sie universell auf alle Punkte in der gleichen Position des Begrenzungsrahmens zugreifen, indem Sie eine Positionsnummer angeben. (Alle Null-Bit-Zahlen sind nur Null Java warnt davor, dass diese Zuordnungen bedeutungslos sind, aber sie helfen mit Ablesbarkeit..)

den Begrenzungsrahmen einrichten: (tun dies für jeden Begrenzungskasten)

pointList = new Point3d[8]; 

    pointList[WEST|SOUTH|BOTTOM] = new Point3d(x0,y0,z0); 
    pointList[WEST|SOUTH|TOP] = new Point3d(x0,y0,z1); 
    pointList[WEST|NORTH|BOTTOM] = new Point3d(x0,y1,z0); 
    pointList[WEST|NORTH|TOP] = new Point3d(x0,y1,z1); 
    pointList[EAST|SOUTH|BOTTOM] = new Point3d(x1,y0,z0); 
    pointList[EAST|SOUTH|TOP] = new Point3d(x1,y0,z1); 
    pointList[EAST|NORTH|BOTTOM] = new Point3d(x1,y1,z0); 
    pointList[EAST|NORTH|TOP] = new Point3d(x1,y1,z1); 

Weiter Berechnen Sie die Normale aus Ihrem Blickwinkel. (Yaw ist links/rechts Rotation, Tonhöhe nach oben/unten Rotation)

float nx = -(float)Math.cos(yaw); 
    float ny = (float)Math.sin(yaw); 
    float nz = (float)Math.sin(pitch); 

Ich denke, das negative richtig ist, aber wenn alles auf der einen Seite nicht sichtbar ist, ist es gerade umgekehrt :)

Berechnen Sie die Charakteristik Punkt, der nur der Index ist, dass Sie in jedem Begrenzungskasten überprüfen gehen, weil es den Punkt in jedem Feld darstellt, die am nächsten zu der Ebene, auf der unsichtbaren Seite sein:

int characteristicPoint = (nx<0?WEST:EAST)| 
           (ny<0?SOUTH:NORTH)| 
           (nz<0?BOTTOM:TOP); 

Vergewissern Sie sich, dass jeder Begrenzungs Box ist so eingerichtet, dass x, y, z etwas kleiner sind nx, y, z prime (x0 = x aught, x1 = x prime)

Dann sammeln Sie Ihre charakteristischen ('check') Punkt, Ihre Gruppe von Normalen ('Kaugummi') und Ihre Kameraposition (x, y z), und dies mit jeder Bounding-Box:

float checkA = ((bounds.pointList[check].x-position.x)*frustrum.x) + 
      ((bounds.pointList[check].y-position.y)*frustrum.y); 

    float checkB = ((bounds.pointList[check].x-position.x)*frustrum.x) + 
      ((bounds.pointList[check].z-position.z)*frustrum.z); 
    if(checkB>=0&&checkA>=0) { 
     visible = true; 
     return; 
    } else if(checkB<0&&checkA<0) { 
     visible = false; 
     return; 
    } else { 
     float checkC = ((bounds.pointList[check].y-position.y)*frustrum.y) + 
      ((bounds.pointList[check].z-position.z)*frustrum.z); 
     if(checkC>=0) { 
      visible = true; 
      return; 
     } else { 
      visible = false; 
      return; 
     } 

    } 

Dies ist eine einfache lineare Algebra (IMO), und die Logik ist wie folgt: Wenn der Punkt auf der positiven Seite von zwei oder mehr der Linien repräsentieren die Flugzeug, es ist sichtbar. Wenn es sich um die negative Seite des Kabels oder um mehrere der Linien handelt, die die Ebene darstellen, ist es unsichtbar. Sie berechnen die ersten beiden, und wenn sie unterschiedlich sind (eine negative, eine positive), überprüfen Sie die dritte und nehmen Sie diesen Wert.

Es ist wichtig, die folgende Eigenschaft zu beachten, wenn Linien als Gleichungen Behandlung:

-x-y = p != x+y = p 

Die Linie ist die gleiche, aber die implizit ‚‘ zugewandte inverse.

Ich hoffe, das hilft jemand anderen mit dieser Frage. Es war schwer, aber angenehm, um es herauszufinden.

Diese effizienter gestaltet werden könnte durch die erste Hälfte des Checka speichern, nehme ich an :)

1

Ich denke, Sie wollen die Menge der Punktepaare finden, wo beide Punkte hinter der Kameraebene sind (was ich glaube, Sie beschreiben als normale 2D-Ebene, die den Punkt pC und mit normaler HC enthält), aber ich kann habe missverstanden.

Wenn das ist, was Sie wollen, dann versuchen Sie dies:

  • hC ist Ihre normale Ebene
  • Satz vp0 als Vektor von pC zu p0 (do Position p0 - Position von pC)
  • Satz VP1 als der Vektor von pC bis p1 (do Position p1 - Position des pC)

p0 ist sichtbar, wenn VP0. hC> = 0 (oder> 0, wenn Sie möchten, dass es sich genau vor der Kamera befindet).

p1 ist sichtbar, wenn vp1. hC> = 0 (oder> 0, wenn Sie möchten, dass es sich genau vor der Kamera befindet).

. Hier ist ein Standard-Vektor-Dot-Produkt.

Wenn also sowohl p0 als auch p1 hinter der Kamera sind, können Sie die Form ausschließen.

+0

+1, das ist ziemlich genau was ich tippte. @RiverC die einzige Mathematik, die Sie vermissen, ist die Standardterminologie; Sie haben die Konzepte unten. Ihre Kamera "Position" und "Kopf" zusammen definieren eine ** Ebene ** in Bezug auf ** einen Punkt auf ** und seine ** normal **. – AakashM

+0

Ein Problem. Betrachten wir den Fall, dass die Kamera bei p0 oder p1 sitzt und senkrecht zu der Linie steht, die durch p0, p1 gebildet wird. (P). Während sowohl p0 als auch p1 hinter der Ebene liegen können, wird ein Teil des begrenzenden Würfels immer noch auf der Inklusionsseite der Ebene liegen. Gibt es einen einfachen Weg, um dies zu lösen, oder brauche ich alle acht Punkte statt nur zwei? (im Allgemeinen muss ich nur herausfinden, wie viel Mathematik es braucht, um herauszufinden, bei welcher Geometrie Komplexitätsebene es wert ist, dies zu tun) –

+0

Ich denke, dass Sie entweder alle 8 Punkte des Begrenzungswürfels wissen und jeden von ihnen testen möchten oder möglicherweise eine 3D-Raumtransformationsmatrix finden und diese auf alle Punkte anwenden, so dass die Achse entweder parallel oder senkrecht zur Betrachtungsebene ist. Dann kannst du wahrscheinlich zwei Punkte auf deinen begrenzenden Würfeln behalten. Ich bezweifle, dass dies ein effizienter Weg ist. – Helen

1

Wenn eine der 6 Ecken des "Würfels" (konventionell als Axis-Aligned Bounding Box oder AABB bezeichnet) auf der Ansichtsseite der Ebene liegt, kann möglicherweise etwas darin zu sehen sein.Sie können, indem Sie die beiden ersten Punkte beginnen, aber wenn sie beide unsichtbar sind, werden Sie auch die anderen sechs Ecken überprüfen müssen, wie folgt:

initial corners: p0=(p0.x, p0.y, p0.z) 
       p1=(p1.x, p1.y, p1.z) 

other corners:  (p1.x, p0.y, p0.z) 
        (p0.x, p1.y, p0.z) 
        (p0.x, p0.y, p1.z) 

        (p1.x, p1.y, p0.z) 
        (p0.x, p1.y, p1.z) 
        (p1.x, p0.y, p1.z) 

Beachten Sie, dass die herkömmliche Rasterung Pipeline nicht hinter ziehen sollten Objekte die Kamera, weil es Dreiecke klammert, die außerhalb der viewing frustum fallen. Dies deutet darauf hin, dass Sie vielleicht auch gegen die anderen Kegelstümpfe oder vielleicht gegen den Sichtkegelstumpf als Ganzes testen möchten, was ein bisschen komplexer, aber wahrscheinlich eine gute Idee ist. Es mag langweilig erscheinen, aber ein Kegeltest ist immer noch billiger als der Versuch, unsichtbare Objekte zu zeichnen.

+0

Richtig, aber wenn Sie partitionierten Speicherplatz verwenden - wenn die Begrenzungsfelder komplexe Datengruppen darstellen (sie werden!), Möchten Sie sicherstellen, dass Sie keine Zyklen verschwenden, wenn Sie ~ 1000 faces + an den Renderer senden ein paar Checks gegen die Begrenzungsboxen der Partitionen und eliminiere sie aus der Renderliste dieses Frames. Mein Hauptpunkt hier ist meine Ansicht Winkel und Position, kombiniert mit einer Sammlung von p0, p1-Paare, was muss ich eigentlich in Java tun, um jede Bounding-Box zu "verdunkeln"? –

+0

Um zu einer Ebene zu überprüfen, müssen Sie sicherstellen, dass alle 8 Ecken auf der unsichtbaren Seite der Ebene liegen. Gegenüber einem Betrachtungsfrustum zu prüfen ist ein bisschen komplexer, aber es sollte besser sein, alles gleichzeitig zu machen. Google "AABB frustum" - Ich habe keinen definitiven Link gefunden, aber es ist immer noch einen Besuch wert. – comingstorm

+0

aw yiss, ich habe es selbst herausgefunden. Ich hatte gehofft, diesen Wahnsinn nicht zu verstehen, aber irgendwie habe ich es geschafft. –