Arbeit zu BSP

Übersicht Sonstiges Smalltalk

Neue Antwort erstellen

Vertex

Betreff: Arbeit zu BSP

BeitragMi, Jan 12, 2011 20:23
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,

für's Studium habe ich eine Arbeit zum Thema Binary Space Partitioning Trees (BSP-Bäume) ausgearbeitet. Es geht darum, den Algorithmus zum Erstellen eines solchen Baums zu parallelisieren. Wen es interessiert, die Arbeit kann unter http://vertex.dreamfall.at/bsp...lelbsp.pdf eingesehen werden. Der erste Teil beschäftigt sich mit dem BSP-Algorithmus (das wäre für euch 3D Grafiker sicherlich der interessante Teil) und der zweite Teil mit dem Parallelisieren mittels Work Stealing. Die Anwendung habe ich nicht hochgeladen, weil Webserver auf ein paar MB begrenzt ist und zweitens das Projekt in Java programmiert wurde.

Ciao Olli

Edit: Manchmal sucht man ja im Forum nach einer Funktion, die ein Dreieck an einer Ebene schneidet:
Code: [AUSKLAPPEN]
package de.skawronek.parallelbspcompiler.math;

/**
 * Eine Ebene in Hesse-Normalenform beschrieben durch den Normalenvektor
 * {@link #normal} und die Konstante {@link #constant}.
 *
 * @author Oliver Skawronek
 *
 */
public class Plane {
   public static enum Side {
      Planar, Positive, Negative;
   }

   private Vector3d normal;
   private double constant;

   public Plane() {
      normal = new Vector3d();
   }

   public Plane(Vector3d normal, double constant) {
      this.normal = normal;
      this.constant = constant;
   }

   public Plane(Triangle triangle) {
      normal = triangle.getNormal();
      constant = triangle.get1().dot(normal);
   }

   public Vector3d getNormal() {
      return normal;
   }

   public double getConstant() {
      return constant;
   }

   public double distance(Vector3d point) {
      return normal.dot(point) - constant;
   }

   /**
    *
    * @param point
    * @return Seite, auf der <code>point</code> liegt.
    */
   public Side side(Vector3d point) {
      double d = distance(point);
      if (Math.abs(d) < Constants.DBL_EPSILON)
         return Side.Planar;
      else if (d > 0.0)
         return Side.Positive;
      else
         return Side.Negative;
   }

   /**
    * Ermittelt die Seite, auf der <code>triangle</code> liegt:
    * <ul>
    * <li>alle Eckpunkte liegen entweder auf der positiven Seite oder sind plan
    * zur Ebene: {@link Side#Positive}</li>
    * <li>alle Eckpunkte liegen entweder auf der negativen Seite oder sind plan
    * zur Ebene: {@link Side#Negative}</li>
    * <li>sonst: {@link Side#Planar}</li>
    * </ul>
    *
    * @param triangle
    * @return Seite, auf der das Dreieck liegt.
    */
   public Side side(Triangle triangle) {
      int planar = 0, pos = 0, neg = 0;
      for (int i = 0; i < 3; i++) {
         switch (side(triangle.get(i))) {
         case Planar:
            planar++;
            break;
         case Positive:
            pos++;
            break;
         case Negative:
            neg++;
            break;
         }
      }

      // Liegen alle drei Ecken auf der Ebene?
      if (planar == 3) {
         // Zeigt der Normalvektor des Dreiecks in die selbe Richtung wie die
         // Ebene?
         if (Math.abs(normal.dot(triangle.getNormal()) - 1.0) < Constants.DBL_EPSILON)
            return Side.Positive;
         else
            return Side.Negative;
         // Liegen alle Ecken auf der pos. Seite,
         // oder liegen zwei Ecken auf der Ebene und eine auf der pos. Seite,
         // oder liegt eine Ecke auf der Ebene und die anderen zwei auf der
         // pos. Seite?
      } else if (pos + planar == 3) {
         return Side.Positive;
         // Liegen alle Ecken auf der neg. Seite,
         // oder liegen zwei Ecken auf der Ebene und eine auf der neg. Seite,
         // oder liegt eine Ecke auf der Ebene und die anderen zwei auf der
         // neg. Seite?
      } else if (neg + planar == 3) {
         return Side.Negative;
         // Sonst wird das Dreieck geteilt
      } else {
         return Side.Planar;
      }
   }

