/**
*Alcys_Turtle_Logo_3D
*par Jacques Maire
*fait le 28 juillet 2012
*Une tortue qui deviendra interactive ?!
*/
import remixlab.proscene.*;
Scene scene;
Tortue tortue;
Programmes lesProgrammes;
int noProgramme, nbPrgm;
PFont tahoma;
Button2D button;
void setup() {
size(900, 700, P3D);
scene=new Scene(this);
scene.setGridIsDrawn(true);
scene.setAxisIsDrawn(true);
scene.disableKeyboardHandling();
scene.camera().setPosition(new PVector(0, 0, 12000));
scene.camera().setOrientation(new Quaternion(new PVector(1, 0, 0), 0.10));
frameRate(30);
nbPrgm=11;
noProgramme=0;
lesProgrammes=new Programmes();
tortue=new Tortue(lesProgrammes.programmes[noProgramme].liste);
tahoma = loadFont("Tahoma-21.vlw");
textFont(tahoma);
button = new ClickButton(scene, new PVector(50, 50), "TURTLE "+noProgramme, 21);
}
void draw() {
float ang=0.0005*millis();
background(0, 0, 30);
directionalLight(255, 255, 150, 0, -1, -1);
directionalLight(0, 155, 250, -1, -1, -1);
directionalLight(75*sq(1+sin(0.3*ang)), 0, 75*sq(2+sin(0.5*ang)), 0, 0.5, 0);
directionalLight( 0, 125*sq(cos(2*ang)), 100+155*sq(cos(2*ang)), -0.1, 0, 0.5);
directionalLight( 255, 230, 200, 1, 1, -1);
tortue.dessiner();
tortue.moteur();
fill(255);
button.display();
}
/**
* Button 2D.
* by Jean Pierre Charalambos.
*
* Base class of "2d buttons" that shows how simple is to implement
* a MouseGrabber which can enable complex mouse interactions.
*/
public class Button2D extends MouseGrabber {
String myText;
PFont myFont;
int myWidth;
int myHeight;
PVector position;
Button2D(Scene scn, PVector p, int fontSize) {
this(scn, p, "", fontSize);
}
Button2D(Scene scn, PVector p, String t, int fontSize) {
super(scn);
position = p;
myText = t;
textFont( tahoma, 21);
textMode(SCREEN);
textAlign(CENTER);
setText(t);
}
void setText(String text) {
myText = text;
myWidth = (int) textWidth(myText);
myHeight = (int) (textAscent() + textDescent());
}
void display() {
pushStyle();
if (grabsMouse())
fill(255, 0, 0);
else
fill(255);
text(myText, position.x, position.y, myWidth, myHeight);
popStyle();
}
void checkIfGrabsMouse(int x, int y, Camera camera) {
// Rectangular activation area
setGrabsMouse( (position.x <= x ) && ( x <= position.x + myWidth ) && (position.y <= y ) && ( y <= position.y + myHeight ) );
}
}
//---------------------------------------------------------------------
public class ClickButton extends Button2D {
boolean addBox;
public ClickButton(Scene scn, PVector p, String t, int fontSize) {
super(scn, p, t, fontSize);
}
void mouseClicked(Scene.Button button, int numberOfClicks, Camera camera) {
noProgramme=(int)(noProgramme+1)%nbPrgm;
tortue=new Tortue(lesProgrammes.programmes[noProgramme].liste);
setText("TURTLE "+noProgramme);
scene.camera().setPosition(new PVector(0, 0, 12000));
scene.camera().setOrientation(new Quaternion(new PVector(1, 0, 0), 0.1));
}
}
abstract class Instruction {
public abstract void dessiner();
public abstract String getNom();
}
//-------------------------------------------------
class Tourne extends Instruction
{
PVector pos, dir;
float angle;
int compteur, compte;
Quaternion q;
String nom;
Tourne( PVector p, PVector d, float a) {
pos=p;
dir=d;
angle=a;
compteur=floor(angle/0.1);
q=new Quaternion(dir, angle/compteur);
nom="tourne";
}
String getNom() {
return nom;
}
void dessiner() {
compte++;
//println("tourne "+compte+" "+compteur);
if (compte>=compteur+1) {
tortue.finInstruction=true;
compte=0;
}
else {
tortue.repere1.setTranslation(PVector.sub(pos, q.rotate(pos)));
tortue.repere1.setRotation(q);
tortue.positions.add(tortue.repere1.position());
tortue.orientations.add(tortue.repere1.orientation());
tortue.repere.setPosition((PVector)tortue.positions.get(tortue.positions.size()-1));
tortue.repere.setOrientation((Quaternion)tortue.orientations.get(tortue.orientations.size()-1));
}
}
}
//---------------------------------------------
class Avance extends Instruction
{
public String nom;
PVector vecInc, vecBut;
int compteur, compte;
public Avance( PVector but) {
this.vecBut=new PVector (but.x, but.y, but.z);
this.nom="avance";
this.compteur=(int)Math.ceil(vecBut.mag()/50);
this.vecInc= (compteur>0)? PVector.mult(vecBut, 1.0/compteur) : vecBut;
compte=0;
}
//
String getNom() {
return nom;
}
//
public void dessiner() {
//println(nom);
compte++;
if ( compte>=compteur +1) {
tortue.finInstruction=true;
compte=0;
}
else {
tortue.repere1.setTranslation(vecInc);
tortue.positions.add(tortue.repere1.position());
tortue.orientations.add(tortue.repere.orientation());
tortue.repere.setPosition((PVector)tortue.positions.get(tortue.positions.size()-1));
}
}
}
//-----------------------------------------------
class Ouvre extends Instruction {
String nom;
public Ouvre() {
this.nom="ouvre";
}
String getNom() {
return nom;
}
public void dessiner() {
//println(nom);
tortue.finInstruction=true;
}
}
//---------------------------------------------
class Ferme extends Instruction {
String nom;
public Ferme() {
this.nom="ferme";
}
String getNom() {
return nom;
}
public void dessiner() {
//println(nom);
String lnom;
int bee=0;//nombre de parentheses "ouvre" rencontrées dans la remontée
int clos=1;//nombre de parentheses "ferme" rencontrées dans la remontée
int lign= tortue.ligne;
do {
lign--;
if (tortue.listing[lign].getNom() == "ouvre") bee++;
if (tortue.listing[lign].getNom()=="ferme") clos++;
}
while (bee != clos);//on remonte dans le listing pour trouver autant d'"ouvre" que de "ferme"
tortue.ligne=lign-1;
tortue.finInstruction=false;
}
}
//--------------------------------------
class Repete extends Instruction {
String nom;
int compteur, compteur0;
public Repete( int compteur) {
this.compteur=compteur;
this.compteur0=compteur;
this.nom="repete";
}
String getNom() {
return nom;
}
//
public void dessiner() {
if (compteur==0) {
int bee=0;
int clos=0;
int lign= tortue.ligne;
do {
lign++;
if (tortue.listing[lign].getNom()=="ouvre") bee++;
if (tortue.listing[lign].getNom()=="ferme") clos++;
}
while (bee != clos);
tortue.ligne=lign;
compteur=compteur0;//remise en etat
}
else {
compteur--;
}
tortue.finInstruction=true;
}
}
//-------------------------------------------
class GoTo extends Instruction {
String nom;
int lign;
GoTo( int lign) {
this.lign=lign;
this.nom="goto";
}
void dessiner() {
tortue.ligne=lign-1;
tortue.finInstruction=true;
}
String getNom() {
return nom;
}
}
class Listing {
Instruction[] liste;
Listing(Instruction[] li) {
liste=li;
};
}
//----------------------------------------
class Programmes {
Listing[] programmes;
Programmes() {
programmes=new Listing[nbPrgm];
Instruction[] inst0= {
new Repete(8),
new Ouvre(),
new Avance(new PVector(0, 0, 2000)),
new Tourne(new PVector(0, 0, 0), new PVector(0, 1, 0), PI/4),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), 0.5*PI),
new Avance(new PVector(0, 0, 1000)),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), 1.5*PI),
new Avance(new PVector(0, 0, 1000)),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), 1.5*PI),
new Avance(new PVector(0, 0, 1000)),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), 0.5*PI),
new Ferme()
};
programmes[0]= new Listing(inst0);
Instruction[] inst1= {
new Repete(3),
new Ouvre(),
new Avance(new PVector(0, 3000, 0)),
new Tourne(new PVector(0, 1000, 0), new PVector(1, 0, 0), PI),
new Tourne(new PVector(0, 1000, 0), new PVector(1, 1, 0), PI/2),
new Ferme()
};
programmes[1]= new Listing(inst1);
Instruction[] inst2= {
new Repete(20),
new Ouvre(),
new Avance(new PVector(0, 3000, 0)),
new Tourne(new PVector(0, 1000, 0), new PVector(1, 0, 0), PI),
new Tourne(new PVector(0, 1000, 0), new PVector(1, 1, 0), PI/2),
new Tourne(new PVector(0, 0, -1000), new PVector(1, -2, 1), PI/2),
new Ferme()
};
programmes[2]= new Listing(inst2);
Instruction[] inst3= {
new Repete(4),
new Ouvre(),
new Avance(new PVector(0, 3000, 0)),
new Tourne(new PVector(0, 1000, 0), new PVector(1, 0, 0), PI),
new Tourne(new PVector(0, 1000, 0), new PVector(1, 1, 0), PI/2),
new Tourne(new PVector(0, 0, -1000), new PVector(1, -2, 1), PI/2),
new Repete(2),
new Ouvre(),
new Avance(new PVector(0, 3000, 0)),
new Tourne(new PVector(0, 1000, 0), new PVector(1, 0, 0), PI),
new Tourne(new PVector(0, 1000, 0), new PVector(1, 1, 0), PI/2),
new Ferme(),
new Ferme()
};
programmes[3]= new Listing(inst3);
Instruction[] inst4= {
new Repete(3),
new Ouvre(),
new Avance(new PVector(0, 3000, 0)),
new Tourne(new PVector(0, -3000, 0), new PVector(1, 0, 0), PI/3),
new Avance(new PVector(0, 0, 3000)),
new Tourne(new PVector(0, 0, -3000), new PVector(1, 0, 0), PI/3),
new Ferme()
};
programmes[4]= new Listing(inst4);
Instruction[] inst5={
new Repete(8),
new Ouvre(),
new Avance(new PVector(0, 0, 900)),
// new Tourne(new PVector(0, 0, 0), new PVector(0, 1, 0), 0.5*PI),
new Tourne(new PVector(1000, 0, 0), new PVector(0, 1, 0), PI),
new Tourne(new PVector(0, 1000, 0), new PVector(-1, 0, 0), PI),
new Avance(new PVector(0, 0, 900)),
new Tourne( new PVector(-1000, 0, 0), new PVector(0, -1, 0), 1.5*PI),
new Ferme()
};
programmes[5]=new Listing(inst5 );
Instruction[] inst6={
new Repete(16),
new Ouvre(),
new Avance(new PVector(0, 0, 900)),
// new Tourne(new PVector(0, 0, 0), new PVector(0, 1, 0), 0.5*PI),
new Tourne(new PVector(1000, 0, 0), new PVector(0, 1, 0), 0.5*PI),
new Avance(new PVector(0, 0, 900)),
new Tourne(new PVector(0, 1000, 0), new PVector(-1, 0, 0), 9.0*PI/6.0),
new Avance(new PVector(0, 0, 1900)),
new Ferme()
};
programmes[6]=new Listing(inst6 );
Instruction[] inst7= {
new Repete(8),
new Ouvre(),
new Avance(new PVector(0, 0, 3000)),
new Tourne(new PVector(0, 0, 0), new PVector(1, -1, 0), PI/4),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), 0.5*PI),
new Avance(new PVector(0, 0, 4000)),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), 1.5*PI),
new Avance(new PVector(0, 0,3000)),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), 1.5*PI),
new Avance(new PVector(0, 0,4000)),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), 0.5*PI),
new Ferme()
};
programmes[7]= new Listing(inst7);
Instruction[] inst8= {
new Repete(8),
new Ouvre(),
new Avance(new PVector(0, 0, 2000)),
new Tourne(new PVector(0, 0, 0), new PVector(0, 1, 0), PI/4),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), 0.5*PI),
new Avance(new PVector(0, 0, 1000)),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), 1.5*PI),
new Avance(new PVector(0, 0, 1000)),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), 1.5*PI),
new Avance(new PVector(0, 0, 1000)),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), 0.5*PI),
new Tourne(new PVector(0, 2000, 2000), new PVector(1, 0, 0), 0.5*PI),
new Repete(8),
new Ouvre(),
new Avance(new PVector(0, 0, -1000)),
new Tourne(new PVector(0, 200, 0), new PVector(1, 0, 0), PI/4),
new Tourne(new PVector(0, 200, 0), new PVector(1, 1, 0), -PI/4),
new Ferme(),
new Tourne(new PVector(0, 2000, 2000), new PVector(-1, 0, 0), 0.5*PI),
new Ferme()
};
programmes[8]= new Listing(inst8);
Instruction[] inst9= {
new Repete(8),
new Ouvre(),
new Avance(new PVector(0, 0, 3000)),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), PI/8),
new Tourne(new PVector(0, 0, 0), new PVector(0, 1, 0), PI/2),
new Avance(new PVector(0, 0, 3000)),
new Tourne(new PVector(0, 0, 0), new PVector(0, 1, 0), PI/2),
new Avance(new PVector(0, 0, 3000)),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), PI/8),
new Ferme()
};
programmes[9]= new Listing(inst9);
Instruction[] inst10= {
new Repete(8),
new Ouvre(),
new Tourne(new PVector(0, 0, 0), new PVector(1, 0, 0), PI/4),
new Avance(new PVector(0, 0, 1500)),
new Tourne(new PVector(0, 750, 0), new PVector(1, 0, 0), TWO_PI),
new Tourne(new PVector(750, 0, 0), new PVector(0, 1, 0), TWO_PI),
new Tourne(new PVector(-750, 0, 0), new PVector(0, 1, 0), TWO_PI),
new Avance(new PVector(0, 0, 1500)),
new Ferme()
};
programmes[10]= new Listing(inst10);
}
}
class Tortue {
ArrayList positions;
ArrayList orientations;
InteractiveFrame repere, repere1;
Instruction[] listing;
boolean finInstruction;
int ligne;
Tortue(Instruction[] prgm) {
listing=prgm;
finInstruction=false;
ligne=0;
repere=new InteractiveFrame(scene);
repere1=new InteractiveFrame(scene);
repere1.setReferenceFrame(repere);
repere.setPosition(new PVector(0, 0, 0));
repere.setOrientation(new Quaternion(new PVector(0, 0, 1), 0));
repere1.setTranslation(new PVector(0, 0, 0));
repere1.setRotation(new Quaternion(new PVector(0, 0, 1), 0));
positions=new ArrayList();
orientations=new ArrayList();
positions.add(repere.position());
orientations.add(repere.orientation());
}
void dessiner() {
float c=200;
noStroke();
fill(255);
PVector u, v, w, t, u1, v1, w1, t1;
repere.setPosition((PVector)positions.get(0));
repere.setOrientation((Quaternion)orientations.get(0));
pushMatrix();
repere.applyTransformation();
scene.drawAxis(1000);
u=repere.inverseCoordinatesOf(new PVector(-c, -c, 0));
v=repere.inverseCoordinatesOf(new PVector(-c, c, 0));
w=repere.inverseCoordinatesOf(new PVector(c, c, 0));
t=repere.inverseCoordinatesOf(new PVector(c, -c, 0));
popMatrix();
for (int i=1;i<positions.size();i++) {
repere.setPosition((PVector)positions.get(i));
repere.setOrientation((Quaternion)orientations.get(i));
pushMatrix();
repere.applyTransformation();
if (i==positions.size()-1) {
scene.drawAxis(2000);
fill(255, 0, 0);
sphere(300);
fill(125, 125, 200);
}
u1=repere.inverseCoordinatesOf(new PVector(-c, -c, 0));
v1=repere.inverseCoordinatesOf(new PVector(-c, c, 0));
w1=repere.inverseCoordinatesOf(new PVector(c, c, 0));
t1=repere.inverseCoordinatesOf(new PVector(c, -c, 0));
popMatrix();
beginShape(QUAD_STRIP);
vertex(u.x, u.y, u.z);
vertex(u1.x, u1.y, u1.z);
vertex(v.x, v.y, v.z);
vertex(v1.x, v1.y, v1.z);
vertex(w.x, w.y, w.z);
vertex(w1.x, w1.y, w1.z);
vertex(t.x, t.y, t.z);
vertex(t1.x, t1.y, t1.z);
vertex(u.x, u.y, u.z);
vertex(u1.x, u1.y, u1.z);
endShape();
u=u1.get();
v=v1.get();
w=w1.get();
t=t1.get();
}
}
void moteur() {
if (ligne<listing.length-1) {
if (finInstruction )
{
ligne++;
finInstruction=false;
listing[ligne].dessiner();
}
else {
listing[ligne].dessiner();
}
}
}
}