float xr=0.0, yr=0.0; //x rotation and y rotation of field of view float L1=100,L2=100,L3=100; //lengths of the box float I1,I2,I3; //moments of inertia of the box float v0,v1,v2; //angular velocities boolean paused=true; Matrix currentReferenceVelocity; Matrix currentConfiguration; void setup() { size(700,700,P3D); //initializes display window stroke(0,0,0,200); fill(255,255,255); currentConfiguration=new Matrix(); currentReferenceVelocity=new Matrix(0); v0=0; v1=0.01; v2=0; currentReferenceVelocity.a[1][2]=v0; currentReferenceVelocity.a[2][1]=v0*-1; currentReferenceVelocity.a[0][2]=v1; currentReferenceVelocity.a[2][0]=v1*-1; currentReferenceVelocity.a[0][1]=v2; currentReferenceVelocity.a[1][0]=v2*-1; } void draw() { background(100,100,100); translate(350,350,0); rotateY(xr); rotateX(-1*yr); //changes field of view according to data obtained from mouse input stroke(0,0,0,100); line(-200,0,0,200,0,0); // draws x-axis line(0,-200,0,0,200,0); // draws y-axis line(0,0,-200,0,0,200); // draw z-axis updateConfiguration(); float[][] m=currentConfiguration.a; applyMatrix(m[0][0],m[0][1],m[0][2],0, m[1][0],m[1][1],m[1][2],0, m[2][0],m[2][1],m[2][2],0, 0,0,0,1); //moves box to current configuration stroke(0,0,0,150); strokeWeight(2); box(L1,L2,L3); } void updateConfiguration() { if(!paused){ Matrix currentVelocity=currentConfiguration.times(currentReferenceVelocity.times(currentConfiguration.inverse())); // v= Q v_ref Q^(-1) Matrix smallRotation=currentVelocity.exponential(); //converts an infinitesimal rotation to a genuine (small) rotation currentConfiguration=smallRotation.times(currentConfiguration); } } void mouseDragged() { xr+=0.015*(mouseX-pmouseX); yr+=0.015*(mouseY-pmouseY); } void keyTyped() { if(key=='p') { paused=!paused; } } class Matrix { float[][] a= new float[3][3]; public Matrix(float scalar) { for(int i=0;i<3;i++) { a[i][i]=scalar; for(int j=0;j