   /**
    * Berechnet den Schnittpunkt von <code>line</code> mit der Ebene und gibt
    * diesen zurück. Gibt es keinen Schnittpunkt, wird <code>null</code>
    * zurückgegeben.
    *
    * @param line
    * @return Schnittpunkt von <code>line</code> mit der Ebene oder
    *         <code>null</code>.
    */
   public Vector3d intersects(Line line) {
      // d = p2 - p1
      Vector3d direction = line.getEnd().copy();
      direction.substract(line.getStart());
      // n*d
      double denominator = normal.dot(direction);
      if (Math.abs(denominator) < Constants.DBL_EPSILON)
         return null;
      // t = (c - n*p1)/(n*d)
      double t = (constant - normal.dot(line.getStart())) / denominator;
      // Punkt auf Linie?
      if (t < 0.0 || t > 1.0)
         return null;
      // p1 + t*d
      Vector3d intersection = direction.copy();
      intersection.scale(t);
      intersection.add(line.getStart());
      return intersection;
   }

   /**
    * Teilt <code>triangle</code> an der Ebene. Die Dreiecke auf der positiven
    * Seite werden in <code>positiveTriangles</code> und auf der negativen
    * Seite in <code>negativeTriangles</code> eingefügt. Die beiden Arrays
    * müssen mindestens zwei Elemente groß sein. Um anschließend zur ermitteln,
    * wieviele Dreiecke in welches Array eingefügt worden, sollten alle
    * Elemente der Arrays vorher auf <code>null</code> gesetzt werden.
    *
    * @param triangle
    * @param positiveTriangles
    * @param negativeTriangles
    */
   public void intersects(Triangle triangle, Triangle[] positiveTriangles,
         Triangle[] negativeTriangles) {
      // Ebenenseiten aller Eckpunkte
      int planCount = 0;
      int posCount = 0;
      int negCount = 0;

      Side[] sides = new Side[3];
      for (int i = 0; i < 3; i++) {
         sides[i] = side(triangle.get(i));
         switch (sides[i]) {
         case Planar:
            planCount++;
            break;
         case Negative:
            negCount++;
            break;
         case Positive:
            posCount++;
            break;
         }
      }

      if (planCount == 3) {
         if (Math.abs(normal.dot(triangle.getNormal()) - 1.0f) < Constants.DBL_EPSILON)
            positiveTriangles[0] = triangle;
         else
            negativeTriangles[0] = triangle;
         return;
      } else if (planCount + posCount == 3) {
         positiveTriangles[0] = triangle;
         return;
      } else if (planCount + negCount == 3) {
         negativeTriangles[0] = triangle;
         return;
      }

      Line[] edges = new Line[3];
      edges[0] = triangle.getEdge1();
      edges[1] = triangle.getEdge2();
      edges[2] = triangle.getEdge3();

      // Kollision aller Kanten mit der Ebene
      Vector3d[] intersections = new Vector3d[3];
      for (int i = 0; i < 3; i++) {
         intersections[i] = intersects(edges[i]);
      }

      if (sides[1] != Side.Planar && intersections[0] != null
            && intersections[0].equals(intersections[1])) {
         if (sides[1] == Side.Positive) {
            positiveTriangles[0] = triangle;
         } else {
            negativeTriangles[0] = triangle;
         }
      } else if (sides[2] != Side.Planar && intersections[1] != null
            && intersections[1].equals(intersections[2])) {
         if (sides[1] == Side.Positive) {
            positiveTriangles[0] = triangle;
         } else {
            negativeTriangles[0] = triangle;
         }
      } else if (sides[0] != Side.Planar && intersections[2] != null
            && intersections[2].equals(intersections[0])) {
         if (sides[2] == Side.Positive) {
            positiveTriangles[0] = triangle;
         } else {
            negativeTriangles[0] = triangle;
         }
      } else if (sides[0] == Side.Planar) {
         if (sides[1] == Side.Positive) {
            positiveTriangles[0] = new Triangle(triangle.get1(),
                  triangle.get2(), intersections[1]);
            negativeTriangles[0] = new Triangle(triangle.get1(),
                  intersections[1], triangle.get3());
         } else {
            negativeTriangles[0] = new Triangle(triangle.get1(),
                  triangle.get2(), intersections[1]);
            positiveTriangles[0] = new Triangle(triangle.get1(),
                  intersections[1], triangle.get3());
         }
      } else if (sides[1] == Side.Planar) {
         if (sides[0] == Side.Positive) {
            positiveTriangles[0] = new Triangle(triangle.get1(),
                  triangle.get2(), intersections[2]);
            negativeTriangles[0] = new Triangle(intersections[2],
                  triangle.get2(), triangle.get3());
         } else {
            negativeTriangles[0] = new Triangle(triangle.get1(),
                  triangle.get2(), intersections[2]);
            positiveTriangles[0] = new Triangle(intersections[2],
                  triangle.get2(), triangle.get3());
         }
      } else if (sides[2] == Side.Planar) {
         if (sides[1] == Side.Positive) {
            positiveTriangles[0] = new Triangle(intersections[0],
                  triangle.get2(), triangle.get3());
            negativeTriangles[0] = new Triangle(intersections[0],
                  triangle.get3(), triangle.get1());
         } else {
            negativeTriangles[0] = new Triangle(intersections[0],
                  triangle.get2(), triangle.get3());
            positiveTriangles[0] = new Triangle(intersections[0],
                  triangle.get3(), triangle.get1());
         }
      } else if (intersections[0] != null && intersections[1] != null) {
         if (sides[1] == Side.Positive) {
            positiveTriangles[0] = new Triangle(intersections[0],
                  triangle.get2(), intersections[1]);
            negativeTriangles[0] = new Triangle(triangle.get1(),
                  intersections[0], intersections[1]);
            negativeTriangles[1] = new Triangle(triangle.get1(),
                  intersections[1], triangle.get3());

         } else {
            negativeTriangles[0] = new Triangle(intersections[0],
                  triangle.get2(), intersections[1]);
            positiveTriangles[0] = new Triangle(triangle.get1(),
                  intersections[0], intersections[1]);
            positiveTriangles[1] = new Triangle(triangle.get1(),
                  intersections[1], triangle.get3());
         }
      } else if (intersections[1] != null && intersections[2] != null) {
         if (sides[2] == Side.Positive) {
            positiveTriangles[0] = new Triangle(intersections[1],
                  triangle.get3(), intersections[2]);
            negativeTriangles[0] = new Triangle(triangle.get1(),
                  triangle.get2(), intersections[1]);
            negativeTriangles[1] = new Triangle(triangle.get1(),
                  intersections[1], intersections[2]);

         } else {
            negativeTriangles[0] = new Triangle(intersections[1],
                  triangle.get3(), intersections[2]);
            positiveTriangles[0] = new Triangle(triangle.get1(),
                  triangle.get2(), intersections[1]);
            positiveTriangles[1] = new Triangle(triangle.get1(),
                  intersections[1], intersections[2]);
         }
      } else if (intersections[2] != null && intersections[0] != null) {
         if (sides[0] == Side.Positive) {
            positiveTriangles[0] = new Triangle(triangle.get1(),
                  intersections[0], intersections[2]);
            negativeTriangles[0] = new Triangle(intersections[0],
                  triangle.get2(), triangle.get3());
            negativeTriangles[1] = new Triangle(triangle.get3(),
                  intersections[2], intersections[0]);

         } else {
            negativeTriangles[0] = new Triangle(triangle.get1(),
                  intersections[0], intersections[2]);
            positiveTriangles[0] = new Triangle(intersections[0],
                  triangle.get2(), triangle.get3());
            positiveTriangles[1] = new Triangle(triangle.get3(),
                  intersections[2], intersections[0]);
         }
      }
   }

