package tinyray.language;
import java.util.Iterator;
/**
* Die Klasse GlutCCode implementiert einen Besucher (Visitor),
* der aus einem Syntaxbaum, der mit Hilfe von LanguageKit erzeugt ist,
* einen Glut/OpenGL-Code in der Sprache C erzeugt.
*/
public class GlutCCode implements Visitor<String, String> {
// Der Zeilenumbruch.
private final static String NEWLINE = "\r\n";
// Die Einrückung.
private final static String INDENT = "\t";
// Zeigt an, ob die lokalen oder die globalen Parameter
// ausgegeben werden sollen.
private boolean localParameters;
// Die globalen Parameter.
private Defaults defaults;
// Der aktuelle Index für das parallele Sonnenlicht.
private int lightIndex;
/**
* Initialisiert den GlutCCode-Besucher.
* Die globalen Parameter werden eingestellt mit:
* color = [0.5, 0.5, 0.5];
* ambient = [0.1, 0.1, 0.1];
* specular = 0.5;
* shininess = 1000.0;
* mirror = 0.4 (wird aber nicht benutzt).
*/
public GlutCCode() {
this.localParameters = true;
// Setzt globale Parameter
this.defaults = new Defaults();
// color = [0.5, 0.5, 0.5]
this.defaults.parameters.visitables.add(new Vector(0.5, 0.5, 0.5));
// ambient = [0.1, 0.1, 0.1]
this.defaults.parameters.visitables.add(new Vector(0.1, 0.1, 0.1));
// specular = 0.5
this.defaults.parameters.visitables.add(new Real(0.5));
// shininess = 1000.0
this.defaults.parameters.visitables.add(new Real(1000.0));
// mirror = 0.4
this.defaults.parameters.visitables.add(new Real(0.4));
// Setzt den Sonnenlichtindex.
this.lightIndex = 0;
}
/**
* Besucht einen besuchbaren Tinyray-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param tinyray Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Tinyray tinyray, String indent) {
String result = "";
// Kommentar
result += indent;
result += "/*";
result += NEWLINE + indent;
result += " * Automatisch generierter Glut/OpenGL-C-Code.";
result += NEWLINE + indent;
result += " * Kompilieren unter Linux: gcc -lglut <Dateiname>";
result += NEWLINE + indent;
result += " * Herkunft: Tinyray (http://www.stefan-baur.de)";
result += NEWLINE + indent;
result += " */";
result += NEWLINE;
// Includes und Makros
result += NEWLINE + indent;
result += "#include <stdlib.h>";
result += NEWLINE + indent;
result += "#include <GL/glut.h>";
result += NEWLINE;
result += NEWLINE + indent;
result += "#define WIDTH 600";
result += NEWLINE + indent;
result += "#define HEIGHT 400";
result += NEWLINE;
// Globale Variablen
result += NEWLINE + indent;
result += "// Globle Variablen für die Kamerabewegung";
result += NEWLINE + indent;
result += "int mousemotion = 0;";
result += NEWLINE + indent;
result += "int mousex = 0;";
result += NEWLINE + indent;
result += "int mousey = 0;";
result += NEWLINE + indent;
result += "GLfloat anglex = 0.0f;";
result += NEWLINE + indent;
result += "GLfloat angley = 0.0f;";
result += NEWLINE;
// Aktion Quit
result += NEWLINE + indent;
result += "// Programm verlassen";
result += NEWLINE + indent;
result += "void actionQuit()";
result += NEWLINE + indent;
result += "{";
result += NEWLINE + indent + INDENT;
result += "exit(EXIT_SUCCESS);";
result += NEWLINE + indent;
result += "}";
result += NEWLINE;
// Aktion Init
result += NEWLINE + indent;
result += "// Initialisierung: Kameraposition";
result += NEWLINE + indent;
result += "void actionInit()";
result += NEWLINE + indent;
result += "{";
result += NEWLINE + indent + INDENT;
result += "mousex = 0;";
result += NEWLINE + indent + INDENT;
result += "mousey = 0;";
result += NEWLINE + indent + INDENT;
result += "anglex = 0.0f;";
result += NEWLINE + indent + INDENT;
result += "angley = 0.0f;";
result += NEWLINE + indent;
result += "}";
result += NEWLINE;
// Aktion Licht ein/aus
result += NEWLINE + indent;
result += "// Licht ein/aus";
result += NEWLINE + indent;
result += "void actionToggleLighting()";
result += NEWLINE + indent;
result += "{";
result += NEWLINE + indent + INDENT;
result += "if (glIsEnabled(GL_LIGHTING))";
result += NEWLINE + indent + INDENT;
result += "{";
result += NEWLINE + indent + INDENT + INDENT;
result += "glDisable(GL_LIGHTING);";
result += NEWLINE + indent + INDENT;
result += "}";
result += NEWLINE + indent + INDENT;
result += "else";
result += NEWLINE + indent + INDENT;
result += "{";
result += NEWLINE + indent + INDENT + INDENT;
result += "glEnable(GL_LIGHTING);";
result += NEWLINE + indent + INDENT;
result += "}";
result += NEWLINE + indent;
result += "}";
result += NEWLINE;
// Aktion Nebel ein/aus
result += NEWLINE + indent;
result += "// Nebel ein/aus";
result += NEWLINE + indent;
result += "void actionToggleFog()";
result += NEWLINE + indent;
result += "{";
result += NEWLINE + indent + INDENT;
result += "if (glIsEnabled(GL_FOG))";
result += NEWLINE + indent + INDENT;
result += "{";
result += NEWLINE + indent + INDENT + INDENT;
result += "glDisable(GL_FOG);";
result += NEWLINE + indent + INDENT;
result += "}";
result += NEWLINE + indent + INDENT;
result += "else";
result += NEWLINE + indent + INDENT;
result += "{";
result += NEWLINE + indent + INDENT + INDENT;
result += "glEnable(GL_FOG);";
result += NEWLINE + indent + INDENT;
result += "}";
result += NEWLINE + indent;
result += "}";
result += NEWLINE;
// Aktion Shade flat/smooth
result += NEWLINE + indent;
result += "// Shade flat/smooth";
result += NEWLINE + indent;
result += "void actionToggleShadeModel()";
result += NEWLINE + indent;
result += "{";
result += NEWLINE + indent + INDENT;
result += "int shadeModel;";
result += NEWLINE + indent + INDENT;
result += "glGetIntegerv(GL_SHADE_MODEL, &shadeModel);";
result += NEWLINE;
result += NEWLINE + indent + INDENT;
result += "if (shadeModel == GL_SMOOTH)";
result += NEWLINE + indent + INDENT;
result += "{";
result += NEWLINE + indent + INDENT + INDENT;
result += "glShadeModel(GL_FLAT);";
result += NEWLINE + indent + INDENT;
result += "}";
result += NEWLINE + indent + INDENT;
result += "else";
result += NEWLINE + indent + INDENT;
result += "{";
result += NEWLINE + indent + INDENT + INDENT;
result += "glShadeModel(GL_SMOOTH);";
result += NEWLINE + indent + INDENT;
result += "}";
result += NEWLINE + indent;
result += "}";
result += NEWLINE;
// Mouse
result += NEWLINE + indent;
result += "// Callback-Funktion: MouseFunc";
result += NEWLINE + indent;
result += "void mouse(int button, int state, int x, int y)";
result += NEWLINE + indent;
result += "{";
result += NEWLINE + indent + INDENT;
result += "mousemotion = ";
result += "(button == GLUT_LEFT_BUTTON) && (state == GLUT_DOWN);";
result += NEWLINE + indent + INDENT;
result += "if (mousemotion)";
result += NEWLINE + indent + INDENT;
result += "{";
result += NEWLINE + indent + INDENT + INDENT;
result += "mousex = x;";
result += NEWLINE + indent + INDENT + INDENT;
result += "mousey = y;";
result += NEWLINE + indent + INDENT;
result += "}";
result += NEWLINE + indent;
result += "}";
result += NEWLINE;
// Motion
result += NEWLINE + indent;
result += "// Callback-Funktion: MotionFunc";
result += NEWLINE + indent;
result += "void motion(int x, int y)";
result += NEWLINE + indent;
result += "{";
result += NEWLINE + indent + INDENT;
result += "if (mousemotion)";
result += NEWLINE + indent + INDENT;
result += "{";
result += NEWLINE + indent + INDENT + INDENT;
result += "anglex += (GLfloat)(y - mousey);";
result += NEWLINE + indent + INDENT + INDENT;
result += "angley += (GLfloat)(x - mousex);";
result += NEWLINE + indent + INDENT + INDENT;
result += "mousex = x;";
result += NEWLINE + indent + INDENT + INDENT;
result += "mousey = y;";
result += NEWLINE + indent + INDENT + INDENT;
result += "// Szene erneut zeichen";
result += NEWLINE + indent + INDENT + INDENT;
result += "glutPostRedisplay();";
result += NEWLINE + indent + INDENT;
result += "}";
result += NEWLINE + indent;
result += "}";
result += NEWLINE;
// Keyboard
result += NEWLINE + indent;
result += "// Callback-Funktion: KeyboardFunc";
result += NEWLINE + indent;
result += "void keyboard(unsigned char keyPressed, int x, int y)";
result += NEWLINE + indent;
result += "{";
result += NEWLINE + indent + INDENT;
result += "switch (keyPressed)";
result += NEWLINE + indent + INDENT;
result += "{";
result += NEWLINE + indent + INDENT + INDENT;
result += "// Quit";
result += NEWLINE + indent + INDENT + INDENT;
result += "case '0': case 'q': case 'Q': case 27:";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "actionQuit();";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "break;";
result += NEWLINE + indent + INDENT + INDENT;
result += "// Init";
result += NEWLINE + indent + INDENT + INDENT;
result += "case '1': case 'i': case 'I':";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "actionInit();";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "break;";
result += NEWLINE + indent + INDENT + INDENT;
result += "// Toggle Lighting";
result += NEWLINE + indent + INDENT + INDENT;
result += "case '2': case 'l': case 'L':";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "actionToggleLighting();";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "break;";
result += NEWLINE + indent + INDENT + INDENT;
result += "// Toggle Fog";
result += NEWLINE + indent + INDENT + INDENT;
result += "case '3': case 'f': case 'F': case 'n': case 'N':";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "actionToggleFog();";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "break;";
result += NEWLINE + indent + INDENT + INDENT;
result += "// Toggle ShadeModel";
result += NEWLINE + indent + INDENT + INDENT;
result += "case '4': case 's': case 'S':";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "actionToggleShadeModel();";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "break;";
result += NEWLINE + indent + INDENT;
result += "}";
result += NEWLINE + indent + INDENT;
result += "// Szene erneut zeichen";
result += NEWLINE + indent + INDENT;
result += "glutPostRedisplay();";
result += NEWLINE + indent;
result += "}";
result += NEWLINE;
// Menu
result += NEWLINE + indent;
result += "// Menü-Handler";
result += NEWLINE + indent;
result += "void menu(int menuItem)";
result += NEWLINE + indent;
result += "{";
result += NEWLINE + indent + INDENT;
result += "switch (menuItem)";
result += NEWLINE + indent + INDENT;
result += "{";
result += NEWLINE + indent + INDENT + INDENT;
result += "// Quit";
result += NEWLINE + indent + INDENT + INDENT;
result += "case 0:";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "actionQuit();";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "break;";
result += NEWLINE + indent + INDENT + INDENT;
result += "// Init";
result += NEWLINE + indent + INDENT + INDENT;
result += "case 1:";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "actionInit();";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "break;";
result += NEWLINE + indent + INDENT + INDENT;
result += "// Toggle Lighting";
result += NEWLINE + indent + INDENT + INDENT;
result += "case 2:";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "actionToggleLighting();";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "break;";
result += NEWLINE + indent + INDENT + INDENT;
result += "// Toggle Fog";
result += NEWLINE + indent + INDENT + INDENT;
result += "case 3:";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "actionToggleFog();";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "break;";
result += NEWLINE + indent + INDENT + INDENT;
result += "// Toggle ShadeModel";
result += NEWLINE + indent + INDENT + INDENT;
result += "case 4:";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "actionToggleShadeModel();";
result += NEWLINE + indent + INDENT + INDENT + INDENT;
result += "break;";
result += NEWLINE + indent + INDENT;
result += "}";
result += NEWLINE + indent + INDENT;
result += "// Szene erneut zeichen";
result += NEWLINE + indent + INDENT;
result += "glutPostRedisplay();";
result += NEWLINE + indent;
result += "}";
result += NEWLINE;
// Reshape
result += NEWLINE + indent;
result += "// Callback-Funktion: ReshapeFunc";
result += NEWLINE + indent;
result += "void reshape(int width, int height)";
result += NEWLINE + indent;
result += "{";
result += NEWLINE + indent + INDENT;
result += "glMatrixMode(GL_PROJECTION);";
result += NEWLINE + indent + INDENT;
result += "glLoadIdentity();";
result += NEWLINE + indent + INDENT;
result += "GLfloat aspect = (GLfloat)width / (GLfloat)height;";
result += NEWLINE + indent + INDENT;
result += "gluPerspective(30.0f, aspect, 0.1f, 1000.0f);";
result += NEWLINE + indent + INDENT;
result += "glViewport(0, 0, width, height);";
result += NEWLINE + indent;
result += "}";
result += NEWLINE;
// Display
result += NEWLINE + indent;
result += "// Callback-Funktion: DisplayFunc";
result += NEWLINE + indent;
result += "void display(void)";
result += NEWLINE + indent;
result += "{";
result += NEWLINE + indent + INDENT;
result += "// Initialisierungen vor dem Zeichen";
result += NEWLINE + indent + INDENT;
result += "glMatrixMode(GL_MODELVIEW);";
result += NEWLINE + indent + INDENT;
result += "glLoadIdentity();";
result += NEWLINE + indent + INDENT;
result += "glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);";
result += NEWLINE;
// Background
result += NEWLINE;
result += tinyray.background.accept(this, indent + INDENT);
result += NEWLINE;
// Fog
result += NEWLINE;
result += tinyray.fog.accept(this, indent + INDENT);
result += NEWLINE;
// Camera
result += NEWLINE;
result += tinyray.camera.accept(this, indent + INDENT);
result += NEWLINE;
result += NEWLINE + indent + INDENT;
result += "// Rundumbewegung mit Transformationen ermöglichen";
result += NEWLINE + indent + INDENT;
result += "glTranslatef(";
result += tinyray.camera.lookAt.accept(this, "");
result += "); // <- lookAt";
result += NEWLINE + indent + INDENT;
result += "glRotatef(anglex, 1.0f, 0.0f, 0.0f);";
result += NEWLINE + indent + INDENT;
result += "glRotatef(angley, 0.0f, 1.0f, 0.0f);";
result += NEWLINE + indent + INDENT;
result += "glTranslatef(";
result += Vector.anti(tinyray.camera.lookAt).accept(this, "");
result += "); // -> lookAt";
result += NEWLINE;
// Ambience
result += NEWLINE;
result += tinyray.ambience.accept(this, indent + INDENT);
result += NEWLINE;
// Suns
result += NEWLINE + indent + INDENT;
result += "// Lichtquellen setzen";
result += NEWLINE;
Iterator<Sun> suns = tinyray.suns.iterator();
while (suns.hasNext()) {
result += NEWLINE;
result += suns.next().accept(this, indent + INDENT);
result += NEWLINE;
}
// Materialinitialisierung mit Defaults
result += NEWLINE + indent + INDENT;
result += "// Basismaterial";
result += NEWLINE;
result += this.defaults.accept(this, indent + INDENT);
result += NEWLINE;
// Visitables wie Geoobjekte und Defaults.
result += NEWLINE + indent + INDENT;
result += "// Geoobjekte setzen";
result += NEWLINE;
Iterator<Visitable> visitables = tinyray.visitables.iterator();
while (visitables.hasNext()) {
result += NEWLINE;
result += visitables.next().accept(this, indent + INDENT);
result += NEWLINE;
}
// Das neue Bild anzeigen
result += NEWLINE + indent + INDENT;
result += "glutSwapBuffers();";
result += NEWLINE + indent;
result += "}";
result += NEWLINE;
// Main-Methode
result += NEWLINE + indent;
result += "// Die Hauptfunktion";
result += NEWLINE + indent;
result += "int main(int argc, char* argv[])";
result += NEWLINE + indent;
result += "{";
result += NEWLINE + indent + INDENT;
result += "// Glut-Fenster";
result += NEWLINE + indent + INDENT;
result += "glutInit(&argc, argv);";
result += NEWLINE + indent + INDENT;
result += "glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);";
result += NEWLINE + indent + INDENT;
result += "glutInitWindowSize(WIDTH, HEIGHT);";
result += NEWLINE + indent + INDENT;
result += "glutInitWindowPosition(100, 100);";
result += NEWLINE + indent + INDENT;
result += "glutCreateWindow(argv[0]);";
result += NEWLINE;
result += NEWLINE + indent + INDENT;
result += "// Ein Popup-Menu anbinden";
result += NEWLINE + indent + INDENT;
result += "glutCreateMenu(menu);";
result += NEWLINE + indent + INDENT;
result += "glutAddMenuEntry(\"Startposition\", 1);";
result += NEWLINE + indent + INDENT;
result += "glutAddMenuEntry(\"Lichter ein/aus\", 2);";
result += NEWLINE + indent + INDENT;
result += "glutAddMenuEntry(\"Nebel ein/aus\", 3);";
result += NEWLINE + indent + INDENT;
result += "glutAddMenuEntry(\"Shade flat/smooth\", 4);";
result += NEWLINE + indent + INDENT;
result += "glutAddMenuEntry(\"Programm verlassen\", 0);";
result += NEWLINE + indent + INDENT;
result += "glutAttachMenu(GLUT_RIGHT_BUTTON);";
result += NEWLINE;
result += NEWLINE + indent + INDENT;
result += "// OpenGL-Einstellungen";
result += NEWLINE + indent + INDENT;
result += "glEnable(GL_LIGHTING);";
result += NEWLINE + indent + INDENT;
result += "glDepthFunc(GL_LESS);";
result += NEWLINE + indent + INDENT;
result += "glEnable(GL_DEPTH_TEST);";
result += NEWLINE + indent + INDENT;
result += "glEnable(GL_NORMALIZE);";
result += NEWLINE + indent + INDENT;
result += "glEnable(GL_FOG);";
result += NEWLINE + indent + INDENT;
result += "glShadeModel(GL_SMOOTH);";
result += NEWLINE;
result += NEWLINE + indent + INDENT;
result += "// Zunächst Szene darstellen";
result += NEWLINE + indent + INDENT;
result += "reshape(WIDTH, HEIGHT);";
result += NEWLINE + indent + INDENT;
result += "display();";
result += NEWLINE;
result += NEWLINE + indent + INDENT;
result += "// Callback-Funktionen integrieren";
result += NEWLINE + indent + INDENT;
result += "glutMouseFunc(mouse);";
result += NEWLINE + indent + INDENT;
result += "glutMotionFunc(motion);";
result += NEWLINE + indent + INDENT;
result += "glutKeyboardFunc(keyboard);";
result += NEWLINE + indent + INDENT;
result += "glutReshapeFunc(reshape);";
result += NEWLINE + indent + INDENT;
result += "glutDisplayFunc(display);";
result += NEWLINE;
result += NEWLINE + indent + INDENT;
result += "glutMainLoop();";
result += NEWLINE;
result += NEWLINE + indent + INDENT;
result += "return EXIT_SUCCESS;";
result += NEWLINE + indent;
result += "}";
result += NEWLINE;
result += NEWLINE + indent;
result += "/* Quelle: Tinyray-Code";
result += NEWLINE;
result += NEWLINE;
result += tinyray.accept(new PrettyPrint(), indent + INDENT);
result += NEWLINE;
result += NEWLINE + indent;
result += "*/";
result += NEWLINE;
return result;
}
/**
* Besucht einen besuchbaren Camera-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param camera Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Camera camera, String indent) {
String result = "";
result += indent;
result += "// Kamera setzen";
result += NEWLINE + indent;
result += "gluLookAt(";
result += NEWLINE + indent + INDENT;
result += camera.location.accept(this, "");
result += ", // location";
result += NEWLINE + indent + INDENT;
result += camera.lookAt.accept(this, "");
result += ", // lookAt";
result += NEWLINE + indent + INDENT;
result += camera.up.accept(this, "");
result += " // up";
result += NEWLINE + indent;
result += ");";
return result;
}
/**
* Besucht einen besuchbaren Background-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param background Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Background background, String indent) {
String result = "";
result += indent;
result += "// Hintergrundfarbe setzen";
result += NEWLINE + indent;
result += "glClearColor(";
result += background.color.accept(this, "");
result += ", 1.0f";
result += ");";
return result;
}
/**
* Besucht einen besuchbaren Ambience-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param ambience Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Ambience ambience, String indent) {
String result = "";
result += indent;
result += "// Globales, ambientes Umgebungslicht setzen";
result += NEWLINE + indent;
result += "glLightModelfv(";
result += NEWLINE + indent + INDENT;
result += "GL_LIGHT_MODEL_AMBIENT,";
result += NEWLINE + indent + INDENT;
result += "(GLfloat[]) { ";
result += ambience.color.accept(this, "");
result += ", 1.0f }";
result += NEWLINE + indent;
result += ");";
return result;
}
/**
* Besucht einen besuchbaren Fog-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param fog Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Fog fog, String indent) {
String result = "";
result += indent;
result += "// Nebel";
result += NEWLINE + indent;
result += "glFogi(GL_FOG_MODE, GL_EXP2);";
result += NEWLINE + indent;
result += "glFogfv(";
result += NEWLINE + indent + INDENT;
result += "GL_FOG_COLOR,";
result += NEWLINE + indent + INDENT;
result += "(GLfloat[]) { ";
result += fog.color.accept(this, "");
result += " }";
result += NEWLINE + indent;
result += ");";
result += NEWLINE + indent;
result += "glFogf(";
result += NEWLINE + indent + INDENT;
result += "GL_FOG_DENSITY,";
result += NEWLINE + indent + INDENT;
result += fog.density.accept(this, "");
result += NEWLINE + indent;
result += ");";
return result;
}
/**
* Besucht einen besuchbaren Sun-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param sun Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Sun sun, String indent) {
String result = "";
result += indent;
result += "// Sonne " + this.lightIndex + " setzen";
result += NEWLINE + indent;
// Ambienter Anteil
result += "glLightfv(";
result += NEWLINE + indent + INDENT;
result += "GL_LIGHT0 + " + this.lightIndex + ",";
result += NEWLINE + indent + INDENT;
result += "GL_AMBIENT,";
result += NEWLINE + indent + INDENT;
result += "(GLfloat[]) { 0.0f, 0.0f, 0.0f, 1.0f }";
result += NEWLINE + indent;
result += ");";
result += NEWLINE + indent;
// Diffuser Anteil
result += "glLightfv(";
result += NEWLINE + indent + INDENT;
result += "GL_LIGHT0 + " + this.lightIndex + ",";
result += NEWLINE + indent + INDENT;
result += "GL_DIFFUSE,";
result += NEWLINE + indent + INDENT;
result += "(GLfloat[]) { ";
result += sun.color.accept(this, "");
result += ", 1.0f }";
result += NEWLINE + indent;
result += ");";
result += NEWLINE + indent;
// Spekularer Anteil
result += "glLightfv(";
result += NEWLINE + indent + INDENT;
result += "GL_LIGHT0 + " + this.lightIndex + ",";
result += NEWLINE + indent + INDENT;
result += "GL_SPECULAR,";
result += NEWLINE + indent + INDENT;
result += "(GLfloat[]) { ";
result += sun.color.accept(this, "");
result += ", 1.0f }";
result += NEWLINE + indent;
result += ");";
result += NEWLINE + indent;
// Paralleles Licht
result += "glLightfv(";
result += NEWLINE + indent + INDENT;
result += "GL_LIGHT0 + " + this.lightIndex + ",";
result += NEWLINE + indent + INDENT;
result += "GL_POSITION,";
result += NEWLINE + indent + INDENT;
result += "(GLfloat[]) { ";
result += sun.direction.accept(this, "");
result += ", 0.0f }";
result += NEWLINE + indent;
result += ");";
result += NEWLINE + indent;
result += "glEnable(GL_LIGHT0 + " + this.lightIndex + ");";
this.lightIndex++;
return result;
}
/**
* Besucht einen besuchbaren Bounding-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param bounding Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Bounding bounding, String indent) {
String result = "";
result += indent;
result += "/* > Bounding */";
result += NEWLINE;
Iterator<Visitable> visitables = bounding.visitables.iterator();
while (visitables.hasNext()) {
result += NEWLINE;
result += visitables.next().accept(this, indent + INDENT);
result += NEWLINE;
}
result += NEWLINE + indent;
result += "/* < Bounding */";
return result;
}
/**
* Besucht einen besuchbaren Triangle-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param triangle Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Triangle triangle, String indent) {
String result = "";
result += indent;
result+= "/* > Triangle */";
result += NEWLINE;
this.localParameters = true;
result += triangle.parameters.accept(this, indent);
result += NEWLINE + indent;
result += "glBegin(GL_TRIANGLES);";
result += NEWLINE + indent + INDENT;
result += "glNormal3f(";
Vector normal = Vector.normal0(triangle.x, triangle.y, triangle.z);
result += normal.accept(this, "");
result += ");";
result += NEWLINE + indent + INDENT;
result += "glVertex3f(";
result += triangle.x.accept(this, "");
result += ");";
result += NEWLINE + indent + INDENT;
result += "glVertex3f(";
result += triangle.y.accept(this, "");
result += ");";
result += NEWLINE + indent + INDENT;
result += "glVertex3f(";
result += triangle.z.accept(this, "");
result += ");";
result += NEWLINE + indent;
result += "glEnd();";
result += NEWLINE;
this.localParameters = false;
result += triangle.parameters.accept(this, indent);
result += NEWLINE + indent;
result+= "/* < Triangle */";
return result;
}
/**
* Besucht einen besuchbaren Sphere-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param sphere Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Sphere sphere, String indent) {
String result = "";
result += indent;
result+= "/* > Sphere */";
result += NEWLINE;
this.localParameters = true;
result += sphere.parameters.accept(this, indent);
result += NEWLINE + indent;
result += "glPushMatrix();";
result += NEWLINE + indent;
result += "glTranslatef(";
result += sphere.center.accept(this, "");
result += ");";
result += NEWLINE + indent;
result += "glutSolidSphere(";
result += sphere.radius.accept(this, "");
result += ", 30, 30);";
result += NEWLINE + indent;
result += "glPopMatrix();";
result += NEWLINE;
this.localParameters = false;
result += sphere.parameters.accept(this, indent);
result += NEWLINE + indent;
result += "/* < Sphere */";
return result;
}
/**
* Besucht einen besuchbaren Plane-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param plane Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Plane plane, String indent) {
String result = "";
result += indent;
result+= "/* > Plane */";
result += NEWLINE;
this.localParameters = true;
result += plane.parameters.accept(this, indent);
result += NEWLINE + indent;
result += "glPushMatrix();";
// center = (p.x + p.y + p.z) / 3.0
Vector center = new Vector();
center.x.value = plane.x.x.value;
center.y.value = plane.x.y.value;
center.z.value = plane.x.z.value;
center.x.value += plane.y.x.value;
center.y.value += plane.y.y.value;
center.z.value += plane.y.z.value;
center.x.value += plane.z.x.value;
center.y.value += plane.z.y.value;
center.z.value += plane.z.z.value;
center.x.value /= 3.0;
center.y.value /= 3.0;
center.z.value /= 3.0;
result += NEWLINE + indent;
result += "glTranslatef(";
result += center.accept(this, "");
result += ");";
result += NEWLINE + indent;
result += "glScalef(500.0f, 500.0f, 500.0f);";
result += NEWLINE + indent;
result += "glTranslatef(";
result += Vector.anti(center).accept(this, "");
result += ");";
result += NEWLINE + indent;
result += "glBegin(GL_TRIANGLES);";
result += NEWLINE + indent + INDENT;
result += "glNormal3f(0.0f, 0.0f, 1.0f);";
result += NEWLINE + indent + INDENT;
result += "glVertex3f(";
result += plane.x.accept(this, "");
result += ");";
result += NEWLINE + indent + INDENT;
result += "glVertex3f(";
result += plane.y.accept(this, "");
result += ");";
result += NEWLINE + indent + INDENT;
result += "glVertex3f(";
result += plane.z.accept(this, "");
result += ");";
result += NEWLINE + indent;
result += "glEnd();";
result += NEWLINE + indent;
result += "glPopMatrix();";
result += NEWLINE;
this.localParameters = false;
result += plane.parameters.accept(this, indent);
result += NEWLINE + indent;
result+= "/* < Plane */";
return result;
}
/**
* Besucht einen besuchbaren Defaults-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param defaults Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Defaults defaults, String indent) {
String result = "";
int thisSize = this.defaults.parameters.visitables.size();
int size = defaults.parameters.visitables.size();
for (int i = 0; i < Math.min(thisSize, size); i++) {
Visitable v = defaults.parameters.visitables.get(i);
this.defaults.parameters.visitables.set(i, v);
}
// Die Parameter werden wieder zurückgesetzt.
this.localParameters = false;
result += defaults.parameters.accept(this, indent);
return result;
}
/**
* Besucht einen besuchbaren Parameters-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param parameters Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Parameters parameters, String indent) {
String result = "";
int size = parameters.visitables.size();
result += indent;
if (this.localParameters) {
result += "// Parameters " + size;
} else {
result += "// Defaults " + size;
}
if (0 < size) {
Visitable v0;
if (this.localParameters) {
v0 = parameters.visitables.get(0);
} else {
v0 = this.defaults.parameters.visitables.get(0);
}
result += NEWLINE + indent;
result += "glColor3f(";
result += v0.accept(this, "");
result += "); // Farbe, falls Licht deaktiviert";
result += NEWLINE + indent;
result += "glMaterialfv(";
result += NEWLINE + indent + INDENT;
result += "GL_FRONT,";
result += NEWLINE + indent + INDENT;
result += "GL_DIFFUSE,";
result += NEWLINE + indent + INDENT;
result += "(GLfloat[]) { ";
result += v0.accept(this, "");
result += ", 1.0f }";
result += NEWLINE + indent;
result += ");";
}
if (1 < size) {
Visitable v1;
if (this.localParameters) {
v1 = parameters.visitables.get(1);
} else {
v1 = this.defaults.parameters.visitables.get(1);
}
result += NEWLINE + indent;
result += "glMaterialfv(";
result += NEWLINE + indent + INDENT;
result += "GL_FRONT,";
result += NEWLINE + indent + INDENT;
result += "GL_AMBIENT,";
result += NEWLINE + indent + INDENT;
result += "(GLfloat[]) { ";
result += v1.accept(this, "");
result += ", 1.0f }";
result += NEWLINE + indent;
result += ");";
}
if (2 < size) {
Visitable v2;
if (this.localParameters) {
v2 = parameters.visitables.get(2);
} else {
v2 = this.defaults.parameters.visitables.get(2);
}
result += NEWLINE + indent;
result += "glMaterialfv(";
result += NEWLINE + indent + INDENT;
result += "GL_FRONT,";
result += NEWLINE + indent + INDENT;
result += "GL_SPECULAR,";
result += NEWLINE + indent + INDENT;
result += "(GLfloat[]) { ";
result += v2.accept(this, "");
result += ", ";
result += v2.accept(this, "");
result += ", ";
result += v2.accept(this, "");
result += ", 1.0f }";
result += NEWLINE + indent;
result += ");";
}
if (3 < size) {
Visitable v3;
if (this.localParameters) {
v3 = parameters.visitables.get(3);
} else {
v3 = this.defaults.parameters.visitables.get(3);
}
result += NEWLINE + indent;
result += "glMaterialf(";
result += NEWLINE + indent + INDENT;
result += "GL_FRONT,";
result += NEWLINE + indent + INDENT;
result += "GL_SHININESS,";
result += NEWLINE + indent + INDENT;
result += v3.accept(this, "");
result += NEWLINE + indent;
result += ");";
}
if (4 < size) {
Visitable v4;
if (this.localParameters) {
v4 = parameters.visitables.get(4);
} else {
v4 = this.defaults.parameters.visitables.get(4);
}
result += NEWLINE + indent;
result += "// Mirror = ";
result += v4.accept(this, "");
result += " wird nicht unterstützt!";
}
return result;
}
/**
* Besucht einen besuchbaren Vector-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param vector Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Vector vector, String indent) {
String result = "";
result += vector.x.accept(this, indent);
result += ", ";
result += vector.y.accept(this, "");
result += ", ";
result += vector.z.accept(this, "");
return result;
}
/**
* Besucht einen besuchbaren Real-Knoten und generiert einen
* entsprechenden Glut/OpenGL-C-Code mit einer bestimmten Einrückung
* und gibt diesen Code als Zeichenkette zurück.
* @param real Der besuchbare Knoten.
* @param indent Die Einrückung.
* @return Der generierte Glut/OpenGL-C-Code.
*/
public String visit(Real real, String indent) {
String result = "";
result += indent;
result += new Float(real.value).toString(); // downcast
result += "f";
return result;
}
}