Triedre trian; float tempo,incrtempo,angleX,angleY,t; Quat[] qua; Quat idq,idq0; void setup(){ t=0; size(400,400); trian=new Triedre(10); tempo=0.0f;incrtempo=0.15f; qua=new Quat[8]; idq=(new Quat(1,new Vecteur(0f,0,-1))); idq0=(new Quat(1,new Vecteur(0f,0,1))); idq.normalize(); idq0.normalize(); for(int i=0;i<8;i++){ qua[i]=new Quat(cos(i*PI/8.0f),new Vecteur(0,-sin(i*PI/8.0f),0)); } } void loop(){ push(); modifierparam(); push(); appliqueQuat(idq); trian.afficher(2); pop(); for(int i=0;i<8;i++){ push(); appliqueQuat(qua[i]); trian.afficher(2); pop(); for(float tto=0.1f;tto<0.9;tto+=0.05f){ push(); Quat s4=Quat.slerp(idq0,qua[i],tto); appliqueQuat(s4); trian.afficher(tto); pop(); push(); Quat sl=Quat.slerp(idq,qua[i],tto); appliqueQuat(sl); trian.afficher(tto); pop(); } } pop(); } void appliqueQuat(Quat q){ float[] ro=q.getValue(); rotate(ro[0],ro[1],ro[2],ro[3]); } //******************************************* //******************************************* //******************************************* void modifierparam(){ background(30); tempo+=incrtempo; angleX+=sin(tempo/10)/10; angleY+=cos(tempo/5)/20; translate(200,200,0); rotateX(angleX); rotateY(angleY); } // ******************************************* // ******************************************* // ******************************************* class Triedre{ Vecteur[] sommets; float u; public Triedre(float u){ this.u=u; sommets=new Vecteur[]{ new Vecteur(u,-u,-u), new Vecteur(u,u,u), new Vecteur(-u,-u,u), new Vecteur(-u,u,-u)}; } void afficherFace(int u,int d,int t,int r,int g,int b,float sc){ noStroke(); if(sc==2){ fill(150,150,255); }else{fill(r,g,b);} float s=0.8f+sc*0.8f; beginShape(TRIANGLES); vertex(sommets[u].x*s,sommets[u].y*s,sommets[u].z*s); vertex(sommets[d].x*s,sommets[d].y*s,sommets[d].z*s); fill(r/3,g/3,b/3,50); vertex(sommets[t].x*s,sommets[t].y*s,sommets[t].z*s); endShape(); } void afficher(float sca){ push(); translate(170,0,0); rotateX(tempo*2); rotateZ(tempo*3); afficherFace(0,1,2,100,0,255,sca); afficherFace(0,2,3,255,0,50,sca); afficherFace(0,1,3,225,225,150,sca); afficherFace(2,1,3,255,255,255,sca); afficherRepere(); pop(); } // ******************************************* // ******************************************* // ******************************************* void afficherRepere(){ beginShape(QUADS); fill(255,0,0,50);noStroke(); vertex(0,50,100); vertex(0,50,150); vertex(0,0,150); vertex(0,0,100); endShape(); } } //------------------------------------------------------------ // Quat class //------------------------------------------------------------ static class Quat { float w, x, y, z; Quat() { reset(); } Quat(float w, float x, float y, float z) { this.w = w; this.x = x; this.y = y; this.z = z; } Quat(float w, Vecteur v) { this.w = w; this.x = v.x; this.y = v.y; this.z = v.z; } Quat(Quat q) { set(q); } void reset() { w = 1.0f; x = 0.0f; y = 0.0f; z = 0.0f; } void set(float w, Vecteur v) { this.w = w; x = v.x; y = v.y; z = v.z; } void set(Quat q) { w = q.w; x = q.x; y = q.y; z = q.z; } float norme2() { float d2 = x * x + y * y + z * z + w * w; return d2; } float norme() { float d2 =(float)Math.sqrt( x * x + y * y + z * z + w * w); return d2; } void normalize() { float square = x * x + y * y + z * z + w * w; float dist = (square > 0.0f) ? (1.0f / (float) Math.sqrt(square)) : 1.0f; x *= dist; y *= dist; z *= dist; w *= dist; } void scale(float dist) { x *= dist; y *= dist; z *= dist; w *= dist; } static Quat mul(Quat q1, Quat q2) { Quat res = new Quat(); res.w = q1.w * q2.w - q1.x * q2.x - q1.y * q2.y - q1.z * q2.z; res.x = q1.w * q2.x + q1.x * q2.w + q1.y * q2.z - q1.z * q2.y; res.y = q1.w * q2.y + q1.y * q2.w + q1.z * q2.x - q1.x * q2.z; res.z = q1.w * q2.z + q1.z * q2.w + q1.x * q2.y - q1.y * q2.x; return res; } static Quat comb(Quat q1,float r1, Quat q2,float r2) { Quat res = new Quat(); res.w = q1.w *r1 + q2.w*r2; res.x = q1.x * r1+ q2.x * r2; res.y = q1.y * r1+ q2.y * r2; res.z = q1.z * r1+ q2.z * r2; return res; } float[] getValue() { // le quaternion doit etre norme; rend l'angle de la rotation et l'axe float[] res = new float[4]; res[0] = (float) Math.acos(w) * 2.0f; float nV= (float) Math.sqrt(x*x+y*y+z*z); if ( nV< 0.00001f) { res[1] = x ; res[2] = y; res[3] = z ; }else{ res[1] = x /nV; res[2] = y/nV ; res[3] = z/nV; } return res; } Quat conjugue(){ return new Quat(w,-x,-y,-z); } Quat inverse(){ float d=w*w+x*x+y*y+z*z; return new Quat(w/d,-x/d,-y/d,-z/d); } Vecteur tourner(Vecteur v){ Quat qv=new Quat(0.0f,v.x,v.y,v.z); Quat qc=this.conjugue(); Quat q1=Quat.mul(qv,qc); Quat q= Quat.mul(this,q1); return new Vecteur(q.x,q.y,q.z); } static float angleQ(Quat d, Quat a){ float angl=(float)Math.acos(d.w*a.w+d.x*a.x+d.y*a.y+d.z*a.z); return angl; } static Quat slerp(Quat d, Quat a,float t){ float rd,ra,cosangle,angle; d.normalize(); a.normalize(); cosangle=d.x*a.x+d.y*a.y+d.z*a.z; if(cosangle<0){ cosangle*=-1; a.scale(-1.0f); } angle=(float)Math.acos(cosangle); if(cosangle<0.999f){ float sina=(float)Math.sin(angle); rd=(float)Math.sin(angle*(1-t))/sina; ra=(float)Math.sin(angle*t)/sina; }else{ rd=1-t; ra=t; } Quat res= Quat.comb(d,rd,a,ra); return res; } static Quat slerp1(Quat d, Quat a,float t){ float rd,ra; d.normalize(); a.normalize(); float angle=(float)Math.acos(d.x*a.x+d.y*a.y+d.z*a.z); float sina=(float)Math.sin(angle); if(Math.abs(sina)>0.00001f){ rd=(float)Math.sin(angle*(1-t))/sina; ra=(float)Math.sin(angle*t)/sina; }else{ rd=0; ra=1; } Quat res= Quat.comb(d,rd,a,ra); return res; } Vecteur axe(){ return new Vecteur(x,y,z); } } //------------------------------------------------------- // classe Vecteur //------------------------------------------------------- static class Vecteur { float x, y, z; Vecteur() { } Vecteur(float x, float y, float z) { this.x = x; this.y = y; this.z = z; } void place(float xx, float yy, float zz) { this.x = xx; this.y = yy; this.z = zz; } Vecteur axe(){ return new Vecteur(x,y,z); } Vecteur normalize() { float length = length(); x /= length; y /= length; z /= length; return this; } Vecteur normalize(float fl) { float length = length(); x *=fl/ length; y *= fl/length; z *= fl/length; return this; } float length() { return (float) Math.sqrt(x * x + y * y + z * z); } Vecteur cross(Vecteur v2) { Vecteur res = new Vecteur(); res.x = y * v2.z - z * v2.y; res.y =z * v2.x - x * v2.z; res.z = x * v2.y - y * v2.x; return res; } static float dot(Vecteur v1, Vecteur v2) { return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; } float dot(Vecteur v1) { return v1.x * x + v1.y *y + v1.z *z; } Vecteur mul( float d) { Vecteur res = new Vecteur(); res.x =x * d; res.y = y * d; res.z = z * d; return res; } static Vecteur comb(float a,Vecteur v1,float b, Vecteur v2) { float rx =a* v1.x + b*v2.x; float ry =a* v1.y + b*v2.y; float rz =a* v1.z + b*v2.z; return new Vecteur(rx,ry,rz); } Vecteur ajouter(Vecteur v,float m){ Vecteur res=new Vecteur(x+v.x*m, y+v.y*m,z+v.z*m); return res; } static Vecteur symetric(Vecteur a,Vecteur b,Vecteur v){ Vecteur n=(a.cross(b)).normalize(); Vecteur vv=v.ajouter(n,(v.dot(n))*(-2)); return vv; } }