Willkommen auf unserem Seminar-Blog

Immer auf dem aktuellen Stand bleiben

Dieser Seminar-Blog befindet sich noch im Aufbau und wird in den kommenden Tagen entsprechend verfeinert.

Member Login

Lost your password?

Registration is closed

Sorry, you are not allowed to register by yourself on this site!

You must either be invited by one of our team member or request an invitation by email at viad.info {at} zhdk {dot} ch.

3D Math Matrizen

Matrizen

Mit Matrizen kann man alle Transformationen(Translation, Rotation, Skalierung) beschreiben. Für 3d Matrizen verwenden wir 4x4 Matrizen. Wenn man nur Rotationen berechnen will würden auch 3x3 Matrizen genügen. Processing arbeitet aber mit 4x4 Matrizen und hat hierfür eine Klasse(nicht offiziell Dokumentiert): PMatrix3D Processing beziehungsweise OpenGL arbeitet intern mit Matrizen. Ihr hab dies schon genutzt wenn ihr mit 'pushMatrix/popMatrix', 'rotate', 'translate' oder 'scale' gearbeitet habt. Dies habt ihr aber immer nur für die Grafik-Ausgabe gebraucht, wenn ihr zum Beispiel genau wissen wollt, wo ein Vektor nach dieser Transformation war, konntet ihr dies nicht ausfindig machen. Mit den folgenden Tipps seid ihr aber in der Lage dies zu bewerkstelligen. Mathematische Grundlagen der 3D Grafik, David Nadlinger Transformationen akkumulieren: Matrizen beinhalten Transformationen, das können Translationen, Rotationen oder Skalierungen sein. Diese Transformationen können alle zusammen kumuliert werden. Matrizen sind aber nicht Kommutativ verwendbar, sprich man muss auf die Reihenfolge der Operationen achten. Es macht einen Unterschied ob man zuerst rotiert und dann verschiebt, anstatt wie umgekehrt.
PMatrix3D xform = new PMatrix3D();

xform.reset();
xform.rotate(radians(45),0,0,1); // rotation um die Z-Achse
xform.translate(50,0,0);         // verschiebung
Mit dem Befehl 'applyMatrix' kann man diese Transformation an Processing übergeben.
applyMatrix(xform);

transform

Download Beispiel Vektor Transformation berechnen: Wenn man Vektor-Transformationen explizit berechnen will nutzt man die PMatrix3D Methode 'mult'. Sie multipliziert den Vektor mit der Matrize und liefert den transformierten Vektor zurück.'
PVector p1 = new PVector(0, 0, 0);
PVector p2 = new PVector(100, 0, 0);
PVector p3 = new PVector(100, 100, 0);

p1Res = xform.mult(p1, null);
p2Res = xform.mult(p2, null);
p3Res = xform.mult(p3, null);
Nur ein bisschen anders geschrieben, aber das Gleiche:
xform.mult(p1, p1Res);
xform.mult(p2, p1Res);
xform.mult(p3, p1Res);
Download Beispiel Inverse Matrize benutzen: Die Transformation in einer Matrize kann auch Umgekehrt, Invertiert werden. Dafür nutzt man die Methode 'invert'.
xform.rotate(radians(angle), 0, 0, 1);
xform.translate(trans.x, trans.y, trans.z);

invXForm = xform.get();
invXForm.invert();
Download Beispiel Transformations Matrize für ein gegebenes Lagesystem finden: Es gibt Fälle da will man die Transformations-Matrize wissen durch welche ein Objekt verändert wurde. Zum Beispiel wollt ihr auf eine Fläche schreiben oder ein Objekte darauf platzieren, aber ihr wisst die Transformations-Matrize nicht. Dafür kennt ihr die Eck-Punkte der Fläche. Damit könnt ihr die Ebene der Fläche errechnen und damit eure gesucht Transformations-Matrize erstellen. Die Funktion 'getCoordSys' errechnet euch aus der Ebene(definiert durch p1,p2,p3) 3 Vektoren, welche die Achsen eines Koordinatensystems beschreiben.
void getCoordSys(PVector p1, PVector p2, PVector p3,
                 PVector xAxis,PVector yAxis,PVector zAxis)
{
  PVector u = PVector.sub(p2, p1);
  PVector v = PVector.sub(p3, p1);
  
  u.normalize();
  v.normalize();

  xAxis.set(u);

  zAxis.set(PVector.cross(u,v,null));
  zAxis.normalize();

  yAxis.set(PVector.cross(zAxis,xAxis,null));
  yAxis.normalize();
}
Anhand der Achsen eines Koordinatensystem kann nun eine Transformations-Matrix erzeugt werden.
PMatrix3D getRotationMat(PVector p1, PVector p2, PVector p3)
{
  PVector xAxis = new PVector();
  PVector yAxis = new PVector();
  PVector zAxis = new PVector();
  
  // calc a clean coordsystem out of the triangle, based on the x-axis(p1-p2)
  getCoordSys(p1, p2, p3,
              xAxis,yAxis,zAxis);
            
  PMatrix3D mat = new PMatrix3D();
  mat.translate(p1.x,p1.y,p1.z);  

  mat.m00 = xAxis.x;
  mat.m10 = xAxis.y;
  mat.m20 = xAxis.z;

  mat.m01 = yAxis.x;
  mat.m11 = yAxis.y;
  mat.m21 = yAxis.z;

  mat.m02 = zAxis.x;
  mat.m12 = zAxis.y;
  mat.m22 = zAxis.z;

  return mat;
}

