Linear algebra question - how to rotate a figure around point

edited February 2018 in Questions about Code

Here is a sketch, in this sketch I tried to impement a rotation of a figure in 3 dimensions. The rotation should be around the point of mouse coordintates (please hold left button and move the mouse), but it don't work properly. I used following method - find mouse coordinates, calculate new point coodinates in new axis space, rotate all the points around this new center, return the translation of coordinates in normal coordinate space (hope the explanation makes sence). The question is - why my rotation is stange and not around the point?

Figure figure=new Figure();
PVector mus;
PVector dirx;
PVector diry;
float anglx;
float angly;
float locX=0;
float locY=0;


void setup()
{
  size(500,500,P3D);
  ortho();
  dirx=new PVector(0,0,0);
  diry=new PVector(0,0,0);
}



void draw()
{
  mus=new PVector(mouseX-pmouseX,mouseY-pmouseY,0);
  mus.setMag(0.04);

  dirx = new PVector(1,0,0);
  dirx.add(mus.copy());
  dirx.setMag(1);

  diry = new PVector(0,1,0);
  diry.add(mus.copy());
  diry.setMag(1);


  background(200);
  figure.display();
}



void mousePressed()
{
  locX=mouseX;
  locY=mouseY;
}



void mouseDragged()
{

  ellipse(locX,locY,5,5);

  float ax = figure.A.x-locX;
  float bx = figure.B.x-locX;
  float cx = figure.C.x-locX;

  float ay= figure.A.y-locY;
  float by= figure.B.y-locY;
  float cy= figure.C.y-locY;



  {// rotation by X axis

  float nax=(figure.A.x*1)+(0)+(0);
  float nay=(0)+(ay*dirx.x)+(figure.A.z*dirx.y);
  float naz=(0)+(ay*-dirx.y)+(figure.A.z*dirx.x);

  float nbx=(figure.B.x*1)+(0)+(0);
  float nby=(0)+(by*dirx.x)+(figure.B.z*dirx.y);
  float nbz=(0)+(by*-dirx.y)+(figure.B.z*dirx.x);

  float ncx=(figure.C.x*1)+(0)+(0);
  float ncy=(0)+(cy*dirx.x)+(figure.C.z*dirx.y);
  float ncz=(0)+(cy*-dirx.y)+(figure.C.z*dirx.x);


  figure.A.x=nax;
  figure.A.y=nay+locY;
  figure.A.z=naz;
  figure.B.x=nbx;
  figure.B.y=nby+locY;
  figure.B.z=nbz;
  figure.C.x=ncx;
  figure.C.y=ncy+locY;
  figure.C.z=ncz;
  }


  {// rotation by Y axis


  float nax=(ax*diry.y)+(0)+(figure.A.z*-diry.x);
  float nay=(0)+(figure.A.y*1)+(0);
  float naz=(ax*diry.x)+(0)+(figure.A.z*diry.y);

  float nbx=(bx*diry.y)+(0)+(figure.B.z*-diry.x);
  float nby=(0)+(figure.B.y*1)+(0);
  float nbz=(bx*diry.x)+(0)+(figure.B.z*diry.y);

  float ncx=(cx*diry.y)+(0)+(figure.C.z*-diry.x);
  float ncy=(0)+(figure.C.y*1)+(0);
  float ncz=(cx*diry.x)+(0)+(figure.C.z*diry.y);


  figure.A.x=nax+locX;
  figure.A.y=nay;
  figure.A.z=naz;
  figure.B.x=nbx+locX;
  figure.B.y=nby;
  figure.B.z=nbz;
  figure.C.x=ncx+locX;
  figure.C.y=ncy;
  figure.C.z=ncz;

  }
}




class Figure
{
  PVector A;
  PVector B;
  PVector C;


  Figure()
  {
    A=new PVector(random(width*2, width*4), random(width*2, width*4), random(width*2, width*4));
    B=new PVector(random(width*2, width*4), random(width*2, width*4), random(width*2, width*4));
    C=new PVector(random(width*2, width*4), random(width*2, width*4), random(width*2, width*4));
  }