   @Override
   public String toString() {
      return "(" + normal.x + ", " + normal.y + ", " + normal.z + ", "
            + constant + ")";
   }

   @Override
   public boolean equals(Object obj) {
      if (!(obj instanceof Plane))
         return false;
      Plane plane = (Plane) obj;
      return normal.equals(plane.normal)
            && Math.abs(constant - plane.constant) < 0.0001;
   }
}
  • Zuletzt bearbeitet von Vertex am Sa, Jan 15, 2011 18:31, insgesamt einmal bearbeitet

Ana

BeitragMi, Jan 12, 2011 21:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hab mal den anfang angelesen und scheint ja recht interessant zu sein, selbst dafür das ich Grafik als solches nicht so spannend finde. Vielen dank dafür und viel erfolg damit Wink

Ich versteh zwar nicht viel von Rechtsangelegenheiten, aber hat eine Uni nicht die veröffentlichungsrechte für solche Sachen und nicht der Verfasser?

Lg Diana
Don't only practice your art,
but force your way into its secrets,
for it and knowledge
can raise human to divine

Firstdeathmaker

BeitragMi, Jan 12, 2011 22:18
Antworten mit Zitat
Benutzer-Profile anzeigen
Wenn die Uni dir als Hausaufgabe aufgibt, das zu programmieren, dann hast du noch lange keinen Vertrag mit denen geschlossen, dass du alle Rechte daran abgibst. Von daher kann man damit machen was man will. Problematisch wirds erst, wenn die Uni vielleicht im Jahr darauf die gleiche Aufgabe stellt, und man deine Lösung per im Internet finden kann. Aber illegal ist das nicht, ist schließlich dein code.