transform

Download Beispiel

Aufgaben

Berechne die Positionen eines Uhrzeigers. Zeichne an jeder Stunden-Position eine Kugel. Das Ziffernblatt hat einen Radius von 70 Einheiten und befindet sich in der folgenden Ebene:
PVector p1 = new PVector(0, 0, 0);
PVector p2 = new PVector(100, 0, 0); 
PVector p3 = new PVector(100, 100, 100); 
import peasy.*;

PeasyCam cam;

PMatrix3D objXform;
PVector p1 = new PVector(0, 0, 0);
PVector p2 = new PVector(100, 50, 0); 
PVector p3 = new PVector(100, 100, 100); 

float radius = 70;

void setup()
{
  size(800, 600, P3D);
  cam = new PeasyCam(this, 1500);
  cam.setMinimumDistance(5);
  cam.setMaximumDistance(5000);
  perspective(radians(25), (float)width / (float)height, .1, 5000);
  
  // calc   
  objXform = getRotationMat(p1, p2, p3);  
}

void draw()
{
  background(0);

  coordSys(200);
  
  stroke(255,255,0);
   
  // ref obj
  pushMatrix();
   
  applyMatrix(objXform); 
  
  coordSys(40); 
  ellipse(0,0,radius*2,radius*2);
  
  stroke(100,255,0);
  for(int i=0;i < 12;i++)
  {
    pushMatrix();
    
    rotate(2*PI / 12.0 * i);
    translate(0,-radius,0);
    sphere(5);
    
    popMatrix();
  }
  
  popMatrix();

}

void coordSys(float size)
{
  pushStyle();

  stroke(255, 0, 0);
  line(0, 0, 0, 
  size, 0, 0);

  stroke(0, 255, 0);
  line(0, 0, 0, 
  0, size, 0);

  stroke(0, 0, 255);
  line(0, 0, 0, 
  0, 0, size);

  popStyle();
}

PVector getPlaneNormal(PVector p1, PVector p2, PVector p3)
{
  PVector u = PVector.sub(p2, p1);
  PVector v = PVector.sub(p3, p1);
  
  u.normalize();
  v.normalize();

  PVector ret = PVector.cross(u,v,null);
  ret.normalize();
  return ret;
}

void getCoordSys(PVector p1, PVector p2, PVector p3,
                 PVector xAxis,PVector yAxis,PVector zAxis)
{
  PVector u = PVector.sub(p2, p1);
  PVector v = PVector.sub(p3, p1);
  
  u.normalize();
  v.normalize();

  xAxis.set(u);

  zAxis.set(PVector.cross(u,v,null));
  zAxis.normalize();

  yAxis.set(PVector.cross(zAxis,xAxis,null));
  yAxis.normalize();
}

PMatrix3D getRotationMat(PVector p1, PVector p2, PVector p3)
{
  PVector xAxis = new PVector();
  PVector yAxis = new PVector();
  PVector zAxis = new PVector();
  
  // calc a clean coordsystem out of the triangle, based on the x-axis(p1-p2)
  getCoordSys(p1, p2, p3,
              xAxis,yAxis,zAxis);
            
  PMatrix3D mat = new PMatrix3D();
  mat.translate(p1.x,p1.y,p1.z);  

  mat.m00 = xAxis.x;
  mat.m10 = xAxis.y;
  mat.m20 = xAxis.z;

  mat.m01 = yAxis.x;
  mat.m11 = yAxis.y;
  mat.m21 = yAxis.z;

  mat.m02 = zAxis.x;
  mat.m12 = zAxis.y;
  mat.m22 = zAxis.z;

  return mat;
}