  void display()
  {

    stroke(255, 150);
    fill(#73C1C1);

    beginShape(TRIANGLES);
    vertex(A.x, A.y, A.z);
    vertex(B.x, B.y, B.z);
    vertex(C.x, C.y, C.z);
    endShape();

    fill(255);
    text("AX="+A.x, 10, 20);
    text("AY="+A.y, 10, 40);
    text("AZ="+A.z, 10, 60);

    text("BX="+B.x, 10, 100);
    text("BY="+B.y, 10, 120);
    text("BZ="+B.z, 10, 140);

    text("CX="+B.x, 10, 180);
    text("CY="+B.y, 10, 200);
    text("CZ="+B.z, 10, 220);

    text(locX, 10, 260);
    text(locY, 10, 280);
  }
}

Answers

  • Hm... i dunno.....

    Why don’t you use rotateX and -Y and -Z ?

  • @Chrisir , I want to understand how rotation works in linear algebra, without using built-in functions of processing, so I can implement this approach in any programming language.

  • @jeremydouglass, thanks for the link.

  • just wanted to show this (not by me) which also has some trigonometry / angles / rotation for a 3D sphere when positioning each sphere. See constructor of the class - might be similar problem

    import peasy.*;
    
    PeasyCam cam;
    
    Node[] nodes;
    Node curr=null; 
    
    
    // -----------------------------------------------------
    
    void setup() {
      size(1200, 800, P3D);
    
      int NUM_PARTICLES = 350;
      nodes = new Node[NUM_PARTICLES];
    
      background(255); 
      cam = new PeasyCam(this, width);
    
      for (int i=0; i<NUM_PARTICLES; i++) {
        // Node n = new Node( PI, .3 );  // belt        
        Node n = new Node(i, map(i, 0, NUM_PARTICLES, -1, 1));   // full sphere 
        nodes[i] = n;
      }
    }
    
    void draw() {
      background(255);
    
      lights(); 
    
      pushMatrix();
      translate(0, 0, 0);
      fill(0, 244, 255);
      box(10);
      stroke(0, 0, 0, 20);
      popMatrix();
    
      for (int i=0; i<nodes.length; i++) {
        Node n = nodes[i];
        n.render();
      }
    
      cam.beginHUD();
      noLights(); 
      fill(0); 
      text("click a node to select (it appears red), then space key "
        +"to change Z; use peasycam outside sphere; use mousewheel to zoom etc.", 
        19, 19); 
      cam.endHUD();
    }
    
    //-----------------------------------------------
    
    void keyPressed() {
      if (curr!=null)
        curr.z+=6;
    }
    
    void mousePressed() {
    
      boolean done=false; 
      Node  old=curr;
    
      // search node 
      for (int i=0; i<nodes.length; i++) {
        Node n = nodes[i];
        if (dist(n.scrX, n.scrY, mouseX, mouseY)<6) {
          n.selected=!n.selected;
          curr=n;
          done = true; 
          break; // leave
        }
      }
      if (done&&old!=null&&(curr!=old)) {
        old.selected=false;
      }
    }
    
    // =====================================================================
    
    class Node extends PVector {
    
      float radius = 150;
    
      float theta, u;
      float scrX, scrY; 
      boolean selected= false; 
    
      color c = color(random(100, 255), 
        random(100, 255), 
        random(100, 255));
    
      // constructor
      Node(float Theta, float U) {
        theta = Theta;
    
        u = U;
    
        x = radius*cos(theta)*sqrt(1-(u*u));
        y = radius*sin(theta)*sqrt(1-(u*u));
        z = u*radius;
      }  // constructor
    
      void render() {
        pushMatrix();
        translate(x, y, z);
        noStroke(); 
        if (selected) 
          fill(255, 0, 0);
        else {
          // fill(0, 244, 0);
          fill(c);
        }
    
        sphere(10) ;
        scrX=screenX(0, 0, 0); 
        scrY=screenY(0, 0, 0); 
    
        popMatrix();
      }
    }//class
    //
    
Sign In or Register to comment.