Zum Thema: Interressant, mich würde das Konzept interessieren wie du das auf mehrere Prozesse/Threads verteilst. Ich googel mal Wink
www.illusion-games.de
Space War 3 | Space Race | Galaxy on Fire | Razoon
Gewinner des BCC #57 User posted image

Hummelpups

BeitragDo, Jan 13, 2011 11:04
Antworten mit Zitat
Benutzer-Profile anzeigen
hm, kenne ich aber auch das man als Student seine Arbeiten nich
einfach so ins Netz stellen sollte :/ warum, weiß ich nicht.
blucode - webdesign - Ressource - NetzwerkSim
BlitzBasic 2D - BlitzMax - MaxGUI - Monkey - BlitzPlus

ozzi789

BeitragDo, Jan 13, 2011 16:46
Antworten mit Zitat
Benutzer-Profile anzeigen
Nice. thx
0x2B || ! 0x2B
C# | C++13 | Java 7 | PHP 5

Arrangemonk

BeitragFr, Jan 14, 2011 1:05
Antworten mit Zitat
Benutzer-Profile anzeigen
bsp nix gut für aufwendige szenen, esseiden, man arbeitet wie in der unreal engine mit static meshes, die mit dem bsp nur ausmachen, ob sie überhaupt sichtbar sind
ingeneur

Vertex

BeitragSa, Jan 15, 2011 18:34
Antworten mit Zitat
Benutzer-Profile anzeigen
In solchen Arbeiten steckt richtig viel Zeit drin und da finde ich es einfach zu schade, dass es sich einer mal durchliest und das wars. Wenn ich zu einem speziellen Thema was suche, bin ich auch immer froh eine PDF bei Google dazu zu finden und wenn jemand etwas zu BSP sucht, wird es vllt. auch nützlich finden. Zudem habe ich nichts unterschrieben, dass ich irgendwelche Rechte an die BA abtrete. Anders sieht das mit unseren Projektarbeiten in Zusammenarbeit mit unseren Praxispartnern aus. Da steckt dann auch Firmen-Know-How drin, wass natürlich nicht ohne Absprache veröffentlicht werden sollte.

Habe mal im ersten Post noch den Code für die Klasse Plane hinzugefügt. In der Arbeit ist zwar immer die Rede davon, dass ein Polygon (hier ausschließlich Dreiecke) an einer Ebene geteilt werden sollen, aber wie das funktioniert nicht (es ging ja auch hauptsächlich um das Parallelisieren). Im Code kann man sich das aber mal anschauen (Plane.intersects(Triangle ....))

Ciao Olli
vertex.dreamfall.at | GitHub

Neue Antwort erstellen


Übersicht Sonstiges Smalltalk

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group