boolean premierefois,sourisrelachee,auto; int centreX,centreY,frame; float angleX,angleY,bangleX,bangleY,tempo,incrtempo,phi,psi,t,ka,kb,kas,kbs; Vecteur a ,b,c,aXc, bXc,aPb,uPv, aPbXc,coora,coorb,coorc,cooraPb, cooraXc,coorbXc,cooruPv,test,coorm,coorsm,coorssm,coorhssm, kaa,kbb,kaPb,kaXc,kbXc,kuPv,kaPbXc, coorka,coorkb,coorkaPb, coorkaXc,coorkbXc,coorkuPv; Quat qslerp,qbleu,qvert; Vecteur[] tamponArc,tamponArc1; Tirette barreU,barreV,barreS,barreT; Bouton button; String texte; BFont futura; //******************************************* //******************************************* //******************************************* void setup(){ futura = loadFont("GillSans.vlw.gz"); size(700,500); background(255); initier(); } void loop(){ clear(); push(); modifierparam(); figurer(); pop(); figurertexte(); fill(0); this.rect(550,0,200,450); barreT.actualiser(); t=barreT.getValeur(); barreU.actualiser(); c.x=barreU.getValeur(); barreV.actualiser(); c.y=barreV.getValeur(); barreS.actualiser(); c.z=barreS.getValeur(); c.normalize(); frame=button.actualiser(sourisrelachee); sourisrelachee=false; textFont(futura,24); fill(0); text(texte,20,480); } void mouseReleased(){ sourisrelachee=true; } public void keyPressed() { if (key == 'a') { auto = !auto; }; if (!auto) { if (key == UP) { c.x += 0.1; }; if (key == DOWN) { c.x -= 0.1; }; if (key == RIGHT) { c.z += 0.1; }; if (key == LEFT) { c.z -= 0.1; }; } } //******************************************* //******************************************* //******************************************* void initier(){ angleX=0; angleY=0; tempo=0; t=0.5f; incrtempo=1.0f/40; a=(new Vecteur(0.7f,0.9f,0.3f)).normalize(); b=(new Vecteur(0.9f,0,-0.8f)).normalize(); c=(new Vecteur(-0.1f,0.33f,1.3f)).normalize(); test=new Vecteur(1.4f,0.0f,0.0f); premierefois =true; sourisrelachee=false; auto=true; frame=1; centreX=width/2; centreY=height/2; barreU=new Tirette(630,250,60,-2.0f,2.2f,"cx= ",235, 20,futura,this); barreV=new Tirette(630,300,60,-1.89f,2.11f,"cy= ",235, 20,futura,this); barreS=new Tirette(630,350,60,-0.7f,2.1f,"cz= ",235, 20,futura,this); barreT=new Tirette(300,450,200,0.0f,1.0f,"t = ",155, 20,futura,this); button=new Bouton(550,400,40,20," next",this); texte=" "; } //******************************************* //******************************************* //******************************************* void modifierparam(){ if(tempo>6||tempo<0)incrtempo*=-1; tempo+=incrtempo; if(mousePressed && mouseX<500&&mouseY<400){ if(premierefois){centreX=mouseX;centreY=mouseY;} premierefois=false; bangleX=(-mouseY-170+centreX)/50.0f; bangleY=(-mouseX+centreY)/50.0f; angleX+=(bangleX-angleX)/10.0f; angleY+=(bangleY-angleY)/10.0f; } else { premierefois=true; } translate(-150,30,-4000); rotateX(2+angleX); rotateY(-3+angleY); } //******************************************* //******************************************* //******************************************* void figurer(){ //calculs preliminaires aXc=a.cross(c); bXc=b.cross(c); uPv=(aXc.ajouter(bXc,1)); aPb=a.ajouter(b,1); aPbXc=aPb.cross(c); //calcul de theta Quat q1=new Quat(a.dot(c),aXc); Quat q2=new Quat(b.dot(c),bXc); float theta=Quat.angleQ(q1,q2); float sintheta=sin(theta); ka=sin(theta*(1-t))/sintheta; kb=sin(theta*t)/sintheta; //coordonnées des lettrines coora=coorabs(a.mul(1550f)); coorb=coorabs(b.mul(1550f)); coorc=coorabs(c.mul(1550f)); cooraPb=coorabs(a.ajouter(b,1).mul(1550f)); cooraXc=coorabs(aXc.mul(1550f)); coorbXc=coorabs(bXc.mul(1550f)); cooruPv=coorabs(uPv.mul(1550f)); coorm=coorabs(test.mul(1.03f)); //etat 0: le quaternion q1 if(frame>0){ stroke(0); line(0,0,0,1500f*c.x,1500f*c.y,1500f*c.z); line(0,0,0,1500f*a.x,1500f*a.y,1500f*a.z); line(0,0,0,1500f*aXc.x,1500f*aXc.y,1500f*aXc.z); afficherPlan(a,aXc,0xFF0000); afficherPlan(c,aXc,0xFF0088);} //etat 1 le quaternion q2 if(frame>1){ stroke(0); line(0,0,0,1500f*b.x,1500f*b.y,1500f*b.z); line(0,0,0,1500f*bXc.x,1500f*bXc.y,1500f*bXc.z); afficherPlan(b,bXc,0x8800FF); afficherPlan(c,bXc,0x0000FF);} //etat 2 les vecteurs ka , kb et kaPb if(frame>2){ kaa=a.mul(ka); kbb=b.mul(kb); kaPb=kaa.ajouter(kbb,1); afficherPlan(kaa,kbb,0xFFFF00); stroke(255,0,0); line(0,0,0,1500f*kaPb.x,1500f*kaPb.y,1500f*kaPb.z); coorka=coorabs(kaa.mul(1550f)); coorkb=coorabs(kbb.mul(1550f)); coorkaPb=coorabs(kaPb.mul(1550f)); } //etat 3 le plan aXc bXc if(frame>3){ kaXc=aXc.mul(ka); kbXc=bXc.mul(kb); kuPv=kaXc.ajouter(kbXc,1); coorkuPv=coorabs(kuPv.mul(1550f)); coorkaXc=coorabs(kaXc.mul(1550f)); coorkbXc=coorabs(kbXc.mul(1550f)); afficherPlan(kaXc,kbXc,0x00FFFF); stroke(0); line(0,0,0,1500f*kuPv.x,1500f*kuPv.y,1500f*kuPv.z);} // etat 4 if(frame>4){ kaPbXc=kaPb.cross(c); afficherPlan(kaPbXc,c,0xFFFFFF); afficherPlan(kaPb,kaPbXc,0xFFFFFF); stroke(0); line(0,0,0,1500f*kaPbXc.x,1500f*kaPbXc.y,1500f*kaPbXc.z);} //etat 5 le test if(frame>5){ push(); translate(test.x*1500,test.y*1500,test.z*1500) ; fill(50,255,50,200); stroke(125); box(300); afficherRepere() ; noStroke(); pop(); brasetboite(q1,test,aXc.mul(aXc.dot(test)),255,0,0); brasetboite(q2,test,bXc.mul(bXc.dot(test)),0,0,255); Quat slerp=new Quat(kaPb.dot(c),kuPv); brasetboite(slerp,test,kuPv.mul(kuPv.dot(test)),250,250,250); } } // ******************************************* // ******************************************* // ******************************************* void afficherTriangle(Vecteur v,Vecteur w,int couleur){ int r,g,b; fill(couleur>>16,(couleur&0xFF00)>>8,couleur&0xFF,150); r=couleur>>16;g=(couleur&0xFF00)>>8;b=couleur&0xFF; beginShape(TRIANGLES); fill(r/6,g/6,b/6,220); vertex(0,0,0); fill(r,g,b,220); vertex(v.x,v.y,v.z); vertex(w.x,w.y,w.z); endShape(); } //******************************************* //******************************************* //******************************************* void afficherPlan(Vecteur v1,Vecteur w1,int couleur){ int r,g,b; Vecteur v=v1.mul(1500); Vecteur w=w1.mul(1500); r=couleur>>16;g=(couleur&0xFF00)>>8;b=couleur&0xFF; noStroke(); beginShape(QUADS); fill(r,g,b,220); vertex(v.x,v.y,v.z); vertex(v.x+w.x,v.y+w.y,v.z+w.z); fill(r/2,g/2,b/2,220); vertex(w.x,w.y,w.z); fill(r/6,g/6,b/6,220); vertex(0,0,0); endShape(); } //******************************************* //******************************************* //******************************************* void afficherSphere(){ for(int i=0;i<8;i++){ float co=(float)Math.cos(PI/8*i); float si=(float)Math.sin(PI/8*i); afficherCercle(co,0,si,2500.0f,0.0f,0.0f,0.0f); afficherCercle(0.0f,1.0f,0.0f,2500.0f*si,0.0f,2500.0f*co,0.0f); } } void afficherCercle(float nx,float ny,float nz,float r,float cx,float cy,float cz){ push(); noFill(); ellipseMode(CENTER_DIAMETER); translate(cx,cy,cz); rotateZ(atan2(ny,nx)); rotateY(atan2(sqrt(nx*nx+ny*ny),nz)); ellipse(0, 0, 2*r, 2*r); pop(); } //******************************************* //******************************************* //******************************************* Vecteur coorabs(Vecteur v) { float xa = objectX(v.x, v.y, v.z); float ya = objectY(v.x, v.y, v.z); float za = objectZ(v.x, v.y, v.z); return new Vecteur(xa, ya, za); } //******************************************* //******************************************* //******************************************* void afficherObjet(Quat q,Vecteur v){ push(); //appliquer le Quaternion q et dessiner v dans le nouveau repere; float[] a=q.getValue(); rotate(a[0] ,a[1] ,a[2],a[3]); translate(v.x,v.y,v.z); afficherRepere(); //fill(255,0,0,150); //box(500); pop(); } //******************************************* //******************************************* //******************************************* void figurertexte(){ if(frame>0 ){ afficherF("a" ,coora); afficherF("U=a^c",cooraXc); afficherF("c" ,coorc); texte="le quaternion p est defini par le produit scalaire a*c et le produit vectoriel U=a^c ..."; } if(frame>1 ){ afficherF("b" ,coorb); afficherF("V=b^c",coorbXc); texte="le quaternion q est defini par le produit scalaire b*c et le produit vectoriel V=b^c ..."; } if(frame>2 ){ kas=Math.round(ka*100.0f)/100.0f; kbs=Math.round(kb*100.0f)/100.0f; afficherF(kas+"*a+"+kbs+"*b",coorkaPb); afficherF(kas+"*a",coorka); afficherF(kbs+"*b",coorkb); texte="le vecteur somme de "+ kas+"*a et "+kbs+"*b , "+kas+"*a+"+kbs+"*b ... Vous pouvez modifiez ces vecteurs "; } if(frame>3 ){ afficherF(kas+"*U"+kbs+"*V",coorkuPv); texte="et le vecteur somme "+ kas+"U + "+kbs+" V, definissent le quaternion "+kas+"p + "+kbs+"q " ; } if(frame>4 ){ texte=" que l'on dessinne par son axe et ses deux plans de reflexion (en blanc)"; } if(frame>5 ){ texte=" Slerpons par le cube blanc du bleu au rouge. Ces trois cubes sont images du cube vert"; if(frame>6 ){ texte=" 'Next' pour repiquer au truc..... ";} } } //******************************************* //******************************************* //******************************************* void afficherRepere(){ stroke(255,0,0); line(0,0,0,500,0,0); stroke(0,255,0); line(0,0,0,0,500,0); stroke(0,0,255); line(0,0,0,0,0,500); } //******************************************* //******************************************* //******************************************* void afficherArc(){ noStroke(); int limite=(int)(tempo/abs(incrtempo)); beginShape(BApplet.QUADS);fill(0,0,255); for(int i=1;ixpos-10)&&(apple.mouseXy-10)&&(apple.mouseY 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){ 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); float rd=(float)Math.sin(angle*(1-t))/sina; float ra=(float)Math.sin(angle*t)/sina; Quat res= Quat.comb(d,rd,a,ra); return res; } static Quat slerp1(Quat d, Quat a,float tt){ d.normalize(); a.normalize(); float t=(tt-1)*(tt-1)*(tt-1)+1; float angle=(float)Math.acos(d.x*a.x+d.y*a.y+d.z*a.z); float sina=(float)Math.sin(angle); float rd=(float)Math.sin(angle*(1-t))/sina; float ra=(float)Math.sin(angle*t)/sina; Quat res= Quat.comb(d,rd,a,ra); return res; } Vecteur axe(){ return new Vecteur(x,y,z); } } //---------------------------------------------------------------------------------------------------- public class Bouton { int x,y,l,h,noFrame; String texte; BApplet gra; boolean sur; public Bouton(int x,int y, int l,int h,String texte,BApplet gra){ this.x=x; this.y=y; this.l=l; this.h=h; this.texte=texte; this.gra=gra; this.sur=false; this.noFrame=1; } int actualiser(boolean etatsouris){ sur=((gra.mouseX>x)&&(gra.mouseYy)&&(gra.mouseY7) {noFrame=1;}; }else{ if(sur ){dessin(255f,200f,200f); }else{ dessin(255f,255f,255f);} } return noFrame; } void dessin(float rr,float gg,float bb){ gra.fill(gg,gg,bb); gra.rect(x,y,3*l,h); gra.fill(rr,0,0); gra.beginShape(BApplet.TRIANGLES); gra.vertex(x,y); gra.vertex(l*0.4f+x,y+h/2); gra.vertex(x,y+h); gra.endShape(); gra.text(texte,x+l,y+h/2+5); } } //-------------------------------------------------------------------------------------------- //------------------------------------------------------- // classe Vecteur //------------------------------------------------------- public 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; } }