2010-10-07 31 views
2

J'essaie de faire tourner des vecteurs en utilisant des matrices, mais je me suis trompé.Comment faire pivoter des vecteurs en utilisant des matrices dans Processing?

Je pensais que tout ce que je devais faire était de créer une matrice de rotation et de la multiplier en un vecteur pour obtenir le vecteur pivoté.

Here vous pouvez voir un test simple que je l'ai fait à l'aide Processing:

processing text

Utilisez un pour incrémenter rotation et x/y/z aux changements de l'axe.

Et voici source:

PVector[] clone,face = {new PVector(50,0,50),new PVector(-50,0,50),new PVector(-50, 0, -50),new PVector(50, 0, -50)}; 
color faceC = color(255,0,0),cloneC = color(0,255,0); 
float angle = 90; 
PVector x = new PVector(1,0,0),y = new PVector(0,1,0),z = new PVector(0,0,1), axis = x; 
PFont ocr; 

void setup(){ 
    size(400,400,P3D); 
    strokeWeight(1.1610855);smooth(); 
    clone = rotateVerts(face,angle,axis); 
    ocr = loadFont("ocr.vlw"); 
} 
void draw(){ 
    background(255); 
    fill(0);textFont(ocr,10);text("a = increment rotation\nx/y/z = change axis\nrotation: " + angle + "\naxis: " + axis,10,10,200,200);fill(255); 
    translate(width*.5,height*.5); 
    rotateX(map(mouseY,height*.5,-height*.5,0,TWO_PI)); 
    rotateY(map(mouseX,0,width,0,TWO_PI)); 
    drawQuad(face,faceC); 
    drawQuad(clone,cloneC); 
    stroke(128,0,0);line(0,0,0,100,0,0);stroke(0,128,0);line(0,0,0,0,-100,0);stroke(0,0,128);line(0,0,0,0,0,100); 
} 
void keyPressed(){ 
    if(key == 'a') angle += 15; 
    if(angle > 360) angle -= 360; 
    if(key == 'x') axis = x; 
    if(key == 'y') axis = y; 
    if(key == 'z') axis = z; 
    clone = rotateVerts(face,angle,axis); 
} 
PVector[] rotateVerts(PVector[] verts,float angle,PVector axis){ 
    int vl = verts.length; 
    PVector[] clone = new PVector[vl]; 
    for(int i = 0; i<vl;i++) clone[i] = PVector.add(verts[i],new PVector()); 
    //rotate using a matrix 
    PMatrix3D rMat = new PMatrix3D(); 
    rMat.rotate(radians(angle),axis.x,axis.y,axis.z); 
    for(int i = 0; i<vl;i++) rMat.mult(clone[i],clone[i]); 
    return clone; 
} 
void drawQuad(PVector[] verts,color c){ 
    stroke(c); 
    beginShape(QUADS); 
    for(int i = 0 ; i < 4; i++) vertex(verts[i].x,verts[i].y,verts[i].z); 
    endShape(); 
} 

traitement est livré avec un PVector et PMatrix3D que je l'ai utilisé. Est-ce que je n'utilise pas PMatrix, il devrait être utilisé ou est-ce un bug? Des indices?

Répondre

3

C'est le coupable:

rMat.mult(clone[i],clone[i]); 

ce n'est pas sûr de le faire, parce que contrairement à C ou Java, la source change à mesure que l'opération se déroule.

changer la fin de la fonction:

PVector[] dst = new PVector[vl]; 
for(int i = 0; i<vl;i++) dst[i] = new PVector(); 
for(int i = 0; i<vl;i++) rMat.mult(clone[i],dst[i]); 
return dst; 

va résoudre le problème.

+0

C'est tout! woo hoo! Merci! –

3

Au lieu de PVector, vous pouvez également utiliser les classes de géométrie toxiclibs, qui contribuerait à simplifier la syntaxe tout un peu:

import toxi.geom.*; 

Vec3D[] rotateVerts(Vec3D[] verts, float angle, Vec3D axis){ 
    Vec3D[] clone = new Vec3D[verts.length]; 
    for(int i = 0; i<verts.length;i++) 
    clone[i] = verts[i].getRotatedAroundAxis(axis,angle); 
    return clone; 
} 

ou en utilisant une matrice pour faire la transform:

Vec3D[] rotateVerts(Vec3D[] verts, float angle, Vec3D axis){ 
    Matrix4x4 mat=new Matrix4x4(); 
    mat.rotateAroundAxis(axis,angle); 
    Vec3D[] clone = new Vec3D[verts.length]; 
    for(int i = 0; i<verts.length;i++) clone[i] = mat.applyTo(verts[i]); 
    return clone; 
} 

Ce dernier sera légèrement plus lent pour une simple rotation d'axe, mais il a plus de sens si vous faites d'autres transformations en même temps (par ex. Traduire etc.). En outre, dans les deux cas, le angle est supposé être en radians ...

Espérons que cela aide!

+0

Très bien! Je vous remercie! Je regardais à travers les docs (https://dev.postspectacular.com/docs/core/toxi/geom/Vec3D.html#headingXY()) et trouvé headingXY, XZ, YZ qui sont très pratiques. Si j'ai 4 sommets et un normal, comment puis-je obtenir la rotation sur l'axe Z? Si j'utilise les méthodes d'en-tête sur la normale, Z sera toujours le même, parce que j'ai affaire à 1 vertex. Des indices? –