[
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2015, 2016 Maurice Tollmien <maurice.tollmien@gmail.com>\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Water-Simulation with Realtime Reflections/Refractions from the Surface\nThis project consists of several smaller projects joined together. Everything is done completely from\nscratch. No external libraries or dependencies (except basic OpenGL) are needed to run this simulation.\n\nThe final result looks like that:\n\n![Water-Simulation](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished3.png \"Water-Simulation with reflections/refractions\")\n\n## **Water Simulation**\n\nThe water simulation itself is a pressure based height field.\n\nThe water's surface is divided into a small grid of points. Each height represents\nthe pressure at that point. For each time step the pressure is divided and continued on to\nthe next water point. The calculation itself is similar to image processing calculations,\nwhere a kernel over each pixel calculates the color at that pixel.\n\nA height field water simulation looks very real for smaller waves and distorted water surfaces.\nBut because of using a height-field (real time efficiency and simplicity to implement) there is no\npossibility of calculating single drops or any kind of detachment of waterbodies from the surface.\nAlso no overlapping waves or such things are possible.\n\nExample with random displacement added to the water's surface, creating very small waves (distortion):\n\n![Water-Distortion](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished6.png \"Small distortions\")\n\nExample with some small spreading waves:\n\n![Spreading waves](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished7.png \"Spreading waves\")\n\nExample with waves bouncing back from the shore:\n\n![Bouncing waves](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished1.png \"Waves bouncing from the shore\")\n\n\n## **Reflections / Refractions (Screenspace)**\n\nBoth the reflection and refraction of the water's surface is calculated in screen space with OpenGL fragment shaders.\n\nThe main benefit of using screenspace reflections/refractions is, that it takes a constant time to calculate and doesn't depend\non the complexity of the scene. Another benefit is, that both the reflection and refraction can be calculated using\nthe exact same calculations.\n\n- For each frame, two textures (color-texture and depth-texture) are created from the point of view and provided to the\n  OpenGL fragment shader.\n\n- For each pixel, the position of each reflection/refraction-point is provided in world-coordinates to the fragment shader.\n\n- A step-size is determined (could also be constant).\n\n- For each step, the reflection-vector is scaled with the determinded step-size and transformed into screenspace.\n  We now have two vectors. One is the reflection-vector in world coordinates and the same one transformed into screen space.\n\n- Because we look at the same scene which is saved into the texture, we can now sample the depth-texture and get the depth\n  of the scene at the point of the scaled reflection-vector.\n\n- We continue the scaling of the reflection-vector until the depth of the sampled depth-texture is smaller than the\n  z-coordinate (depth) of the reflection-vector in world coordinates. In this case we know, that we hit something which should\n  be displayed as the reflection for the original fragment.\n\n- We can then take the transformed reflection-vector and sample the color texture. The result should be the color of the\n  reflection. We take that color and are finished.\n\nPositive features: Works in real time looks good most of the time.\n\nNegative features: Actually takes longer to calculate, if there are no reflections, is not always correct, not defined\nfor situations where the reflection goes outside the screenspace and can only reflect objects which are on the screen!\n(Also there are incorrect reflections if there is an object between the camera and the water's surface.)\n\nWater refraction:\n\n![Refraction](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished2.png \"Water-Refraction looking good!\")\n\nReflection and refraction with no waves at all:\n\n![No Wave-Reflection](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished5.png \"Water-Reflection, no waves\")\n\nRefraction and Reflection of smaller waves from above:\n\n![Small waves](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished4.png \"Water-Refraction/Reflection with small waves\")\n\n## **Terrain Modelling**\n\nThe terrain is modelled using a 2D-Perlin-Noise-function (implemented from scratch!).\nIt overlays different frequences of sinus and cosinus waves.\nThe perlin-noise height field is then textured based on the current height (Overlapping of different textures).\nThe mountain like hill is added by adding a gauss function to the perlin-noise output.\nThe same goes for the valley where the water is.\n\n## **Install && Run**\n\nI only tested and ran this simulation on a debian-based Linux OS (Ubuntu, Mint, ...). It should run on other machines as well but is not\ntested.\n\n### **Requirements**\n\nThe following system-attributes are required for running this simulation:\n\n- A graphics card supporting OpenGL version 3.3 (For the shaders).\n\n- Unix-Libraries: xorg-dev, freeglut3-dev and mesa-common-dev\n\n### **Running**\n\nCompiling and running is pretty straight forward.\n\n- make\n\n- ./water\n\nWhile the simulation runs, you can move around (always looking to the center!) with your mouse (left-klick and move).\n\nInitializing a random movement (choppy water) is done with 'r'.\n\nCreating one/several waves can be done by pressing 'n'.\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "src/Makefile",
    "content": "# Quelldateien\nSRCS             = imageLoader.c vector.c main.c scene.c io.c water.c terrain.c logic.c stringOutput.c \n\n# ausfuehrbares Ziel\nTARGET           = water\n\n# Ist libz verfgbar?\nHAVE_LIBZ = yes\n\n\n# Basis-Makefile einbinden\n-include ./Makefile.common\n\n\n# Precompiler flags\n# Pfad der Schnittstelle des ImageLoaders hinzufuegen\nCPPFLAGS_COMMON  += -I$(IMGLOADER_DIR)/include\n\n# Linker flags\n# Pfad der ImageLoader-Bibliothek hinzufuegen\nLDFLAGS_COMMON  += -L$(IMGLOADER_DIR)/lib\n\n\n# Wenn libz verfuegbar ist, muessen wir sie mit einlinken, um die\n# Bibliothek auch zum Laden von PNG-Bildern verwenden zu koennen.\nifeq ($(HAVE_LIBZ),yes)\nLDLIBS += -lz\nendif\n\n\n.PHONY: distcleanimageloader\n\n\n# TARGETS\n\n# Regel zur Erstellung der ImageLoader-Bibliothek\n$(IMGLOADER_DIR)/lib/$(IMGLOADER_LIB):\n\t(cd $(IMGLOADER_DIR) && ./configure)\n\t$(MAKE) -C $(IMGLOADER_DIR)\n\n# Vollstaendiges Aufraeumen beinhaltet auch Aufraeumen des ImageLoaders\ndistclean: distcleanimageloader\n\n# Regel zum Aufraeumen des ImageLoaders\ndistcleanimageloader:\n\tif [ -f $(IMGLOADER_DIR)/Makefile ]; then $(MAKE) -C $(IMGLOADER_DIR) HAVE_LIBZ=$(HAVE_LIBZ) distclean; fi\n"
  },
  {
    "path": "src/Makefile.common",
    "content": "# Objektdateien\nOBJS             = $(SRCS:.c=.o)\n\n# Compiler\nCC               = gcc\n\n# Precompiler flags\nCPPFLAGS_LINUX   =\nCPPFLAGS_LINUX64 =\nCPPFLAGS_MACOSX  = -DMACOSX\nCPPFLAGS_COMMON  = -I./\nCPPFLAGS         = $(CPPFLAGS_COMMON) $(CPPFLAGS_$(OS))\n\n# Compiler flags\nCFLAGS_LINUX   =\nCFLAGS_LINUX64 =\nCFLAGS_MACOSX  =\nCFLAGS_COMMON  = -Wextra -ansi\nCFLAGS         = $(CFLAGS_COMMON) $(CFLAGS_$(OS))\n\n# Linker\nLD               = gcc\n\n# Linker flags\nLDFLAGS_LINUX    = -L/usr/X11R6/lib -L/usr/lib\nLDFLAGS_LINUX64  = -L/usr/X11R6/lib64\nLDFLAGS_MACOSOX  =\nLDFLAGS_COMMON   =\nLDFLAGS          = $(LDFLAGS_COMMON) $(LDFLAGS_$(OS))\n\n# Linker libraries\nXLIBS            = -lXmu -lXi -lX11\nGLLIBS           = -lglut -lGLU -lGL\n\nLDLIBS_LINUX     = $(GLLIBS) #$(XLIBS)\nLDLIBS_LINUX64   = $(GLLIBS) #$(XLIBS)\nLDLIBS_MACOSX    = -framework OpenGL -framework GLUT -framework Foundation\nLDLIBS_COMMON    = -lm\nLDLIBS           = $(LDLIBS_COMMON) $(LDLIBS_$(OS))\n\n# welches Betriebssystem?\nifeq ($(findstring Linux,$(shell uname -s)),Linux)\n  OS = LINUX\n  ifeq ($(shell uname -m),x86_64)\n    OS = LINUX64\n  endif\nelse\n  ifeq ($(shell uname -s),Darwin)\n    OS = MACOSX\n  endif\nendif\n\n# Debugging-Informationen aktivieren\nDEBUG = yes\n\n# Wenn Debugging-Informationen aktiviert werden sollen, entsprechende\n# Praeprozessorflags setzen\nifeq ($(DEBUG),yes)\nCPPFLAGS_COMMON+=-g -DDEBUG\nendif\n\n\n.SUFFIXES: .o .c\n.PHONY: all clean distclean depend\n\n\n# TARGETS\nall: depend $(TARGET)\n\ndoc:\n\tdoxygen ../common/Doxyfile\n\n# Linken des ausfuehrbaren Programms\n$(TARGET): $(OBJS)\n\t$(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(TARGET)\n\n# Kompilieren der Objektdateien\n%.o: %.c\n\t$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $*.o $*.c\n\n# einfaches Aufraeumen\nclean:\n\trm -f $(TARGET)\n\trm -f $(OBJS)\n\n# alles loeschen, was erstellt wurde\ndistclean: clean\n\trm -f *~\n\trm -f Makefile.depend\n\trm -rf doc\n\trm -rf doxygen.log\n\n# Abhaengigkeiten automatisch ermitteln\ndepend:\n\t@rm -f Makefile.depend\n\t@echo -n \"building Makefile.depend ... \"\n\t@$(foreach SRC, $(SRCS), ( $(CC) $(CPPFLAGS) $(SRC) -MM -g0 ) 1>> Makefile.depend;)\n\t@echo \"done\"\n\n# zusaetzliche Abhaengigkeiten einbinden\n-include Makefile.depend\n\n"
  },
  {
    "path": "src/Makefile.depend",
    "content": "imageLoader.o: imageLoader.c imageLoader.h\nvector.o: vector.c stringOutput.h types.h\nmain.o: main.c io.h scene.h types.h\nscene.o: scene.c stringOutput.h scene.h types.h logic.h water.h terrain.h \\\n vector.h\nio.o: io.c io.h scene.h types.h logic.h water.h terrain.h vector.h \\\n imageLoader.h\nwater.o: water.c water.h types.h terrain.h particle.h logic.h vector.h\nterrain.o: terrain.c terrain.h types.h logic.h vector.h\nlogic.o: logic.c stringOutput.h logic.h types.h vector.h scene.h water.h \\\n terrain.h\nstringOutput.o: stringOutput.c stringOutput.h\n"
  },
  {
    "path": "src/colorFragmentShader.frag",
    "content": "#version 330 \n\nin vec3 color; \nout vec4 Color; \nuniform vec3 colorIn; \n\nvoid main(){ \n\tColor = vec4(colorIn, 1.0); \n}\n"
  },
  {
    "path": "src/colorVertexShader.vert",
    "content": "#version 330 \n\nlayout (location = 0) in vec3 vertPos; \nuniform mat4 viewMatrix, projMatrix; \n\nvoid main(){ \n\tgl_Position =  projMatrix * viewMatrix * vec4(vertPos, 1.0); \n}\n"
  },
  {
    "path": "src/imageLoader.c",
    "content": "\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <math.h>\n/* ---- Eigene Header einbinden ---- */\n#include \"imageLoader.h\"\n\nint error(FILE * f, char * name, char * errorMessage) {\n\tprintf(\"%s: %s.\\n\", errorMessage, name);\n\tfclose(f);\n\treturn 0;\n}\n\n/* Loads image for texture creation.*/\nint imageLoad(char *filename, Image *image) {\n    FILE *file;\n    unsigned long size;                 /* size of the image in bytes.*/\n    unsigned long i;                    /* standard counter.*/\n    unsigned short int planes;          /* number of planes in image (must be 1) */\n    unsigned short int bpp;             /* number of bits per pixel (must be 24)*/\n    char temp;                          /* used to convert bgr to rgb color.*/\n\n\timage->sizeX = 0;\n\timage->sizeY = 0;\n\n    /* make sure the file is there*/\n    if ((file = fopen(filename, \"rb\")) == NULL)\n\t\treturn error(file, \"File Not Found\", filename);\n    \n    /* seek through the bmp header, up to the width/height:*/\n    fseek(file, 18, SEEK_CUR);\n\n    /* read the width*/\n    if ((i = fread(&image->sizeX, 4, 1, file)) != 1) \n\t\treturn error(file, \"Error reading width from\", filename);\n\t\t\n    printf(\"Width of %s: %lu\\n\", filename, image->sizeX);\n    \n    /* read the height */\n    if ((i = fread(&image->sizeY, 4, 1, file)) != 1) \n\t\treturn error(file, \"Error reading height from\", filename); \n\t\t\n    printf(\"Height of %s: %lu\\n\", filename, image->sizeY);\n    \n    /* calculate the size (assuming 24 bits or 3 bytes per pixel).*/\n    size = image->sizeX * image->sizeY * 3;\n\n    /* read the planes*/\n    if ((fread(&planes, 2, 1, file)) != 1) \n\t\treturn error(file, \"Error reading planes from\", filename);\n\t\t\n    if (planes != 1)\n\t\treturn error(file, \"Planes from file is not 1\", filename);\n\n    /* read the bpp */\n    if ((i = fread(&bpp, 2, 1, file)) != 1) \n\t\treturn error(file, \"Error reading bpp from\", filename);\n\t\t\n    if (bpp != 24) \n\t\treturn error(file, \"Bpp from file is not 24\\n\", filename);\n\t\n    /* seek past the rest of the bitmap header.*/\n    fseek(file, 24, SEEK_CUR);\n\n    /* read the data. */\n    image->data = malloc(size);\n    if (image->data == NULL) \n\t\treturn error(file, \"Error allocating memory for color-corrected image data\", filename);\n\t\t\n    if ((i = fread(image->data, size, 1, file)) != 1) \n\t\treturn error(file, \"Error reading image data from\", filename);\n\n    for (i=0;i<size;i+=3) \n\t{ \n\t\ttemp = image->data[i];\n\t\timage->data[i] = image->data[i+2];\n\t\timage->data[i+2] = temp;\n    }\n\n\tfclose(file);\n\n    return 1;\n}\n"
  },
  {
    "path": "src/imageLoader.h",
    "content": "#ifndef __IMAGE_H__\n#define __IMAGE_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * Programmlogik und Datenhaltung\n *\n * @author Maurice Tollmien\n */\n\n/* ---- System Header einbinden ---- */\n#ifdef WIN32\n#include <windows.h>\n#endif\n\n#ifdef MACOSX\n#include <OpenGL/glu.h>\n#else\n#include <GL/glu.h>\n#endif\n\n#include <stdio.h>\n#include <stdarg.h>\n\ntypedef struct {\n\tlong unsigned int sizeX, sizeY;\n\tunsigned char * data;\n} Image;\n\nint imageLoad(char *filename, Image *image);\n\n#endif\n\n"
  },
  {
    "path": "src/io.c",
    "content": "\n\n/**\n * @file\n * Hier sind alle CallBack-Funktionen\n *\n * @author Maurice Tollmien, Tilman Nedele\n */\n\n/* ---- System Header einbinden ---- */\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <math.h>\n\n#ifdef MACOSX\n#include <GLUT/glut.h>\n#else\n#include <GL/glut.h>\n#endif\n\n/* ---- Eigene Header einbinden ---- */\n#include \"io.h\"\n#include \"scene.h\"\n#include \"logic.h\"\n#include \"water.h\"\n#include \"terrain.h\"\n#include \"vector.h\"\n#include \"imageLoader.h\"\n\n/* ---- Eigene Funktionen ---- */\n\n/* Texturen und Framebuffer */\nGLuint G_fboCam, G_fboRefl, G_fboRefr, G_TexCamera, G_TexCameraDepth, G_TexReflection, G_TexRefraction, G_TexImageGrass, G_TexImageSand, G_TexImageCaustics, G_TexImageRocks, G_TexImageSnow, G_TexImageForest, G_TexImageTundra;\n\n/* Shader-ID's */\nGLuint G_ShaderID, G_ShaderIDSimple, G_ShaderColor, G_ShaderIDSimpleD;\n\n/* Geometrie-Buffer */\nGLuint G_arrayBuffer, G_TexCube, G_cubeBuffer, G_SurfaceBuffer, G_WaterBuffer, G_WaterBufferIndex, G_ObjectsBuffer, G_TerrainBuffer, G_TerrainBufferIndex, G_CausticsBuffer;\n\n/* Cube-Map */\nGLuint G_TexCubeFront, G_TexCubeBack, G_TexCubeBottom, G_TexCubeTop, G_TexCubeLeft, G_TexCubeRight;\n\n/* Shader-Variablen */\nGLuint G_projMatrixLoc, G_viewMatrixLoc, G_sampler2dLoc, G_samplerDepth2dLoc, G_cameraPosLoc, G_colorIn, G_samplerCubeLoc;\n\nint view = 1;\nint G_Width = 1024;\nint G_Height = 1024;\nint G_fullScreen = 1;\n\nGLfloat G_data[] = {\n\t\t\t\t-1.0, -1.0, 0.0,\t\t0.0, 0.0,\t\n\t\t\t\t1.0, -1.0, 0.0,\t\t\t1.0, 0.0,\t\n\t\t\t\t1.0, 1.0, 0.0,\t\t\t1.0, 1.0,\n\t\t\t\t-1.0, -1.0, 0.0,\t\t0.0, 0.0,\n\t\t\t\t1.0, 1.0, 0.0,\t\t\t1.0, 1.0,\n\t\t\t\t-1.0, 1.0, 0.0,\t\t\t0.0, 1.0\n\t\t\t};\n\nfloat G_Surface[] = {\n\t-75, 0.0, -75,\n\t-75, 0.0, 75,\n\t75, 0.0, 75,\n\t-75, 0.0, -75,\n\t75, 0.0, 75,\n\t75, 0.0, -75\n};\n\nGLfloat G_Objects[] = {\n\t-30.0, -30.0, -30.0,\t\n\t30.0, -30.0, -30.0,\t\n\t30.0, 30.0, -30.0,\n\t-30.0, -30.0, -30.0,\n\t30.0, 30.0, -30.0,\n\t-30.0, 30.0, -30.0\n};\n\nfloat G_points[] = {\n\t\t\t  -100.0f,  100.0f, -100.0f,\n\t\t\t  -100.0f, -100.0f, -100.0f,\n\t\t\t   100.0f, -100.0f, -100.0f,\n\t\t\t   100.0f, -100.0f, -100.0f,\n\t\t\t   100.0f,  100.0f, -100.0f,\n\t\t\t  -100.0f,  100.0f, -100.0f,\n\t\t\t  \n\t\t\t  -100.0f, -100.0f,  100.0f,\n\t\t\t  -100.0f, -100.0f, -100.0f,\n\t\t\t  -100.0f,  100.0f, -100.0f,\n\t\t\t  -100.0f,  100.0f, -100.0f,\n\t\t\t  -100.0f,  100.0f,  100.0f,\n\t\t\t  -100.0f, -100.0f,  100.0f,\n\t\t\t  \n\t\t\t   100.0f, -100.0f, -100.0f, \n\t\t\t   100.0f, -100.0f,  100.0f,\n\t\t\t   100.0f,  100.0f,  100.0f,\n\t\t\t   100.0f,  100.0f,  100.0f,\n\t\t\t   100.0f,  100.0f, -100.0f,\n\t\t\t   100.0f, -100.0f, -100.0f,\n\t\t\t   \n\t\t\t  -100.0f, -100.0f,  100.0f,\n\t\t\t  -100.0f,  100.0f,  100.0f,\n\t\t\t   100.0f,  100.0f,  100.0f,\n\t\t\t   100.0f,  100.0f,  100.0f,\n\t\t\t   100.0f, -100.0f,  100.0f,\n\t\t\t  -100.0f, -100.0f,  100.0f,\n\t\t\t  \n\t\t\t  -100.0f,  100.0f, -100.0f,\n\t\t\t   100.0f,  100.0f, -100.0f,\n\t\t\t   100.0f,  100.0f,  100.0f,\n\t\t\t   100.0f,  100.0f,  100.0f,\n\t\t\t  -100.0f,  100.0f,  100.0f,\n\t\t\t  -100.0f,  100.0f, -100.0f,\n\t\t\t  \n\t\t\t  -100.0f, -100.0f, -100.0f,\n\t\t\t  -100.0f, -100.0f,  100.0f,\n\t\t\t   100.0f, -100.0f, -100.0f,\n\t\t\t   100.0f, -100.0f, -100.0f,\n\t\t\t  -100.0f, -100.0f,  100.0f,\n\t\t\t   100.0f, -100.0f,  100.0f\n\t\t\t};\n\n\n/**\n * Timer-Callback.\n * Initiiert Berechnung der aktuellen Position und Farben und anschliessendes\n * Neuzeichnen, setzt sich selbst erneut als Timer-Callback.\n * @param lastCallTime Zeitpunkt, zu dem die Funktion als Timer-Funktion\n *   registriert wurde (In).\n */\nstatic void\ncbTimer (int lastCallTime)\n{\n\t/* Seit dem Programmstart vergangene Zeit in Millisekunden */\n\tint thisCallTime = glutGet (GLUT_ELAPSED_TIME);\n    \n\t/* Seit dem letzten Funktionsaufruf vergangene Zeit in Sekunden */\n\tdouble interval = (double) (thisCallTime - lastCallTime) / 1000.0f;\n\t\t\n\tcalcTimeRelatedStuff(interval);\n\t\t\t\n\t/* Wieder als Timer-Funktion registrieren */\n\tglutTimerFunc (1000 / TIMER_CALLS_PS, cbTimer, thisCallTime);\n\n\t/* Neuzeichnen anstossen */\n\tglutPostRedisplay ();\n    \n}\n\n/**\n * Setzen der Projektionsmatrix.\n * Setzt die Projektionsmatrix unter Berücksichtigung des Seitenverhaeltnisses\n * des Anzeigefensters, sodass das Seitenverhaeltnisse der Szene unveraendert\n * bleibt und gleichzeitig entweder in x- oder y-Richtung der Bereich von -1\n * bis +1 zu sehen ist.\n * @param aspect Seitenverhaeltnis des Anzeigefensters (In).\n */\nstatic void\nsetProjection (GLdouble aspect)\n{\n  /* Nachfolgende Operationen beeinflussen Projektionsmatrix */\n  glMatrixMode (GL_PROJECTION);\n  /* Matrix zuruecksetzen - Einheitsmatrix laden */\n  glLoadIdentity ();\n    \n  {\n      /* perspektivische Projektion */\n      gluPerspective (90.0,     /* Oeffnungswinkel */\n                      aspect,   /* Seitenverhaeltnis */\n                      0.01,      /* nahe ClipPIEng-Ebene */\n                      1000.0 /* ferne ClipPIEng-Ebene */ );\n  }\n}\n\nstatic void drawColoredQuad(double r, double g, double b) {\n\tglDisable(GL_CULL_FACE);\n\tglUseProgram(G_ShaderColor);\n\t\tGLfloat mp[16], mv[16];\n\t\tglGetFloatv(GL_PROJECTION_MATRIX, mp);\n\t\tglGetFloatv(GL_MODELVIEW_MATRIX, mv);\n\t\tglUniformMatrix4fv(glGetUniformLocation(G_ShaderColor, \"projMatrix\"),  1, GL_FALSE, &mp[0]);\n\t\tglUniformMatrix4fv(glGetUniformLocation(G_ShaderColor, \"viewMatrix\"),  1, GL_FALSE, &mv[0]);\n\t\t\n\t\tGLfloat color[] = {r, g, b};\n\t\tGLfloat cam[] = {getCameraPosition(0), getCameraPosition(1), getCameraPosition(2)};\n\t\tglUniform3fv(glGetUniformLocation(G_ShaderColor, \"colorIn\"), 1, color);\n\t\tglUniform3fv(glGetUniformLocation(G_ShaderColor, \"cameraPos\"), 1, cam);\n\t\t\n\t\tglBindBuffer (GL_ARRAY_BUFFER, G_ObjectsBuffer);\n\t\tglEnableVertexAttribArray(0);\n\t\tglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), 0);\n\t\tglDrawArrays(GL_TRIANGLES, 0, 6);\n\t\t\n\t\tglDisableVertexAttribArray(0);\n\t\tglBindBuffer (GL_ARRAY_BUFFER, 0);\n\tglUseProgram(0);\n\tglEnable(GL_CULL_FACE);\n}\n\nstatic void drawSimpleStuff(GLuint colorTex, int fromX, int fromY, int width, int height)   {\n\tglUseProgram(G_ShaderIDSimple);\n\t\t\n\tglBindFramebuffer(GL_FRAMEBUFFER, 0);\n\tglViewport (fromX, fromY, width, height);\t\t\n\tglMatrixMode (GL_PROJECTION);\n\tglLoadIdentity ();\n\tgluPerspective (90.0, 1, 5.1, 1000.0 );\n\tglMatrixMode(GL_MODELVIEW);\n\tglLoadIdentity();\n\n\tgluLookAt (0,0,1,\n\t\t 0.0, 0.0, 0.0,\n\t\t 0.0, 1.0, 0.0);\n\t\n\tglEnable(GL_TEXTURE_2D);\n\tglActiveTexture(GL_TEXTURE0);\n\tglBindTexture(GL_TEXTURE_2D, colorTex);\n\t\n\tGLfloat mp[16], mv[16];\n\tglGetFloatv(GL_PROJECTION_MATRIX, mp);\n\tglGetFloatv(GL_MODELVIEW_MATRIX, mv);\n\tglUniformMatrix4fv(glGetUniformLocation(G_ShaderIDSimple, \"projMatrix\"),  1, GL_FALSE, &mp[0]);\n\tglUniformMatrix4fv(glGetUniformLocation(G_ShaderIDSimple, \"viewMatrix\"),  1, GL_FALSE, &mv[0]);\n\t\n\tglUniform1i(glGetUniformLocation(G_ShaderIDSimple, \"texsampler\"), 0);\n\t\n\tglBindBuffer (GL_ARRAY_BUFFER, G_arrayBuffer);\n\tglEnableVertexAttribArray(0);\n\tglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), 0);\n\tglEnableVertexAttribArray(1);\n\tglVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), 3*sizeof(float));\n\t\n\tglDrawArrays(GL_TRIANGLES, 0, 6);\n\t\n\tglDisableVertexAttribArray(0);\n\tglDisableVertexAttribArray(1);\n\tglBindBuffer (GL_ARRAY_BUFFER, 0);\n\t\n\tglUseProgram(0);\t\n}\n\nstatic void drawSimpleStuffShader(GLuint shader, GLuint colorTex, int fromX, int fromY, int width, int height)   {\n\tglUseProgram(shader);\n\t\t\n\tglBindFramebuffer(GL_FRAMEBUFFER, 0);\n\tglViewport (fromX, fromY, width, height);\t\t\n\tglMatrixMode (GL_PROJECTION);\n\tglLoadIdentity ();\n\tgluPerspective (90.0, 1, 5.1, 1000.0 );\n\tglMatrixMode(GL_MODELVIEW);\n\tglLoadIdentity();\n\n\tgluLookAt (0,0,1,\n\t\t 0.0, 0.0, 0.0,\n\t\t 0.0, 1.0, 0.0);\n\t\n\tglEnable(GL_TEXTURE_2D);\n\tglActiveTexture(GL_TEXTURE0);\n\tglBindTexture(GL_TEXTURE_2D, colorTex);\n\t\n\tGLfloat mp[16], mv[16];\n\tglGetFloatv(GL_PROJECTION_MATRIX, mp);\n\tglGetFloatv(GL_MODELVIEW_MATRIX, mv);\n\tglUniformMatrix4fv(glGetUniformLocation(G_ShaderIDSimple, \"projMatrix\"),  1, GL_FALSE, &mp[0]);\n\tglUniformMatrix4fv(glGetUniformLocation(G_ShaderIDSimple, \"viewMatrix\"),  1, GL_FALSE, &mv[0]);\n\t\n\tglUniform1i(glGetUniformLocation(G_ShaderIDSimple, \"texsampler\"), 0);\n\t\n\tglBindBuffer (GL_ARRAY_BUFFER, G_arrayBuffer);\n\tglEnableVertexAttribArray(0);\n\tglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), 0);\n\tglEnableVertexAttribArray(1);\n\tglVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), 3*sizeof(float));\n\t\n\tglDrawArrays(GL_TRIANGLES, 0, 6);\n\t\n\tglDisableVertexAttribArray(0);\n\tglDisableVertexAttribArray(1);\n\tglBindBuffer (GL_ARRAY_BUFFER, 0);\n\t\n\tglUseProgram(0);\t\n}\n\nvoid drawTerrainComplete(void) {\n\tglUseProgram(G_ShaderIDSimple);\n\t\n\tglActiveTexture(GL_TEXTURE0);\n\tglBindTexture(GL_TEXTURE_2D, G_TexImageGrass);\n\tglActiveTexture(GL_TEXTURE1);\n\tglBindTexture(GL_TEXTURE_2D, G_TexImageSand);\n\tglActiveTexture(GL_TEXTURE0+2);\n\tglBindTexture(GL_TEXTURE_2D, G_TexImageForest);\n\tglActiveTexture(GL_TEXTURE0+3);\n\tglBindTexture(GL_TEXTURE_2D, G_TexImageRocks);\n\tglActiveTexture(GL_TEXTURE0+4);\n\tglBindTexture(GL_TEXTURE_2D, G_TexImageSnow);\n\tglActiveTexture(GL_TEXTURE0+5);\n\tglBindTexture(GL_TEXTURE_2D, G_TexImageTundra);\n\t\t\n\tGLfloat mp[16], mv[16];\n\tglGetFloatv(GL_PROJECTION_MATRIX, mp);\n\tglGetFloatv(GL_MODELVIEW_MATRIX, mv);\n\tglUniformMatrix4fv(glGetUniformLocation(G_ShaderIDSimple, \"projMatrix\"),  1, GL_FALSE, &mp[0]);\n\tglUniformMatrix4fv(glGetUniformLocation(G_ShaderIDSimple, \"viewMatrix\"),  1, GL_FALSE, &mv[0]);\n\t\t \n\tglUniform1i(glGetUniformLocation(G_ShaderIDSimple, \"texSand\") , 1);\n\tglUniform1i(glGetUniformLocation(G_ShaderIDSimple, \"texGrass\"), 0);\n\tglUniform1i(glGetUniformLocation(G_ShaderIDSimple, \"texForest\"), 2);\n\tglUniform1i(glGetUniformLocation(G_ShaderIDSimple, \"texRocks\"), 3);\n\tglUniform1i(glGetUniformLocation(G_ShaderIDSimple, \"texSnow\"), 4);\n\tglUniform1i(glGetUniformLocation(G_ShaderIDSimple, \"texTundra\"), 5);\n\t\n\t/* Wasser-Normalen für eigene Caustics-Berechnungen */\n\t\tglBindBuffer (GL_ARRAY_BUFFER, G_CausticsBuffer);\n\t\tglBufferData (GL_ARRAY_BUFFER, sizeof(*getTerrainCaustics())*TERRAIN_SIZE*TERRAIN_SIZE, getTerrainCaustics(), GL_STREAM_DRAW);\n\t\tglEnableVertexAttribArray(3);\n\t\tglVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 5*sizeof(GLfloat));\n\t\t\n\t/* Offset in X und Z-Richtung eventuell hier in die Shader übergeben... */\n\t\n\tglBindBuffer (GL_ARRAY_BUFFER, G_TerrainBuffer);\n\tglEnableVertexAttribArray(0);\n\tglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 0);\n\tglEnableVertexAttribArray(1);\n\tglVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 3*sizeof(GLfloat));\n\tglEnableVertexAttribArray(2);\n\tglVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 5*sizeof(GLfloat));\n\t\n\tglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, G_TerrainBufferIndex);\n\tglDrawElements(GL_TRIANGLES, TERRAIN_SIZE*TERRAIN_SIZE*2*3, GL_UNSIGNED_INT, 0);\n\t\n\tglDisableVertexAttribArray(0);\n\tglDisableVertexAttribArray(1);\n\tglDisableVertexAttribArray(2);\n\tglDisableVertexAttribArray(3);\n\t\n\tglUseProgram(0);\n\t\n}\n\nvoid drawSceneToTexture(GLuint tex, GLfloat ex, GLfloat ey, GLfloat ez, GLfloat cx, GLfloat cy, GLfloat cz) {\n\tglBindFramebuffer(GL_FRAMEBUFFER, tex);\t\n\tglClearColor(0.0, 1.0, 1.0, 0.0);\n\tglClearDepth(1.0f);\n\tglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\t\n\tglViewport (0, 0, G_Width, G_Height);\t\t\n\tsetProjection (1);\n\tglMatrixMode(GL_MODELVIEW);\n\tglLoadIdentity();\n\tgluLookAt (\tex, ey, ez,\n\t\t cx, cy, cz,\n\t\t 0.0, 1.0, 0.0);\n\n\tglDisable(GL_TEXTURE_2D);\n\tif (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {\n\t\tprintf (\"Framebuffer ist nicht korrekt! 4\\n\");\n\t}\n\n\t/*drawSides();*/\n\tdrawTerrainComplete();\n\t\n}\n\n\nvoid allocateMemoryStuff(GLuint * texID, GLuint * fbo) {\n\t\n\tglGenTextures(1, texID);\n\tglBindTexture(GL_TEXTURE_2D, *texID);\n\t\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\n\t/*glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);*/\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\t\n\t/*glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);\t*/\n\tglTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);\n\t\n\tglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, G_Width, G_Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);\n\t\n\tglGenFramebuffers(1, fbo);\n\tglBindFramebuffer(GL_FRAMEBUFFER, *fbo);\t\n\t\n\tglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texID, 0);\n\tglBindFramebuffer(GL_FRAMEBUFFER, 0);\n}\n\nvoid allocateMemoryStuffDepth(GLuint * texID, GLuint * texID2, GLuint * fbo) {\n\t\n\tglGenTextures(1, texID);\n\tglBindTexture(GL_TEXTURE_2D, *texID);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\t\n\tglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, G_Width, G_Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);\n\t\n\tglGenTextures(1, texID2);\n\tglBindTexture(GL_TEXTURE_2D, *texID2);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\t\n\tglTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, G_Width, G_Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);\n\t\n\tglGenFramebuffers(1, fbo);\n\tglBindFramebuffer(GL_FRAMEBUFFER, *fbo);\t\n\t\n\tglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texID, 0);\n\tglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, *texID2, 0);\n\tglBindFramebuffer(GL_FRAMEBUFFER, 0);\n}\n\nvoid loadCubeSide(GLuint * texID, GLenum side) {\n\t/*glBindTexture(GL_TEXTURE_CUBE_MAP, *texID);*/\n\t\n\tglTexImage2D(side, 0, GL_RGBA8, G_Width, G_Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);\t\n}\n\nvoid appendTexToFB(GLuint * fbo, GLuint * texID, GLenum side) {\n\tglGenFramebuffers(1, fbo);\n\tglBindFramebuffer(GL_FRAMEBUFFER, *fbo);\t\t\n\tglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, side, *texID, 0);\n\tglBindFramebuffer(GL_FRAMEBUFFER, 0);\n}\n\nvoid allocateMemoryStuffCube(GLuint * texID) {\n\tglActiveTexture (GL_TEXTURE0);\n\tglGenTextures(1, texID);\n\t\n\t\n\tglBindTexture(GL_TEXTURE_CUBE_MAP, *texID);\n\t\n\tglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);\n\tglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\n\tglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\n\tglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n\tglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\n\tglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); \n\tglTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);\n\t\n\tloadCubeSide(texID, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); /* front  */\n\tloadCubeSide(texID, GL_TEXTURE_CUBE_MAP_POSITIVE_Z); /* back   */\n\tloadCubeSide(texID, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y); /* bottom */\n\tloadCubeSide(texID, GL_TEXTURE_CUBE_MAP_POSITIVE_Y); /* top    */\n\tloadCubeSide(texID, GL_TEXTURE_CUBE_MAP_NEGATIVE_X); /* left   */\n\tloadCubeSide(texID, GL_TEXTURE_CUBE_MAP_POSITIVE_X); /* right  */\n\t\n\tappendTexToFB(&G_TexCubeFront, texID, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);\n\tappendTexToFB(&G_TexCubeBack,  texID, GL_TEXTURE_CUBE_MAP_POSITIVE_Z);\n\tappendTexToFB(&G_TexCubeBottom,texID, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);\n\tappendTexToFB(&G_TexCubeTop,   texID, GL_TEXTURE_CUBE_MAP_POSITIVE_Y);\n\tappendTexToFB(&G_TexCubeLeft,  texID, GL_TEXTURE_CUBE_MAP_NEGATIVE_X);\n\tappendTexToFB(&G_TexCubeRight, texID, GL_TEXTURE_CUBE_MAP_POSITIVE_X);\n\t\n\t\n\tif (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {\n\t\tprintf (\"Framebuffer ist nicht korrekt 1!\\n\");\n\t}\n\t\n\tglBindFramebuffer(GL_FRAMEBUFFER, 0);\n}\n\nvoid renderFBToCubeTexture(GLuint * fbo, GLenum side, double vX, double vY, double vZ) {\n\t/*==================================================================*/\n\t/* Eine Seite für die Cube-Textur rendern */\n\t/*==================================================================*/\n\tglBindFramebuffer(GL_FRAMEBUFFER, *fbo);\t\n\tglClearColor(0.0, 1.0, 1.0, 0.0);\n\tglClearDepth(1.0f);\n\tglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\tglViewport (0, 0, G_Width, G_Height);\t\t\n\tsetProjection(1);\n\tglMatrixMode(GL_MODELVIEW);\n\tglLoadIdentity();\n\t\n\tgluLookAt (0, 0, 0,\n\t\t vX, vY, vZ,\n\t\t 0.0, fabs(vY) > 0.8 ? 0.0 : 1.0, vY > 0.8 ? 1.0 : (vY < -0.8 ? -1.0 : 0.0));\n\n\tglDisable(GL_TEXTURE_2D);\n\tif (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {\n\t\tprintf (\"Framebuffer ist nicht korrekt! 2\\n\");\n\n\t}\n\t\n\t/*drawColoredQuad(1,1,1);*/\n\t/*drawSides();*/\n\t\n\t/* RAUS, WEIL EIGENTLICH NUR DIE ENTFERNTE UMGEBUNG HIER WAHRGENOMMEN WERDEN SOLL UND  NICHT DIE KONKRETEN, DYNAMISCHEN OBJEKTE DER SCENE!!!!!!! */\n\t/*drawTerrainComplete();*/\n}\n\n\n\n/**\n * Zeichen-Callback.\n * Loescht die Buffer, ruft das Zeichnen der Szene auf und tauscht den Front-\n * und Backbuffer.\n */\nstatic void\ncbDisplay (void)\n{\n\tglBindFramebuffer(GL_FRAMEBUFFER, 0);\n\tglClearColor(0.0, 1.0, 1.0, 0.0);\n\tglClearDepth(1.0f);\n\tglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\n\t/*==================================================================*/\n\t/* Textur mit Kamera-Perspektive */\n\t/*==================================================================*/\n\tdrawSceneToTexture(G_fboCam, getCameraPosition(0), getCameraPosition(1), getCameraPosition(2), 0.0, 0.0, 0.0);\n\t\n\t/*==================================================================*/\n\t/* Textur mit Reflection-Perspektive */\n\t/*==================================================================*/\n\t/*drawSceneToTexture(G_fboRefl, 0.0, 0.0, 0.0,\n\t\t getCameraPosition(0)+(2*-getCameraPosition(0)), \n\t\t getCameraPosition(1)+(2*-getCameraPosition(1))+2*getCameraPosition(1), \n\t\t getCameraPosition(2)+(2*-getCameraPosition(2)));*/\n\t\n\t/*==================================================================*/\n\t/* Kamera-Textur rendern. */\n\t/*==================================================================*/\n\tif (0) {\n\t\tdrawSimpleStuff(G_fboCam, 0, G_Height/2, G_Width/2, G_Height/2);\n\t}\n\tif (0) {\n\t\tdrawSimpleStuffShader(G_ShaderIDSimpleD, G_TexCameraDepth, 0, 0, G_Width/2, G_Height/2);\n\t}\n\t\n\t/*==================================================================*/\n\t/* Reflection-Textur rendern */\n\t/*==================================================================*/\n\tif (0) {\n\t\tdrawSimpleStuff(G_TexReflection, G_Width/2, G_Height/2, G_Width/2, G_Height/2);\n\t}\n\n\t/*==================================================================*/\n\t/* Spiegelfläche mit korrektem dynamischen Environment-Mapping (Reflection + Refraction) */\n\t/*==================================================================*/\n\tif (0) {\t\t\t\n\t\tglUseProgram(G_ShaderID);\n\t\t\tglBindFramebuffer(GL_FRAMEBUFFER, 0);\n\t\t\tglViewport (0, 0, G_Width/2, G_Height/2);\t\t\n\t\t\tsetProjection (1);\n\t\t\tglMatrixMode(GL_MODELVIEW);\n\t\t\tglLoadIdentity();\n\t\t\tgluLookAt (getCameraPosition(0), getCameraPosition(1), getCameraPosition(2),\n\t\t\t\t 0.0, 0.0, 0.0,\n\t\t\t\t 0.0, 1.0, 0.0);\n\t\t\t\n\t\t\tglEnable(GL_TEXTURE_CUBE_MAP);\n\t\t\tglEnable(GL_TEXTURE_2D);\n\t\t\t\n\t\t\tglActiveTexture(GL_TEXTURE0);\n\t\t\tglBindTexture(GL_TEXTURE_CUBE_MAP, G_TexCube);\n\t\t\t\n\t\t\tGLfloat mp[16], mv[16];\n\t\t\tglGetFloatv(GL_PROJECTION_MATRIX, mp);\n\t\t\tglGetFloatv(GL_MODELVIEW_MATRIX, mv);\n\t\t\tglUniformMatrix4fv(glGetUniformLocation(G_ShaderID, \"projMatrix\"),  1, GL_FALSE, &mp[0]);\n\t\t\tglUniformMatrix4fv(glGetUniformLocation(G_ShaderID, \"viewMatrix\"),  1, GL_FALSE, &mv[0]);\n\t\t\t\n\t\t\tglUniform1i(G_sampler2dLoc, 0);\n\t\t\t\n\t\t\tGLfloat cam_pos[] = {getCameraPosition(0), getCameraPosition(1), getCameraPosition(2)};\n\t\t\tglUniform3fv(glGetUniformLocation(G_ShaderID, \"cameraPos\"), 1, cam_pos);\n\t\t\t\n\t\t\tglBindBuffer (GL_ARRAY_BUFFER, G_WaterBuffer);\n\t\t\tglBufferData (GL_ARRAY_BUFFER, sizeof(*getWaterList())*WORLD_SIZE*WORLD_SIZE, getWaterList(), GL_STATIC_DRAW);\n\t\t\tglEnableVertexAttribArray(0);\n\t\t\tglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat)+1*sizeof(GLint), 0);\n\t\t\tglEnableVertexAttribArray(1);\n\t\t\tglVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat)+1*sizeof(GLint), 5*sizeof(GLfloat));\n\t\t\t\n\t\t\tglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, G_WaterBufferIndex);\n\t\t\t\n\t\t\t/* Wasser. */\n\t\t\tglDrawElements(GL_TRIANGLES, WORLD_SIZE*WORLD_SIZE*2*3, GL_UNSIGNED_INT, 0);\n\t\t\t\n\t\t\tglDisableVertexAttribArray(0);\n\t\t\tglDisableVertexAttribArray(1);\n\t\t\tglDisable(GL_TEXTURE_CUBE_MAP);\n\t\t\tglDisable(GL_TEXTURE_2D);\n\t\t\t\n\t\tglUseProgram(0);\n\t\t\n\t\t/*drawSides();*/\n\t\tdrawTerrainComplete();\n\t\t\n\t\t\n\t}\n\t\n\t/*==================================================================*/\n\t/* Spiegelfläche mit Screenspace-Reflections */\n\t/*==================================================================*/\n\tif (1) {\t\t\t\n\t\tint toX = G_fullScreen ? G_Width : G_Width/2, \n\t\t\ttoZ = G_fullScreen ? G_Height : G_Height/2;\n\t\tglUseProgram(G_ShaderID);\n\t\t\tglBindFramebuffer(GL_FRAMEBUFFER, 0);\n\t\t\tglViewport (0, 0, toX, toZ);\n\t\t\tsetProjection (1);\n\t\t\tglMatrixMode(GL_MODELVIEW);\n\t\t\tglLoadIdentity();\n\t\t\tgluLookAt (getCameraPosition(0), getCameraPosition(1), getCameraPosition(2),\n\t\t\t\t 0.0, 0.0, 0.0,\n\t\t\t\t 0.0, 1.0, 0.0);\n\t\t\t\n\t\t\tglActiveTexture(GL_TEXTURE1);\n\t\t\tglBindTexture(GL_TEXTURE_2D, G_TexCamera);\n\t\t\tglActiveTexture(GL_TEXTURE0);\n\t\t\tglBindTexture(GL_TEXTURE_2D, G_TexCameraDepth);\n\t\t\tglActiveTexture(GL_TEXTURE2);\n\t\t\tglBindTexture(GL_TEXTURE_CUBE_MAP, G_TexCube);\n\t\t\t\n\t\t\tGLfloat mp[16], mv[16];\n\t\t\tglGetFloatv(GL_PROJECTION_MATRIX, mp);\n\t\t\tglGetFloatv(GL_MODELVIEW_MATRIX, mv);\n\t\t\tglUniformMatrix4fv(glGetUniformLocation(G_ShaderID, \"projMatrix\"),  1, GL_FALSE, &mp[0]);\n\t\t\tglUniformMatrix4fv(glGetUniformLocation(G_ShaderID, \"viewMatrix\"),  1, GL_FALSE, &mv[0]);\n\t\t\t\n\t\t\tglUniform1i(G_sampler2dLoc, 1);\n\t\t\tglUniform1i(G_samplerDepth2dLoc, 0);\n\t\t\tglUniform1i(G_samplerCubeLoc, 2);\n\t\t\t\n\t\t\tGLfloat cam_pos[] = {getCameraPosition(0), getCameraPosition(1), getCameraPosition(2)};\n\t\t\tglUniform3fv(glGetUniformLocation(G_ShaderID, \"cameraPos\"), 1, cam_pos);\n\t\t\t\n\t\t\t/*glBindBuffer (GL_ARRAY_BUFFER, G_TerrainBuffer);\n\t\t\tglEnableVertexAttribArray(2);\n\t\t\tglVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 0);*/\n\t\t\t\n\t\t\tglBindBuffer (GL_ARRAY_BUFFER, G_WaterBuffer);\n\t\t\tglBufferData (GL_ARRAY_BUFFER, sizeof(*getWaterList())*WORLD_SIZE*WORLD_SIZE, getWaterList(), GL_STATIC_DRAW);\n\t\t\tglEnableVertexAttribArray(0);\n\t\t\tglVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat)+1*sizeof(GLint), 0);\n\t\t\tglEnableVertexAttribArray(1);\n\t\t\tglVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat)+1*sizeof(GLint), 5*sizeof(GLfloat));\n\t\t\t\n\t\t\tglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, G_WaterBufferIndex);\n\t\t\t\n\t\t\t/* Wasser. */\n\t\t\tglDrawElements(GL_TRIANGLES, WORLD_SIZE*WORLD_SIZE*2*3, GL_UNSIGNED_INT, 0);\n\t\t\t\n\t\t\tglDisableVertexAttribArray(0);\n\t\t\tglDisableVertexAttribArray(1);\n\t\t\t\n\t\tglUseProgram(0);\n\t\t\n\t\t/*drawSides();*/\n\t\tdrawTerrainComplete();\n\t\tdrawFPS();\n\t}\n\t\n\t/*==================================================================*/\n\t/* Landschaft aus Perlin-Noise. */\n\t/*==================================================================*/\n\tif (!G_fullScreen) {\n\t\tglBindFramebuffer(GL_FRAMEBUFFER, 0);\n\t\tglViewport (G_Width/2, G_Height/2, G_Width/2, G_Height/2);\n\t\tsetProjection (1);\n\t\tglMatrixMode(GL_MODELVIEW);\n\t\tglLoadIdentity();\n\t\tgluLookAt (getCameraPosition(0), getCameraPosition(1), getCameraPosition(2),\n\t\t\t 0.0, 0.0, 0.0,\n\t\t\t 0.0, 1.0, 0.0);\n\t\t\t \n\t\tdrawTerrainComplete();\n\t}\n\n\t/*==================================================================*/\n\t/* Die Normale Scene auf der rechten Seite rendern. Echte Polygone etc. */\n\t/*==================================================================*/\n\tif (0) {\n\t\tglUseProgram(0);\n\t\tglBindFramebuffer(GL_FRAMEBUFFER, 0);\n\t\tglViewport (0, G_Height/2, G_Width/2, G_Height/2);\t\t\n\t\tsetProjection (1);\n\t\tglMatrixMode(GL_MODELVIEW);\n\t\tglLoadIdentity();\n\n\t\tgluLookAt (getCameraPosition(0), getCameraPosition(1), getCameraPosition(2),\n\t\t\t 0.0, 0.0, 0.0,\n\t\t\t 0.0, 1.0, 0.0);\t\t\n\t\t\t\n\t\tglDisable(GL_TEXTURE_2D);\n\t\t\n\t\tdrawSides();\n\t\tdrawWaterSurface();\t\t\n\t}\t\n\t\n\t/* Alles fertig. */\n\tglutSwapBuffers ();\n}\n\n/**\n * Callback fuer Tastendruck.\n * Ruft Ereignisbehandlung fuer Tastaturereignis auf.\n * @param key betroffene Taste (In).\n * @param x x-Position der Maus zur Zeit des Tastendrucks (In).\n * @param y y-Position der Maus zur Zeit des Tastendrucks (In).\n */\nvoid cbKeyboard (unsigned char key, int x, int y)\n{\n\t\n\tswitch (key)\n\t{\n\t\tcase 'q':\n\t\tcase 'Q':\n\t\tcase ESC:\n\t\t\texit (0);\n\t\t\tbreak;\n\t\tcase 'r':\n        case 'R':\n\t\t\t/*initGame ();*/\n\t\t\tsetRandomize();\n\t\t\tbreak;\n\t\tcase 'h':\n        case 'H':\n            setHelpStatus(!getHelpStatus());\n            break;\n        case '+':\n            incQuadCount();\n            break;\n        case '-':\n            decQuadCount();\n            break;\n        case 'n':\n\t\tcase 'N':\n\t\t\tpushSomeWaterDown();\n            break;\n        case 'w':\n        case 'W':\n\t\t\ttoggleWaterMovement();\n\t\t\tbreak;\n        case 'm':\n\t\tcase 'M':\n\t\t\ttoggleSpheresMoving ();\n            break;\n\t\tcase 'p':\n        case 'P':\n            toggleParticleFreeze ();\n            break;\n\t\tcase 'f':\n        case 'F':\n            G_fullScreen = !G_fullScreen;\n            break;\n        case 's':\n        case 'S':\n            toggleShadows ();\n            break;    \n        case 'k':\n        case 'K':\n\t\t\tprintf (\"k recognized.\\n\");\n            startMovingBall ();\n            break;   \n        case 'v':\n        case 'V':\n            view = !view;\n            break;  \n            \n\t}\t\n}\n\n/* Spezialtasten-Druck-Callback - wird ausgefuehrt, wenn Spezialtaste\n* (F1 - F12, Links, Rechts, Oben, Unten, Bild-Auf, Bild-Ab, Pos1, Ende oder\n* Einfuegen) gedrueckt wird */\nvoid cbSpecial (int key, int x, int y)\n{\n\tswitch (key)\n\t{\n        case GLUT_KEY_LEFT: \n\n\t\t\tbreak;\n\t\tcase GLUT_KEY_RIGHT:\n\n\t\t\tbreak;\n\t\tcase GLUT_KEY_UP:\n            setKey (1, 1);\n\t\t\tbreak;\n\t\tcase GLUT_KEY_DOWN:\n            setKey(0,1);\n\t\t\tbreak;\n\t\tcase GLUT_KEY_F1:\n            toggleWireframeMode();\n\t\t\tbreak;\n        case GLUT_KEY_F2:\n            setLightStatus(!getLightStatus());\n            break;\n\t\tcase GLUT_KEY_F3:\n            setTextureStatus(!getTextureStatus());\n\t\t\tbreak;\n        case GLUT_KEY_F4:\n\n            break;\n        case GLUT_KEY_F5:\n\n            break;\n        case GLUT_KEY_F6:\n\n            break;\n        case GLUT_KEY_F7:\n\n            break;\n        case GLUT_KEY_F8:\n\n            break;\n\t}\n}\n\n/* Wird aufgerufen, wenn eine Spezialtaste wieder losgelassen wird1 */\nvoid cbUpSpecial (int key, int x, int y)\n{\n\tswitch (key)\n\t{\n\t\tcase GLUT_KEY_LEFT: \n\n\t\t\tbreak;\n\t\tcase GLUT_KEY_RIGHT:\n\n\t\t\tbreak;\n\t\tcase GLUT_KEY_UP:\n            setKey (1,0);\n\t\t\tbreak;\n\t\tcase GLUT_KEY_DOWN:\n            setKey (0,0);\n\t\t\tbreak;\n\t}\n}\n\n/**\n * Verarbeitung eines Mausereignisses.\n * Durch Bewegung der Maus bei gedrueckter Maustaste kann die aktuelle\n * Zeichenfarbe beeinflusst werden.\n * Falls Debugging aktiviert ist, wird jedes Mausereignis auf stdout\n * ausgegeben.\n * @param x x-Position des Mauszeigers zum Zeitpunkt der Ereignisausloesung.\n * @param y y-Position des Mauszeigers zum Zeitpunkt der Ereignisausloesung.\n * @param eventType Typ des Ereignisses.\n * @param button ausloesende Maustaste (nur bei Ereignissen vom Typ mouseButton).\n * @param buttonState Status der Maustaste (nur bei Ereignissen vom Typ mouseButton).\n */\nstatic void\nhandleMouseEvent (int x, int y, CGMouseEventType eventType, int button, int buttonState)\n{\n    switch (eventType)\n    {\n        case mouseButton:\n            switch (button)\n            {\n                case GLUT_LEFT_BUTTON:\n                    setMouseEvent(MOVE,x,y);\n                break;\n                case GLUT_RIGHT_BUTTON:\n                    setMouseEvent(ZOOM,x,y);\n                break;\n                default:\n                  break;\n            }\n        break;\n        default:\n          break;\n    }\n    if (buttonState)\n        setMouseEvent(NONE,x,y);\n\n}\n\n/**\n * Mouse-Button-Callback.\n * @param button Taste, die den Callback ausgeloest hat.\n * @param state Status der Taste, die den Callback ausgeloest hat.\n * @param x X-Position des Mauszeigers beim Ausloesen des Callbacks.\n * @param y Y-Position des Mauszeigers beim Ausloesen des Callbacks.\n */\nstatic void\ncbMouseButton (int button, int state, int x, int y)\n{\n\thandleMouseEvent (x, y, mouseButton, button, state);\n}\n\nvoid mouseMovement(int x, int y) \n{\n    \n    if (getMouseEvent() == MOVE)\n\t\tsetCameraMovement(x,y);\n\t\n    if (getMouseEvent() == ZOOM)\n        setCameraZoom(x,y);\n}\n\n\n\n\n/**\n * Callback fuer Aenderungen der Fenstergroesse.\n * Initiiert Anpassung der Projektionsmatrix an veraenderte Fenstergroesse.\n * @param w Fensterbreite (In).\n * @param h Fensterhoehe (In).\n */\nstatic void\ncbReshape (int w, int h)\n{\n  /* Das ganze Fenster ist GL-Anzeigebereich */\n  glViewport (0, 0, (GLsizei) w, (GLsizei) h);\n\n  /* Anpassen der Projektionsmatrix an das Seitenverhaeltnis des Fensters */\n  setProjection ((GLdouble) w / (GLdouble) h);\n}\n\n/**\n * Registrierung der GLUT-Callback-Routinen.\n */\nstatic void registerCallBacks (void)\n{\n    /* Mouse-Button-Callback (wird ausgefuehrt, wenn eine Maustaste\n     *  gedrueckt oder losgelassen wird) */\n    glutMouseFunc (cbMouseButton);\n    \n    glutMotionFunc(mouseMovement);\n\t\n\t/* Timer-Callback - wird einmalig nach msescs Millisekunden ausgefuehrt */\n\tglutTimerFunc (1000 / TIMER_CALLS_PS, /* msecs - bis Aufruf von func */\n                 cbTimer,       /* func  - wird aufgerufen    */\n                 glutGet (GLUT_ELAPSED_TIME));  /* value - Parameter, mit dem\n                                                   func aufgerufen wird */\n\n\t/* Reshape-Callback - wird ausgefuehrt, wenn neu gezeichnet wird (z.B. nach\n\t* Erzeugen oder Groessenaenderungen des Fensters) */\n\tglutReshapeFunc (cbReshape);\n\n\t/* Display-Callback - wird an mehreren Stellen imlizit (z.B. im Anschluss an\n\t* Reshape-Callback) oder explizit (durch glutPostRedisplay) angestossen */\n\tglutDisplayFunc (cbDisplay);\n\t\n\t/* Tasten-Druck-Callback - wird ausgefuehrt, wenn eine Taste gedrueckt wird */\n\tglutKeyboardFunc (cbKeyboard);\n\t\n\t/* Spezialtasten-Druck-Callback - wird ausgefuehrt, wenn Spezialtaste\n\t* (F1 - F12, Links, Rechts, Oben, Unten, Bild-Auf, Bild-Ab, Pos1, Ende oder\n\t* Einfuegen) gedrueckt wird */\n\tglutSpecialFunc (cbSpecial);\n\t\n    /* Wird aufgerufen, wenn eine Taste wieder losgelassen wird! */\n\tglutSpecialUpFunc(cbUpSpecial);\n    \n\t/* Automat. Tastendruckwiederholung ignorieren */\n\tglutIgnoreKeyRepeat (1);\n    \n    /* Wenn die Fenstergröße verändert wird. */\n    /*glutReshapeFunc(cgReshape);*/\n}\n\nint readFile (char * name, char ** buffer) {\n\tFILE *f = fopen(name, \"rb\");\n\tfseek(f, 0, SEEK_END);\n\tint pos = ftell(f);\n\tfseek(f, 0, SEEK_SET);\n\n\t(*buffer) = malloc(pos+1);\n\tfread(*buffer, pos-1, 1, f);\n\t(*buffer)[pos-1] = '\\0';\n\tfclose(f);\n}\n\nGLuint loadShaders(char * vertexShader, char * fragmentShader){\n \n    /* Create the shaders */\n    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);\n    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);\n \n\t/* Read Shader from File was here */\n \n    GLint Result = GL_FALSE;\n    int InfoLogLength;\n \n    /* Compile Vertex Shader */\n    printf(\"Compiling Vertex shader\\n\");\n    char * VertexSourcePointer = NULL;\n    readFile(vertexShader, &VertexSourcePointer);\n    \n    glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);\n    glCompileShader(VertexShaderID);\n \n    /* Check Vertex Shader */\n    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);\n    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);\n    char * vertexShaderErrorMessage = calloc(InfoLogLength, sizeof(char));\n    glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &(vertexShaderErrorMessage[0]));\n    fprintf(stdout, \"vertexShaderErrorMessage: %s\\n\", vertexShaderErrorMessage);\n \n    /* Compile Fragment Shader */\n    printf(\"Compiling Fragment shader\\n\");\n    char * FragmentSourcePointer = NULL;\n    readFile(fragmentShader, &FragmentSourcePointer);\n    \n    /*printf (\"FragmentShader: \\n\\\"%s\\\"\\n\", FragmentSourcePointer);*/\n    \n    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);\n    glCompileShader(FragmentShaderID);\n \n    /* Check Fragment Shader */\n    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);\n    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);\n    char * fragmentShaderErrorMessage = calloc(InfoLogLength, sizeof(char));\n    glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &(fragmentShaderErrorMessage[0]));\n    fprintf(stdout, \"fragmentShaderErrorMessage: %s\\n\", fragmentShaderErrorMessage);\n \n    /*  Link the program */\n    GLuint ProgramID = glCreateProgram();\n    \n    glAttachShader(ProgramID, VertexShaderID);\n    \n    glAttachShader(ProgramID, FragmentShaderID);\n    \n    glLinkProgram(ProgramID);\n    \n    /* Check the program */\n    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);\n    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);\n    char * programErrorMessage = calloc(InfoLogLength, sizeof(char));\n    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &(programErrorMessage[0]));\n    fprintf(stdout, \"programErrorMessage: %s\\n\", programErrorMessage);\n \n    glDeleteShader(VertexShaderID);\n    glDeleteShader(FragmentShaderID);\n \n    return ProgramID;\n}\n\nint loadTextureImage(Image * image, char * name, GLuint * tex) {\n\t\n\tif (!imageLoad(name, image)) \n\t{\n\t\tprintf(\"Error reading image file\");\n\t\texit(1);\n\t}        \n\t\n\tglGenTextures(1, tex);\n\tglBindTexture(GL_TEXTURE_2D, *tex);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);\n\tglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);\n\t\n\tglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image->sizeX, image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image->data);\t\n}\n\n/**\n * Initialisiert das Programm (inkl. I/O und OpenGL) und startet die\n * Ereignisbehandlung.\n * @param title Beschriftung des Fensters\n * @param width Breite des Fensters\n * @param height Hoehe des Fensters\n * @return ID des erzeugten Fensters, 0 im Fehlerfall\n */\nint initAndStartIO (char *title, int width, int height)\n{\n\tint windowID = 0;\n\t\n\t/* Kommandozeile immitieren */\n\tint argc = 1;\n\tchar *argv = \"cmd\";\n\t\n\tG_Width = width;\n\tG_Height = height;\n\n\t/* Glut initialisieren */\n\tglutInit (&argc, &argv);\n\t\n\t/* FensterInitialisierung */\n\tglutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);\n\t/* FensterGröße */\n\tglutInitWindowSize (G_Width, G_Height);\n\t/* FensterPosition */\n\tglutInitWindowPosition (0, 0);\n\t\n\twindowID = glutCreateWindow (title);\n\t\n\tif (windowID)\n\t{\n\t\t/* Hintergrund und so werden initialisiert (Farben) */\n\t\tif (initScene ())\n\t\t{\n\t\t\tG_ShaderID = loadShaders(\"waterVertexShader.vert\", \"waterFragmentShader.frag\");\n\t\t\tG_ShaderIDSimple = loadShaders(\"textureVertexShader.vert\", \"textureFragmentShader.frag\");\n\t\t\tG_ShaderIDSimpleD = loadShaders(\"textureVertexShader.vert\", \"textureDepthFragmentShader.frag\");\n\t\t\tG_ShaderColor = loadShaders(\"colorVertexShader.vert\", \"colorFragmentShader.frag\");\n           \n\t\t\tregisterCallBacks ();\n\t\t\t\n\t\t\tallocateMemoryStuffDepth(&G_TexCamera, &G_TexCameraDepth, &G_fboCam);\n\t\t\tallocateMemoryStuff(&G_TexReflection, &G_fboRefl);\n\t\t\tallocateMemoryStuff(&G_TexRefraction, &G_fboRefr);\n\t\t\t\n\t\t\tallocateMemoryStuffCube(&G_TexCube);\n\n\t\t\tG_sampler2dLoc  \t\t= glGetUniformLocation(G_ShaderID, \"texsampler\");\n\t\t\tG_samplerDepth2dLoc  \t= glGetUniformLocation(G_ShaderID, \"texsamplerDepth\");\n\t\t\tG_samplerCubeLoc\t  \t= glGetUniformLocation(G_ShaderID, \"texsamplerCube\");\n\t\t\t\n\t\t\tImage * imageSand, * imageGrass, * imageCaustics, * imageRocks, * imageSnow, * imageForest, * imageTundra;\n\t\t\timageSand  = malloc(sizeof(Image));\n\t\t\timageGrass = malloc(sizeof(Image));\n\t\t\timageCaustics = malloc(sizeof(Image));\n\t\t\timageRocks = malloc(sizeof(Image));\n\t\t\timageSnow = malloc(sizeof(Image));\n\t\t\timageForest = malloc(sizeof(Image));\n\t\t\timageTundra = malloc(sizeof(Image));\n\t\t\t\n\t\t\tloadTextureImage(imageSand,  \"sand1.bmp\", &G_TexImageSand );\n\t\t\tloadTextureImage(imageGrass, \"gras2.bmp\", &G_TexImageGrass);\n\t\t\tloadTextureImage(imageCaustics, \"caustics.bmp\", &G_TexImageCaustics);\n\t\t\tloadTextureImage(imageRocks, \"rocks.bmp\", &G_TexImageRocks);\n\t\t\tloadTextureImage(imageSnow, \"snow.bmp\", &G_TexImageSnow);\n\t\t\tloadTextureImage(imageForest, \"forest.bmp\", &G_TexImageForest);\n\t\t\tloadTextureImage(imageTundra, \"tundra.bmp\", &G_TexImageTundra);\n\t\t\t \n\t\t\tglGenBuffers(1, &G_arrayBuffer);\n\t\t\tglBindBuffer(GL_ARRAY_BUFFER, G_arrayBuffer); \n\t\t\tglBufferData(GL_ARRAY_BUFFER, sizeof(G_data), G_data, GL_STATIC_DRAW);\n\t\t\tglBindBuffer(GL_ARRAY_BUFFER, 0);\n\n\t\t\tglGenBuffers (1, &G_cubeBuffer);\n\t\t\tglBindBuffer (GL_ARRAY_BUFFER, G_cubeBuffer);\n\t\t\tglBufferData (GL_ARRAY_BUFFER, sizeof(G_points), &G_points, GL_STATIC_DRAW);\n\t\t\tglBindBuffer (GL_ARRAY_BUFFER, 0);\n\t\t\t\n\t\t\tglGenBuffers (1, &G_SurfaceBuffer);\n\t\t\tglBindBuffer (GL_ARRAY_BUFFER, G_SurfaceBuffer);\n\t\t\tglBufferData (GL_ARRAY_BUFFER, sizeof(G_Surface), &G_Surface, GL_STATIC_DRAW);\n\t\t\tglBindBuffer (GL_ARRAY_BUFFER, 0);\n\t\t\t\n\t\t\t/* Wasser */\n\t\t\tglGenBuffers (1, &G_WaterBuffer);\n\t\t\tglBindBuffer (GL_ARRAY_BUFFER, G_WaterBuffer);\n\t\t\tglBufferData (GL_ARRAY_BUFFER, sizeof(*getWaterList())*WORLD_SIZE*WORLD_SIZE, getWaterList(), GL_STREAM_DRAW);\n\t\t\tglBindBuffer (GL_ARRAY_BUFFER, 0);\n\t\t\t\n\t\t\tglGenBuffers (1, &G_WaterBufferIndex);\n\t\t\tglBindBuffer (GL_ELEMENT_ARRAY_BUFFER, G_WaterBufferIndex);\n\t\t\tglBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(*getWaterIndices())*WORLD_SIZE*WORLD_SIZE*3*2, getWaterIndices(), GL_STREAM_DRAW);\n\t\t\tglBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);\n\t\t\t\n\t\t\t/* Terrain */\n\t\t\tglGenBuffers (1, &G_TerrainBuffer);\n\t\t\tglBindBuffer (GL_ARRAY_BUFFER, G_TerrainBuffer);\n\t\t\tglBufferData (GL_ARRAY_BUFFER, sizeof(*getTerrainList())*TERRAIN_SIZE*TERRAIN_SIZE, getTerrainList(), GL_STATIC_DRAW);\n\t\t\tglBindBuffer (GL_ARRAY_BUFFER, 0);\n\t\t\t\n\t\t\tglGenBuffers (1, &G_TerrainBufferIndex);\n\t\t\tglBindBuffer (GL_ELEMENT_ARRAY_BUFFER, G_TerrainBufferIndex);\n\t\t\tglBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(*getTerrainIndices())*TERRAIN_SIZE*TERRAIN_SIZE*3*2, getTerrainIndices(), GL_STATIC_DRAW);\n\t\t\tglBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);\n\t\t\t\n\t\t\t/* Caustics --> Indices des Terrains nutzen! */\n\t\t\tglGenBuffers (1, &G_CausticsBuffer);\n\t\t\tglBindBuffer (GL_ARRAY_BUFFER, G_CausticsBuffer);\n\t\t\tglBufferData (GL_ARRAY_BUFFER, sizeof(*getTerrainCaustics())*TERRAIN_SIZE*TERRAIN_SIZE, getTerrainCaustics(), GL_STREAM_DRAW);\n\t\t\tglBindBuffer (GL_ARRAY_BUFFER, 0);\n\t\t\t\n\t\t\tglGenBuffers(1, &G_ObjectsBuffer);\n\t\t\tglBindBuffer(GL_ARRAY_BUFFER, G_ObjectsBuffer); \n\t\t\tglBufferData(GL_ARRAY_BUFFER, sizeof(G_Objects), G_Objects, GL_STATIC_DRAW);\n\t\t\tglBindBuffer(GL_ARRAY_BUFFER, 0);\n\t\t\t\n\t\t\tglBindFramebuffer(GL_FRAMEBUFFER, 0);\n\t\t\tglClearColor(0.0, 1.0, 1.0, 0.0);\n\t\t\tglClearDepth(1.0f);\n\t\t\tglClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);\n\t\t\trenderFBToCubeTexture(&G_TexCubeFront, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0,  0,    -1);\n\t\t\trenderFBToCubeTexture(&G_TexCubeBack,  GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0,  0,    1);\n\t\t\trenderFBToCubeTexture(&G_TexCubeBottom,GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0,  -1,   0);\n\t\t\trenderFBToCubeTexture(&G_TexCubeTop,   GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0,  1,    0);\n\t\t\trenderFBToCubeTexture(&G_TexCubeLeft,  GL_TEXTURE_CUBE_MAP_NEGATIVE_X, -1, 0,    0);\n\t\t\trenderFBToCubeTexture(&G_TexCubeRight, GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1,  0,    0);\n\t\t\t\n\t\t\t/* Die Endlosschleife wird angestoßen */\n\t\t\tglutMainLoop ();  \n\t\t\twindowID = 0;\n\t\t\t\n\t\t\tglDeleteFramebuffers(1, &G_fboCam);\n\t\t\tglDeleteTextures(1, &G_TexCamera);\n            \n\t\t} \n\t\telse\n\t\t{\n\t\t\tglutDestroyWindow (windowID);\n\t\t\twindowID = 0;\n\t\t}\n\t}\n\treturn windowID;\n}\n"
  },
  {
    "path": "src/io.h",
    "content": "#ifndef __IO_H__\n#define __IO_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * CallBack-Funktionsköpfe\n *\n * @author Maurice Tollmien\n */\n\n/* ---- System Header einbinden ---- */\n#ifdef WIN32\n#include <windows.h>\n#endif\n\n#ifdef MACOSX\n#include <GLUT/glut.h>\n#else\n#include <GL/glut.h>\n#endif\n\n#ifdef MACOSX\n#include <OpenGL/glu.h>\n#else\n#include <GL/glu.h>\n#endif\n\n#include <stdio.h>\n#include <stdarg.h>\n\nint initAndStartIO (char *title, int width, int height);\n\n#endif\n"
  },
  {
    "path": "src/logic.c",
    "content": "\n/**\n * @file\n * Hier ist die Datenhaltung und Programmlogik\n *\n * @author Tilman Nedele, Maurice Tollmien\n */\n\n/* ---- System Header einbinden ---- */\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <math.h>\n#include <stringOutput.h>\n#include <assert.h>\n\n#ifdef MACOSX\n#include <GLUT/glut.h>\n#else\n#include <GL/glut.h>\n#endif\n\n/* ---- Eigene Header einbinden ---- */\n#include \"logic.h\"\n#include \"vector.h\"\n#include \"scene.h\"\n#include \"types.h\"\n#include \"water.h\"\n#include \"terrain.h\"\n\n/* Globale Variablen */\n/** Licht an/aus */\nInitType G_Light = ON;\n/** Hilfe an/aus */\nInitType G_Help  = OFF;\n/** Textur an/aus */\nInitType G_Texture = ON;\n/** Mausbewegung zoom/move/none */\nMouseInterpretType G_Mouse;\n/** Kameraposition */\nCGVector3D G_CameraPosition = {CAMERA_X,CAMERA_Y,CAMERA_Z};\n/** Position der Maus */\nMovement G_MouseMove = {0.0,0.0,0.0};\n/** Startpunkt der Mausbewegung */\nCGVector3D G_LastMouseCenter = {0.0,0.0,0.0};\n/** Anzahl der Quadrate für den Boden */\nint G_QuadCount = 0;\n/** Welche Textur soll angezeigt werden */\nint G_TextureCount = 5;\n/** Liste aller Kugeln */\nSpheres * G_Spheres;\n\nint G_BallMoving = 0;\n\nQuads * G_Quads;\n/** Sollen sich die Kugeln bewegen? */\nint G_SpheresMoving = 0;\n/** Ob die Partikel neu berechnet werden */\nint G_ParticleFreeze = 0;\n/** Wie sollen die Partikel gezeichnet werden? */\nParticleType G_ParticleType = line;\n/** Schatten zeichnen? */\nint G_DrawShadows = 0;\n/** Partikel hinzufügen? */\nint G_UpDownKeys[2] = {0,0};\n/** Kamer auf einem Partikel? */\nint G_ParticleCamera = 0;\n/** Position des Partikel in der Liste mit der Kamera */\nint G_CameraParticlePos = 0;\n/** Verfolgermodus? */\nint G_PersecutorParticle = 0;\n/** UP-Vektor anzeigen? */\nint G_ShowUpVector = 0;\n/** FPS */\nint G_FPS = 0;\n/** FPS counter */\ndouble G_Counter = 0.0-EPS;\n\n/* ------- GETTER / SETTER ------- */\n\nint getFPS(void)\n{\n\treturn G_FPS;\n}\n\n/**\n * Setzt die Ansicht des Up-Vektors\n */\nvoid toggleShowUpVector (void)\n{\n\tG_ShowUpVector = !G_ShowUpVector;\n}\n\n/**\n * Getter für Ansicht des Up-Vektors\n * @return 0 / 1\n */\nint getShowUpVector (void)\n{\n\treturn G_ShowUpVector;\n}\n\n/**\n * Getter für die Position des Partikel mit der Kamera\n */\nint getCameraParticlePos() {\n    return G_CameraParticlePos;\n}\n\n/**\n * Ändert den Verfolger-Modus\n */\nvoid togglePersecutorParticle (void)\n{\n    G_PersecutorParticle = !G_PersecutorParticle;\n}\n\n/**\n * Ändert den Kameramodus.\n */\nvoid toggleParticleCamera (void)\n{\n    G_ParticleCamera = !G_ParticleCamera;\n}\n\n/**\n * Ob der Verfolgermodus gesetzt ist\n */\nint getParticleCamera (void)\n{\n    return G_ParticleCamera;\n}\n\nvoid startMovingBall(void)\n{\n\tG_BallMoving = G_BallMoving == 0 ? 1 : 0;\n}\n\n/**\n * Setzt, ob ein Up/Down-Key gedrückt ist.\n * key == 0 = down\n * key == 1 = up\n * value = gesetzt/nicht gesetzt.\n */\nvoid setKey (int key, int value)\n{\n    if (key < 2)\n        G_UpDownKeys[key] = value;\n}\n\n/**\n * Ob Schatten gezeichnet werden sollen, oder nicht.\n */\nvoid toggleShadows(void)\n{\n\tG_DrawShadows = !G_DrawShadows;\n}\n\n/**\n * Ob Schatten gezeichnet werden sollen, oder nicht.\n */\nint getDrawShadows(void)\n{\n\treturn G_DrawShadows;\n}\n\n/**\n * Ändert den Typ der Partikel\n */\nvoid toggleParticleType (void)\n{\n\tif (G_ParticleType + 1 > sphere)\n\t\tG_ParticleType = 0;\n\telse \n\t\tG_ParticleType++;\n}\n\n/**\n * Welcher Typ die Partikel sind\n */\nParticleType getParticleType (void)\n{\n\treturn G_ParticleType;\n}\n\n/**\n * Ob die Partikel sich bewegen oder nicht.\n */\nvoid toggleParticleFreeze (void)\n{\n\tG_ParticleFreeze = !G_ParticleFreeze;\n\tif (G_SpheresMoving)\n\t\tG_SpheresMoving = 0;\n}\n\n/**\n * Gibt eine Sphere zurück.\n */\nSpheres * getSphereList (void) \n{\n\treturn G_Spheres;\n}\n\n/**\n * Gibt eine Sphere zurück.\n */\nQuads * getQuadList (void) \n{\n\treturn G_Quads;\n}\n\n/**\n * Ändert den Wert des Boolean, ob sich die Kugeln bewegen dürfen.\n */\nvoid toggleSpheresMoving (void)\n{\n\tG_SpheresMoving = !G_SpheresMoving;\n}\n\n/**\n * Get-Function für den Status des Lichts\n * @return Status des Lichts\n */\nInitType getLightStatus() {\n    return G_Light;\n}\n\n/**\n * Set-Function für den Status des Lichts\n * @param Status des Lichts\n */\nvoid setLightStatus(InitType state) {\n    G_Light = state;\n}\n\nvoid toggleLight (void)\n{\n\tG_Light = !G_Light;\n}\n\n/**\n * Get-Function für den Status der Hilfe\n * @return Status der Hilfe\n */\nInitType getHelpStatus() {\n    return G_Help;\n}\n\n/**\n * Set-Function für den Status der Hilfe\n * @param Status der Hilfe\n */\nvoid setHelpStatus(InitType state) {\n    G_Help = state;\n}\n\n/**\n * Get-Function für den Status der Texturen\n * @return Status der Texturen\n */\nInitType getTextureStatus() {\n    return G_Texture;\n}\n\n/**\n * Set-Function für den Status der Textur\n * @param Status der Textur\n */\nvoid setTextureStatus(InitType state) {\n    G_Texture = state;\n}\n\n/**\n * Set-Function für den Status der Maus\n * @param Status der Maus\n */\nvoid setMouseEvent(MouseInterpretType state,int x, int y) {\n    G_MouseMove[0] = 0.0;\n    G_MouseMove[2] = 0.0;\n    G_LastMouseCenter[0] = x;\n    G_LastMouseCenter[2] = y;\n    \n    \n    G_Mouse = state;\n}\n\n/**\n * Get-Function für den Status der Maus\n * @return Status der Maus\n */\nMouseInterpretType getMouseEvent() {\n    return G_Mouse;\n}\n\n/**\n * Gibt die Kamerakoordinate zurück.\n */\ndouble getCameraPosition (int axis)\n{\n    if (axis >= 0 && axis < 3)\n        return G_CameraPosition[axis];\n        \n    return 0.0;\n}\n\n\n\n/**\n * Erhöht die Größe der Unterteilungen um den Faktor 2\n */\nvoid incQuadCount() {\n    if (G_QuadCount < 9)\n        ++G_QuadCount;\n}\n\n/**\n * Verkleinert die Größe der Unterteilungen um den Divisor 2\n */\nvoid decQuadCount() {\n    if (G_QuadCount > 0)\n        --G_QuadCount;\n}\n\n/**\n * Rekursionstiefe für die Bodenfläche\n */\nint getQuadCount() {\n    return G_QuadCount;\n}\n\n/**\n * Bewegt die Kamera auf einem Kugelradius um den Szenenmittelpunkt.\n */\nvoid setCameraMovement(int x,int y)\n{\n\tCGVector3D tmp;\n\tdouble factor, radius = vectorLength3D(G_CameraPosition);\n\t\n\ttmp[0] = G_CameraPosition[0];\n\ttmp[1] = G_CameraPosition[1];\n\ttmp[2] = G_CameraPosition[2];\n\t\n\tG_MouseMove[0] = x-G_LastMouseCenter[0];\n\tG_MouseMove[2] = y-G_LastMouseCenter[2];\n\t\n\tG_LastMouseCenter[0] = x;\n\tG_LastMouseCenter[2] = y;\n\t\n\t/* Bewegung um Y-Achse: */\n\tG_CameraPosition[0] = cos(-G_MouseMove[0]*PI/180.0/CAMERA_MOVEMENT_SPEED)*tmp[0] + sin(-G_MouseMove[0]*PI/180.0/CAMERA_MOVEMENT_SPEED)*tmp[2];\n\tG_CameraPosition[2] = -sin(-G_MouseMove[0]*PI/180.0/CAMERA_MOVEMENT_SPEED)*tmp[0] + cos(-G_MouseMove[0]*PI/180.0/CAMERA_MOVEMENT_SPEED)*tmp[2];\n\t\n\t/* Bewegung oben/unten */\n\tG_CameraPosition[1] += G_MouseMove[2]/(CAMERA_MOVEMENT_SPEED/2)*(vectorLength3D(G_CameraPosition)/100.0);\n\tfactor = 1.0 / (vectorLength3D(G_CameraPosition) / radius);\n\tmultiplyVectorScalar (G_CameraPosition, factor, &G_CameraPosition);\n\t\t\n}\n\n/**\n * Verlängert/verkürzt den Vektor zur Kamera.\n */\nvoid setCameraZoom(int x,int y)\n{\n\tdouble factor = 1.0 + (CAMERA_ZOOM_SPEED / 1000.0) * ((G_MouseMove[2] < 0.0) ? -1.0 : 1.0);\n\t\n\tG_MouseMove[0] = x-G_LastMouseCenter[0];\n\tG_MouseMove[2] = y-G_LastMouseCenter[2];\n\t\n\tG_LastMouseCenter[0] = x;\n\tG_LastMouseCenter[2] = y;\n\t\n\tG_CameraPosition[0] *= factor;\n\tG_CameraPosition[1] *= factor;\n\tG_CameraPosition[2] *= factor;\n}\n\n/* ------- BERECHNUNGEN ------- */\n\n/**\n * Berechnet die Bewegung der Kugeln\n * @param interval - Zeit\n */\nvoid moveSpheres (double interval)\n{\n\tint i;\n\t\n\tfor (i=0;i<SPHERE_CNT && G_BallMoving;i++)\n\t{\n\t\tSpheres s = getSphereList()[i];\n\t\n\t\ts->pos[0] += SPHERE_MOVE_SPEED*interval;\n\t\ts->pos[1] += 0.0;\n\t\ts->pos[2] += 0.0;\n\t\t\n\t}\n}\n\n/**\n * Berechnet alle Funktionen, die vom interval abhängig sind\n * @param interval - Zeit\n */\nvoid calcTimeRelatedStuff (double interval)\n{\n    moveSpheres(interval);\n\t\n\tif (!G_ParticleFreeze)\n    {\n        calcWaterAttributes(interval);\n    }\n    \n    /* Keine Partikel hinzufügen oder löschen! */\n    /*\n    if (G_UpDownKeys[0])\n    {\n\t\tfor (i=0;i<100;i++) {\n\t\t\tdeleteParticle ();\n\t\t}\n    } else if (G_UpDownKeys[1]) {\n\t\tfor (i=0;i<100;i++) {\n\t\t\taddParticle ();\n\t\t}\n    }\n    */\n    \n    G_Counter += interval;\n    \n    if (G_Counter >= 1.0)\n\t\tG_Counter = 0.0 -EPS;\n    \n    if (G_Counter <= 0.0)\n\t\tG_FPS = (int) 1.0/interval;\n}\n\n/**\n * Berechnet anhand der Rekursionstiefe die Anzahl der Quadrate auf dem Boden\n * @param p1,p2,p3,p4 - Die Ecken des Quadrats\n * @param rek - Rekursionstiefe\n * @param color - die Farbe der Quadrate\n * \n */\nvoid drawRecursiveQuad(CGPoint3f p1, CGPoint3f p2, CGPoint3f p3, CGPoint3f p4, int rek, int color)\n{\n    CGPoint3f middle0 = {0.0,0.0,0.0},\n              middle1 = {0.0,0.0,0.0},\n              middle2 = {0.0,0.0,0.0},\n              middle3 = {0.0,0.0,0.0},\n              center = {0.0,0.0,0.0};\n\n    center[0] = (p1[0] + p3[0]) / 2;\n    center[2] = (p1[2] + p3[2]) / 2;\n\n    middle0[0] = (p1[0] + p2[0]) / 2;\n    middle0[2] = (p1[2] + p2[2]) / 2;\n\n    middle1[0] = (p2[0] + p3[0]) / 2;\n    middle1[2] = (p2[2] + p3[2]) / 2;\n\n    middle2[0] = (p3[0] + p4[0]) / 2;\n    middle2[2] = (p3[2] + p4[2]) / 2;\n\n\n    middle3[0] = (p4[0] + p1[0]) / 2;\n    middle3[2] = (p4[2] + p1[2]) / 2;\n\n    if (rek > 0)\n    {\n      drawRecursiveQuad(center,middle0,p2,middle1, rek-1, color);\n      drawRecursiveQuad(center,middle1,p3,middle2, rek-1, !color);\n      drawRecursiveQuad(center,middle2,p4,middle3, rek-1, color);\n      drawRecursiveQuad(center,middle3,p1,middle0, rek-1, !color);\n\n\n    } else {\n        drawVertex(p4,p3,p2,p1, color);\n    }\n}\n\n/* ------- INIT ------- */\n\n/**\n * Initialisiert die Kamera.\n */\nvoid initCameraPosition ()\n{\n    G_CameraPosition[0] = CAMERA_X;\n    G_CameraPosition[1] = CAMERA_Y;\n    G_CameraPosition[2] = CAMERA_Z;\n}\n\n/**\n * Initialisiert die Kugeln.\n */\nvoid initSpheres(void)\n{\n\tint i;\n\tG_Spheres = malloc (sizeof(*G_Spheres) * SPHERE_CNT);\n\t\n\tfor (i=0;i<SPHERE_CNT;i++) \n\t{\n\t\t\n\t\tSpheres sphere = malloc (sizeof(**G_Spheres));\n\t\t\n        sphere->interpolatedPoints = NULL;\n        sphere->interpolatedPointsAll = NULL;\n        sphere->controlPoints = NULL;\n        sphere->t = 0.0;\n        \n\t\tsphere->pos[0] = rand() % (int)WORLD_SIZE/2 - rand() % (int)WORLD_SIZE/2+150;\n\t\tsphere->pos[1] = GROUND_HEIGHT-WORLD_SIZE/2.0+0.1 + SPHERE_R + 10;\n\t\tsphere->pos[2] = rand() % (int)WORLD_SIZE/2 - rand() % (int)WORLD_SIZE/2;\n\t\t\n\t\tsphere->newPos[0] = 0.0;\n\t\tsphere->newPos[1] = 0.0;\n\t\tsphere->newPos[2] = 0.0;\n\t\t\n\t\tsphere->color[0] = rand()%255;\n\t\tsphere->color[1] = rand()%255;\n\t\tsphere->color[2] = rand()%255;\n\t\t\n\t\tG_Spheres[i] = sphere;\n\t}\n}\n\n/**\n * Initialisiert die Quads.\n */\nvoid initQuads(void)\n{\n\tint i;\n\tG_Quads = malloc (sizeof(*G_Quads) * QUAD_CNT);\n\t\n\tfor (i=0;i<QUAD_CNT;i++) \n\t{\n\t\t\n\t\tQuads quads = malloc (sizeof(**G_Quads));\n\t\t\n\t\tquads->pos[0] = -40;\n\t\tquads->pos[1] = GROUND_HEIGHT-WORLD_SIZE/2.0+0.1+QUAD_SIDE/2 ;\n\t\tquads->pos[2] = -40;\n\t\t\n\t\tG_Quads[i] = quads;\n\t}\n}\n\n/**\n * Hier findet die komplette Initialisierung des kompletten SPIEeles statt.\n * Inklusive der Datenhaltung und des SPIEelfeldes.\n */\nvoid initGame ()\n{   \n    initCameraPosition();\n    initTerrain();\n    initWater();\n    calcFixWaterPoints(getTerrainList());\n    /*setRandomize();*/\n}\n\n"
  },
  {
    "path": "src/logic.h",
    "content": "#ifndef __LOGIC_H__\n#define __LOGIC_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * Programmlogik und Datenhaltung\n *\n * @author Maurice Tollmien\n */\n\n/* ---- System Header einbinden ---- */\n#ifdef WIN32\n#include <windows.h>\n#endif\n\n#ifdef MACOSX\n#include <OpenGL/glu.h>\n#else\n#include <GL/glu.h>\n#endif\n\n#include <stdio.h>\n#include <stdarg.h>\n#include \"types.h\"\n\n/* eig. Funktionen */\n\n/* ------- GETTER / SETTER ------- */\nInitType getLightStatus(void);\nvoid setLightStatus(InitType state);\nInitType getHelpStatus(void);\nvoid setHelpStatus(InitType state);\nInitType getTextureStatus(void);\nvoid setTextureStatus(InitType state);\nvoid setMouseEvent(MouseInterpretType state,int x, int y);\nMouseInterpretType getMouseEvent(void);\ndouble getCameraPosition (int axis);\nint getTextureSize(void);\nvoid setCameraMovement(int x,int y);\nvoid setCameraZoom(int x,int y);\nvoid toggleLight (void);\nSpheres * getSphereList (void);\nvoid incQuadCount();\nvoid decQuadCount();\nint getQuadCount();\nvoid toggleSpheresMoving (void);\nint getTextureCount();\nvoid nextTexture();\nParticle * getParticleList (void);\nint getParticleCnt (void);\nvoid toggleParticleFreeze (void);\nvoid toggleParticleType (void);\nParticleType getParticleType (void);\nvoid toggleShadows(void);\nint getDrawShadows(void);\nvoid setKey (int key, int value);\nvoid toggleParticleCamera (void);\nvoid togglePersecutorParticle (void);\nint getParticleCamera (void);\nvoid nextCameraParticle();\nint getCameraParticlePos();\nParticle getCameraParticle (void);\nint getShowUpVector (void);\nvoid toggleShowUpVector (void);\nint getFPS(void);\nvoid startMovingBall(void);\n\nQuads * getQuadList (void);\n\n/* ------- BERECHNUNGEN ------- */\nvoid moveCamera(int x, int y);\nvoid zoomCamera(int x, int y);\nvoid calcTimeRelatedStuff (double interval);\nvoid drawRecursiveQuad(CGPoint3f p1, CGPoint3f p2, CGPoint3f p3, CGPoint3f p4, int rek, int color);\n/* ------- INIT ------- */\n\nvoid initGame ();\n\n\n\n#endif\n"
  },
  {
    "path": "src/main.c",
    "content": "/**\n * @file\n * ein erster Versuch, eine eigene Datei zu erstellen...\n * @author Maurice Tollmien.\n */\n\n/* ---- System Header einbinden ---- */\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <stdarg.h>\n#include <time.h>\n\n#ifdef MACOSX\n#include <GLUT/glut.h>\n#else\n#include <GL/glut.h>\n#endif\n\n#ifdef WIN32\n#include <windows.h>\n#endif\n\n/* ---- Eigene Header einbinden ---- */\n#include \"io.h\"\n#include \"scene.h\" \n#include \"types.h\"\n\n\n\n/**\n * Hauptprogramm.\n * Initialisiert Fenster, Anwendung und Callbacks, startet glutMainLoop.\n * @param argc Anzahl der Kommandozeilenparameter (In).\n * @param argv Kommandozeilenparameter (In).\n * @return Rueckgabewert im Fehlerfall ungleich Null.\n */\nint\nmain (int argc, char **argv)\n{\n\tsrand (time (0));\n\tif (!initAndStartIO (\"nen Programm\", 1080, 1080))\n\t{\n\t\tfprintf (stderr, \"Initialisierung fehlgeschlagen!\\n\");\n\t\treturn 1;\n\t} \n\treturn 0;\n}\n"
  },
  {
    "path": "src/particle.c",
    "content": "\n\n/**\n * @file\n * Hier ist die Datenhaltung und Programmlogik\n *\n * @author Tilman Nedele, Maurice Tollmien\n */\n\n/* ---- System Header einbinden ---- */\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <math.h>\n#include <assert.h>\n\n#ifdef MACOSX\n#include <GLUT/glut.h>\n#else\n#include <GL/glut.h>\n#endif\n\n/* ---- Eigene Header einbinden ---- */\n#include \"particle.h\"\n#include \"logic.h\"\n#include \"vector.h\"\n#include \"types.h\"\n\n/** Globale Variablen */\n\n/** Liste mit Partikeln */\nParticle * G_Particles;\n/** Anzahl der Partikel */\nint G_ParticleCnt = PARTICLE_CNT;\n\n/** Init-Wert der Länge der Feder ohne Dehnung */\ndouble G_StructureSpringLengthInit;\ndouble G_SheerSpringLengthInit;\ndouble G_BendingSpringLengthInit;\n\n\n/**\n * Gibt die Liste mit Partikeln zurück\n */\nParticle * getParticleList (void)\n{\n\treturn G_Particles;\n}\n\n/**\n * Getter für ein Partikel an der Position i\n * @return das Partikel\n */\nParticle getParticleAt(int i)\n{\n\treturn G_Particles[i];\n}\n\n/**\n * Gibt die Anzahl der Partikel zurück.\n */\nint getParticleCnt (void)\n{\n\treturn G_ParticleCnt;\n}\n\n/**\n * Setzt die Partikelanzahl\n */\nvoid setParticleCnt (int i)\n{\n    G_ParticleCnt = i;\n}\n\nvoid calcSpringForce (Particle p1, Particle p2, double initLength, double k, CGVector3D * res)\n{\n\tCGVector3D tmp = {0.0,0.0,0.0};\n\tdouble len = 0.0;\n\t\n\t/* Tatsächlicher Abstand beider Punkte */\n\tsubtractVectorVector (p1->s, p2->s, &tmp);\n\t/* Länge des Abstandes */\n\tlen  = vectorLength3D (tmp);\n\t/* Bildung des Einheitsvektors in die Richtung der Kraft */\n\tdivideVectorScalar (tmp, len, &tmp);\n\t/* Abweichung der Initialen Länge berechnen */\n\tlen  = len - initLength;\n\t\n\tif (abs(len) < EPS_LEN) \n\t\tlen = 0.0;\n\t\n\t/* Abweichung mit Federkonstante multiplizieren */\n\tmultiplyVectorScalar (tmp, len * -k, &tmp);\n\t\n\tif (vectorLength3D(tmp) <= EPS_F) \n\t\tmultiplyVectorScalar (tmp, 0, &tmp);\n\t\t\n\t/* NEU! */\n\tif (vectorLength3D(tmp) > MAX_F) {\n\t\tmultiplyVectorScalar (tmp, 0.0001, &tmp);\n\t}\n\t\n\t\t\n\tmultiplyVectorScalar (tmp, -1, &tmp);\n\t\t\n\t(*res)[0] = tmp[0];\n\t(*res)[1] = tmp[1];\n\t(*res)[2] = tmp[2];\n\t\n}\n\nvoid correctConcreteParticleSymmetric (Particle p, Particle p2, double initValue)\n{\n\tCGVector3D tmp = {0.0,0.0,0.0};\n\tdouble len, tooMuch;\n\tdouble moveLen;\n\t\n\tsubtractVectorVector (p->s, p2->s, &tmp);\t\n\tlen = vectorLength3D (tmp);\n\t\n\ttooMuch = 1.0 - (len / initValue);\n\n\t/* Grenze überschritten! Feder zu lang oder kurz! */\n\tif ((double)(abs(tooMuch * 1000.0)/1000.0) > SPRING_EXPANSION_MAX) {\n\t\tif (len > initValue) {\n\t\t\tmoveLen = initValue * SPRING_EXPANSION_MAX + initValue;\n\t\t} else {\n\t\t\tmoveLen = -initValue * SPRING_EXPANSION_MAX + initValue;\n\t\t}\n\n\t\t/* Wenn der Vektor verkürzt werden soll, ist das Ergebnis positiv! */\n\t\tmoveLen = (len - moveLen) / 2.0;\n\t\t\t\n\t\t/* normierter Richtungsvektor in Richtung des Partikels p */\n\t\tdivideVectorScalar (tmp, len, &tmp);\n\t\t\n\t\t/* Vektor zeigt Richtung Partikel p, wenn er verkürzt werden soll! */\n\t\tmultiplyVectorScalar (tmp, moveLen, &tmp);\n\t\t\n\t\taddVectorVector (p2->s, tmp, &(p2->s));\n\t\tmultiplyVectorScalar (tmp, -1, &tmp);\n\t\taddVectorVector (p->s, tmp, &p->s);\t\t\n\t}\n\t\n}\n \nvoid correctConcreteParticleP2 (Particle p, Particle p2, double initValue)\n{\n\tCGVector3D tmp = {0.0,0.0,0.0};\n\tdouble len, tooMuch;\n\tdouble moveLen;\n\t\n\tsubtractVectorVector (p->s, p2->s, &tmp);\t\n\tlen = vectorLength3D (tmp);\n\t\n\ttooMuch = 1.0 - (len / initValue);\n\t/* Grenze überschritten! Feder zu lang oder kurz! */\n\tif ((double)(abs(tooMuch * 1000.0)/1000.0) > SPRING_EXPANSION_MAX) {\n\t\tif (len > initValue) {\n\t\t\tmoveLen = initValue * SPRING_EXPANSION_MAX + initValue;\n\t\t} else {\n\t\t\tmoveLen = -initValue * SPRING_EXPANSION_MAX + initValue;\n\t\t}\n\t\t\n\t\t/* Wenn der Vektor verkürzt werden soll, ist das Ergebnis positiv! */\n\t\tmoveLen = len - moveLen;\n\t\t\t\n\t\t/* normierter Richtungsvektor in Richtung des Partikels p */\n\t\tdivideVectorScalar (tmp, len, &tmp);\n\t\t\n\t\t/* Vektor zeigt Richtung Partikel p, wenn er verkürzt werden soll! */\n\t\tmultiplyVectorScalar (tmp, moveLen, &tmp);\n\t\t\n\t\taddVectorVector (p2->s, tmp, &(p2->s));\n\t}\n\t\n}\n \nvoid correctSpringLengthPosition(Particle p, int i, int j)\n{\n\tint sqrtLen = (int)(sqrt(G_ParticleCnt)+0.5);\n\t\n\t/** ================== STRUKTURFEDERN ===================== */\n\tif (1) {\n\t\t/* Untere Feder */\n\t\tif (i > 0) {\t\t\t\t\n\t\t\t/*Particle p2 = G_Particles[(i-1)*sqrtLen+j];\n\t\t\tcorrectConcreteParticleSymmetric (p, p2, G_StructureSpringLengthInit);*/\n\t\t}\n\t\t\n\t\t/* Obere Feder */\n\t\tif (i < sqrtLen-1) {\t\t\n\t\t\tParticle p2 = G_Particles[(i+1)*sqrtLen+j];\t\t\n\t\t\t\n\t\t\tif ((i == sqrtLen-2 && j == sqrtLen-1) || (i == sqrtLen-2 && j == 0)) {\n\t\t\t\tcorrectConcreteParticleP2(p2, p, G_StructureSpringLengthInit);\n\t\t\t} else {\n\t\t\t\tcorrectConcreteParticleSymmetric (p, p2, G_StructureSpringLengthInit);\n\t\t\t}\n\t\t}\n\t\t\n\t\t/* Rechte Feder */\n\t\tif (j < sqrtLen-1) {\n\t\t\tParticle p2 = G_Particles[i*sqrtLen+(j+1)];\t\t\n\t\t\tcorrectConcreteParticleSymmetric (p, p2, G_StructureSpringLengthInit);\n\t\t\t/*if (i == sqrtLen-1 && j == sqrtLen-2) {\n\t\t\t\tcorrectConcreteParticleP2(p2, p, G_StructureSpringLengthInit);\n\t\t\t} else {\n\t\t\t\tcorrectConcreteParticleSymmetric (p, p2, G_StructureSpringLengthInit);\n\t\t\t}*/\n\t\t}\n\t\t\n\t\t/* Linke Feder */\n\t\tif (j > 0) {\n\t\t\tParticle p2 = G_Particles[i*sqrtLen+(j-1)];\t\t\n\t\t\tcorrectConcreteParticleSymmetric (p, p2, G_StructureSpringLengthInit);\n\t\t\t/*if (i == sqrtLen-1 && j == 1) {\n\t\t\t\tcorrectConcreteParticleP2(p2, p, G_StructureSpringLengthInit);\n\t\t\t} else {\n\t\t\t\tcorrectConcreteParticleSymmetric (p, p2, G_StructureSpringLengthInit);\n\t\t\t}*/\n\t\t}\n\t}\n\t\n\t/** ==================== SCHERFEDERN ====================== */\t\n\t\n\tif (1) {\n\t\t\n\t\t/* Links oben */\n\t\tif (i < sqrtLen-1 && j > 0) {\t\t\t\t\t\n\t\t\tParticle p2 = G_Particles[(i+1)*sqrtLen+(j-1)];\n\t\t\t\n\t\t\tif (i == sqrtLen-2 && j == 1) {\n\t\t\t\tcorrectConcreteParticleP2(p2, p, G_SheerSpringLengthInit);\t\n\t\t\t} else {\n\t\t\t\tcorrectConcreteParticleSymmetric (p, p2, G_SheerSpringLengthInit);\n\t\t\t}\n\t\t}\n\t\t\n\t\t/* Rechts oben */\n\t\tif (i < sqrtLen-1 && j < sqrtLen-1) {\t\t\t\t\t\n\t\t\tParticle p2 = G_Particles[(i+1)*sqrtLen+(j+1)];\n\t\t\t\n\t\t\tif (i == sqrtLen-2 && j == sqrtLen-2) {\n\t\t\t\tcorrectConcreteParticleP2(p2, p, G_SheerSpringLengthInit);\n\t\t\t} else {\n\t\t\t\tcorrectConcreteParticleSymmetric (p, p2, G_SheerSpringLengthInit);\n\t\t\t}\n\t\t}\n\t\t\n\t\tif (i > 0 && j > 0) {\t\t\t\t\t\n\t\t\tParticle p2 = G_Particles[(i-1)*sqrtLen+(j-1)];\n\t\t\tcorrectConcreteParticleSymmetric (p, p2, G_SheerSpringLengthInit);\n\t\t}\n\t\t\n\t\tif (i > 0 && j < sqrtLen-1) {\t\t\t\t\t\n\t\t\tParticle p2 = G_Particles[(i-1)*sqrtLen+(j+1)];\n\t\t\tcorrectConcreteParticleSymmetric (p, p2, G_SheerSpringLengthInit);\n\t\t}\n\t\t\n\t\t\n\t}\n\n}\n\ndouble calcWindForce (CGVector3D va, CGVector3D vb, CGVector3D vc, CGVector3D wind) {\n\tCGVector3D a = {0.0,0.0,0.0};\n\tCGVector3D b = {0.0,0.0,0.0};\n\tCGVector3D c = {0.0,0.0,0.0};\n\tCGVector3D norm = {0.0,0.0,0.0};\n\tdouble la, lb, lc, s, f;\n\t\n\tsubtractVectorVector (vb, va, &a);\n\tsubtractVectorVector (vc, vb, &b);\n\tsubtractVectorVector (va, vc, &c);\n\t\n\tla = vectorLength3D (a);\n\tlb = vectorLength3D (b);\n\tlc = vectorLength3D (c);\n\t\n\ts = (la + lb + lc ) / 2.0;\n\t\n\tf = sqrt (s * (s-la) * (s-lb) * (s-lc));\n\t\n\tcrossProduct3D (norm, a, b);\n\t\n\treturn scalarProduct (norm, wind) * f * WIND_FORCE;\n\t\n}\n\n/**\n * Berechnet mitHilfe von Euler die neuen Attribute der Partikel\n * \n * @param spheres - Liste aller Kugeln\n * @param sphereCnt - Anzahl aller Kugeln\n * @param interval - Zeit\n * @param persecutorParticleMode - Verfolgermodus\n */\nvoid calcParticleAttributesEuler (Spheres * spheres, int sphereCnt, double interval,int persecutorParticleMode, int cameraParticlePos)\n{\n\tint i,j,k;\n\tint sqrtLen = (int)(sqrt(G_ParticleCnt)+0.5);\n\t\t\n\tfor (i=0;i<sqrtLen;i++) {\n\t\t\n\t\tfor (j=0;j<sqrtLen;j++) {\n\t\t\n\t\t\tParticle p = G_Particles[i*sqrtLen +j];\n\t\t\tCGVector3D tmp = {0.0,0.0,0.0};\n\t\t\tCGVector3D fComplete = {0.0,0.0,0.0};\n\t\t\tCGVector3D fInt = {0.0,0.0,0.0};\n\t\t\tCGVector3D fIntNeighbours = {0.0,0.0,0.0};\n\t\t\tCGVector3D fWindForce = {0.0,0.0,0.0};\n\t\t\tCGVector3D fExt = {0.0,G,0.0};\n\t\t\tdouble factor = 1.0;\n\t\t\tCGVector3D wind = WIND_DIR;\n\t\t\tCGVector3D tmp2 = {0.0,0.0,0.0};\n\t\t\n\t\t\n\t\t\t/* Tuch an zwei Ecken aufhängen. */\n\t\t\tif (!(i >= sqrtLen-2 /*   || (i == sqrtLen-1 && j == sqrtLen-1) || (i == sqrtLen-1 && j == 0)  */  )) {\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\t\t\t\t/** ================== STRUKTURFEDERN ===================== */\n\t\t\t\t\n\t\t\t\t/* Linke Feder */\n\t\t\t\tif (i > 0) {\t\t\t\t\t\n\t\t\t\t\tcalcSpringForce (G_Particles[(i-1)*sqrtLen+j], p, G_StructureSpringLengthInit, K_STRUCTURE, &tmp);\t\n\t\t\t\t\taddVectorVector (fInt, tmp, &fInt);\n\t\t\t\t\t\n\t\t\t\t\tdivideVectorScalar (G_Particles[(i-1)*sqrtLen+j]->f, 5, &tmp);\n\t\t\t\t\taddVectorVector (fIntNeighbours, tmp, &fIntNeighbours);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Rechte Feder */\n\t\t\t\tif (i < sqrtLen-1) {\n\t\t\t\t\tcalcSpringForce (G_Particles[(i+1)*sqrtLen+j], p, G_StructureSpringLengthInit, K_STRUCTURE, &tmp);\n\t\t\t\t\taddVectorVector (fInt, tmp, &fInt);\n\t\t\t\t\t\n\t\t\t\t\tdivideVectorScalar (G_Particles[(i+1)*sqrtLen+j]->f, 5, &tmp);\n\t\t\t\t\taddVectorVector (fIntNeighbours, tmp, &fIntNeighbours);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Untere Feder */\n\t\t\t\tif (j > 0) {\n\t\t\t\t\tcalcSpringForce (G_Particles[i*sqrtLen+(j-1)], p, G_StructureSpringLengthInit, K_STRUCTURE, &tmp);\n\t\t\t\t\taddVectorVector (fInt, tmp, &fInt);\n\t\t\t\t\t\n\t\t\t\t\tdivideVectorScalar (G_Particles[i*sqrtLen+(j-1)]->f, 5, &tmp);\n\t\t\t\t\taddVectorVector (fIntNeighbours, tmp, &fIntNeighbours);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Obere Feder */\n\t\t\t\tif (j < sqrtLen-1) {\n\t\t\t\t\tcalcSpringForce (G_Particles[i*sqrtLen+(j+1)], p, G_StructureSpringLengthInit, K_STRUCTURE, &tmp);\n\t\t\t\t\taddVectorVector (fInt, tmp, &fInt);\n\t\t\t\t\t\n\t\t\t\t\tdivideVectorScalar (G_Particles[i*sqrtLen+(j+1)]->f, 5, &tmp);\n\t\t\t\t\taddVectorVector (fIntNeighbours, tmp, &fIntNeighbours);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/** ==================== SCHERFEDERN ====================== */\n\t\t\t\t\n\t\t\t\t/* Links unten */\n\t\t\t\tif (i > 0 && j > 0) {\t\t\t\t\t\n\t\t\t\t\tcalcSpringForce (G_Particles[(i-1)*sqrtLen+(j-1)], p, G_SheerSpringLengthInit, K_SHEER, &tmp);\t\t\n\t\t\t\t\taddVectorVector (fInt, tmp, &fInt);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (i > 0 && j < sqrtLen-1) {\t\t\t\t\t\n\t\t\t\t\tcalcSpringForce (G_Particles[(i-1)*sqrtLen+(j+1)], p, G_SheerSpringLengthInit, K_SHEER, &tmp);\t\t\n\t\t\t\t\taddVectorVector (fInt, tmp, &fInt);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (i < sqrtLen-1 && j > 0) {\t\t\t\t\t\n\t\t\t\t\tcalcSpringForce (G_Particles[(i+1)*sqrtLen+(j-1)], p, G_SheerSpringLengthInit, K_SHEER, &tmp);\n\t\t\t\t\taddVectorVector (fInt, tmp, &fInt);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (i < sqrtLen-1 && j < sqrtLen-1) {\t\t\t\t\t\n\t\t\t\t\tcalcSpringForce (G_Particles[(i+1)*sqrtLen+(j+1)], p, G_SheerSpringLengthInit, K_SHEER, &tmp);\t\n\t\t\t\t\taddVectorVector (fInt, tmp, &fInt);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/** ================== BEUGUNGSFEDERN ===================== */\n\t\t\t\t\n\t\t\t\tif (i > 1) {\t\t\t\t\t\n\t\t\t\t\tcalcSpringForce (G_Particles[(i-2)*sqrtLen+j], p, G_BendingSpringLengthInit, K_BEND, &tmp);\t\n\t\t\t\t\taddVectorVector (fInt, tmp, &fInt);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (i < sqrtLen-2) {\n\t\t\t\t\tcalcSpringForce (G_Particles[(i+2)*sqrtLen+j], p, G_BendingSpringLengthInit, K_BEND, &tmp);\n\t\t\t\t\taddVectorVector (fInt, tmp, &fInt);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (j > 1) {\n\t\t\t\t\tcalcSpringForce (G_Particles[i*sqrtLen+(j-2)], p, G_BendingSpringLengthInit, K_BEND, &tmp);\n\t\t\t\t\taddVectorVector (fInt, tmp, &fInt);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (j < sqrtLen-2) {\n\t\t\t\t\tcalcSpringForce (G_Particles[i*sqrtLen+(j+2)], p, G_BendingSpringLengthInit, K_BEND, &tmp);\n\t\t\t\t\taddVectorVector (fInt, tmp, &fInt);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/*divideVectorScalar (fInt, 5, &fInt);\n\t\t\t\taddVectorVector (fInt, fIntNeighbours, &fInt);*/\n\t\t\t\t\n\t\t\t\tif (vectorLength3D(fInt) <= F_MIN) {\n\t\t\t\t\tmultiplyVectorScalar (fInt, 0, &fInt);\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tp->f[0] = fInt[0];\n\t\t\t\tp->f[1] = fInt[1];\n\t\t\t\tp->f[2] = fInt[2];\n\t\t\t\t\n\t\t\t\t/* Kollision mit Wind :-) */\t\t\t\t\t\t\n\t\t\t\tif (i == 0 || i == sqrtLen-1) {\n\t\t\t\t\tfactor *= WIND_EDGE_FACTOR;\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (j == 0 || j == sqrtLen-1) {\n\t\t\t\t\tfactor *= WIND_EDGE_FACTOR;\n\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\tif (i > 0) {\n\t\t\t\t\tif (j > 0) {\n\t\t\t\t\t\t/* 8 */\n\t\t\t\t\t\tmultiplyVectorScalar (wind, calcWindForce(G_Particles[(i)*sqrtLen+(j)]->s, G_Particles[(i)*sqrtLen+(j-1)]->s, G_Particles[(i-1)*sqrtLen+(j-1)]->s, wind), &tmp2);\n\t\t\t\t\t\taddVectorVector (fWindForce, tmp2, &fWindForce);\n\t\t\t\t\t\t/* 1 */\n\t\t\t\t\t\tmultiplyVectorScalar (wind, calcWindForce(G_Particles[(i)*sqrtLen+(j)]->s, G_Particles[(i-1)*sqrtLen+(j-1)]->s, G_Particles[(i-1)*sqrtLen+(j)]->s, wind), &tmp2);\n\t\t\t\t\t\taddVectorVector (fWindForce, tmp2, &fWindForce);\n\t\t\t\t\t}\n\t\t\t\t\tif (j < sqrtLen-1) {\n\t\t\t\t\t\t/* 2 */\n\t\t\t\t\t\tmultiplyVectorScalar (wind, calcWindForce(G_Particles[(i)*sqrtLen+(j)]->s, G_Particles[(i-1)*sqrtLen+(j)]->s, G_Particles[(i-1)*sqrtLen+(j+1)]->s, wind), &tmp2);\n\t\t\t\t\t\taddVectorVector (fWindForce, tmp2, &fWindForce);\n\t\t\t\t\t\t/* 3 */\n\t\t\t\t\t\tmultiplyVectorScalar (wind, calcWindForce(G_Particles[(i)*sqrtLen+(j)]->s, G_Particles[(i-1)*sqrtLen+(j+1)]->s, G_Particles[(i)*sqrtLen+(j+1)]->s, wind), &tmp2);\n\t\t\t\t\t\taddVectorVector (fWindForce, tmp2, &fWindForce);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tif (i < sqrtLen-1) {\n\t\t\t\t\tif (j < sqrtLen-1) {\n\t\t\t\t\t\t/* 4 */\n\t\t\t\t\t\tmultiplyVectorScalar (wind, calcWindForce(G_Particles[(i)*sqrtLen+(j)]->s, G_Particles[(i)*sqrtLen+(j+1)]->s, G_Particles[(i+1)*sqrtLen+(j+1)]->s, wind), &tmp2);\n\t\t\t\t\t\taddVectorVector (fWindForce, tmp2, &fWindForce);\n\t\t\t\t\t\t/* 5 */\n\t\t\t\t\t\tmultiplyVectorScalar (wind, calcWindForce(G_Particles[(i)*sqrtLen+(j)]->s, G_Particles[(i+1)*sqrtLen+(j+1)]->s, G_Particles[(i+1)*sqrtLen+(j)]->s, wind), &tmp2);\n\t\t\t\t\t\taddVectorVector (fWindForce, tmp2, &fWindForce);\n\t\t\t\t\t}\n\t\t\t\t\tif (j > 0) {\n\t\t\t\t\t\t/* 6 */\n\t\t\t\t\t\tmultiplyVectorScalar (wind, calcWindForce(G_Particles[(i)*sqrtLen+(j)]->s, G_Particles[(i+1)*sqrtLen+(j)]->s, G_Particles[(i+1)*sqrtLen+(j-1)]->s, wind), &tmp2);\n\t\t\t\t\t\taddVectorVector (fWindForce, tmp2, &fWindForce);\n\t\t\t\t\t\t/* 7 */\n\t\t\t\t\t\tmultiplyVectorScalar (wind, calcWindForce(G_Particles[(i)*sqrtLen+(j)]->s, G_Particles[(i+1)*sqrtLen+(j-1)]->s, G_Particles[(i)*sqrtLen+(j-1)]->s, wind), &tmp2);\n\t\t\t\t\t\taddVectorVector (fWindForce, tmp2, &fWindForce);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\tmultiplyVectorScalar (fWindForce, factor, &fWindForce);\n\t\t\t\t\n\t\t\t\t/* Kräfte */\n\t\t\t\taddVectorVector (fInt, fExt, &fComplete);\n\t\t\t\taddVectorVector (fComplete, fWindForce, &fComplete);\n\t\t\t\t\n\t\t\t\t/* Beschleunigung */\n\t\t\t\tp->a[0] = (-LAMDA * p->v[0] + fComplete[0]) / p->m;\n\t\t\t\tp->a[1] = (-LAMDA * p->v[1] + fComplete[1]) / p->m;\n\t\t\t\tp->a[2] = (-LAMDA * p->v[2] + fComplete[2]) / p->m;\n\t\t\t\t\n\t\t\t\t/* Geschwindigkeit */\n\t\t\t\tmultiplyVectorScalar (p->a, interval, &tmp);\n\t\t\t\taddVectorVector (p->v, tmp, &p->v);\n\t\t\t\t\n\t\t\t\tif (vectorLength3D(p->v) > MAX_V) {\n\t\t\t\t\t/*printf (\"V = %f\\n\", vectorLength3D(p->v));*/\n\t\t\t\t\tdivideVectorScalar (p->v, vectorLength3D(p->v), &(p->v));\n\t\t\t\t\tmultiplyVectorScalar(p->v, MAX_V, &(p->v));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Ort */\n\t\t\t\tmultiplyVectorScalar (p->v, interval, &tmp);\n\t\t\t\taddVectorVector (p->s, tmp, &p->s);\n\t\t\t\t\n\t\t\t\t/* Up */\n\t\t\t\tcrossProduct3D (tmp, p->v, p->a);\n\t\t\t\tcrossProduct3D (tmp, tmp, p->v);\n\t\t\t\t\n\t\t\t\tif (vectorLength3D(tmp) > 0.1)\n\t\t\t\t{\n\t\t\t\t\tp->up[0] = tmp[0];\n\t\t\t\t\tp->up[1] = tmp[1];\n\t\t\t\t\tp->up[2] = tmp[2];\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Eventuelle Anpassung der Entfernung zwischen Partikeln, wenn die Feder zu lang oder zu klein wird! */\n\t\t\t\n\t\t\t\tcorrectSpringLengthPosition(p, i, j);\n\t\t\t\t\n\t\t\t\t/* Kollision mit Boden */\n\t\t\t\tif (p->s[1] <= -WORLD_SIZE/2.0 + 0.5) {\n\t\t\t\t\tp->s[1] = -WORLD_SIZE/2.0 + 0.5;\n\t\t\t\t\tmultiplyVectorScalar(p->v, 0, &(p->v));\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Kollision mit Kugel(n) */\n\t\t\t\tfor (k=0;k<SPHERE_CNT;k++) {\n\t\t\t\t\tSpheres s = getSphereList()[k];\n\t\t\t\t\tdouble dist = 0.0;\n\t\t\t\t\t\n\t\t\t\t\tsubtractVectorVector(p->s, s->pos, &tmp);\n\t\t\t\t\tdist = vectorLength3D(tmp);\n\t\t\t\t\t\n\t\t\t\t\tif (dist < SPHERE_R+4.5) {\n\t\t\t\t\t\tdivideVectorScalar(tmp, dist, &tmp);\n\t\t\t\t\t\t\n\t\t\t\t\t\tmultiplyVectorScalar(tmp, SPHERE_R-dist+4.5, &tmp);\n\t\t\t\t\t\t\n\t\t\t\t\t\taddVectorVector(p->s, tmp, &(p->s));\n\t\t\t\t\t\tp->v[0] = 0;\n\t\t\t\t\t\tp->v[1] = 0;\n\t\t\t\t\t\tp->v[2] = 0;\n\t\t\t\t\t\t\n\t\t\t\t\t}\n\t\t\t\t\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t\t/* Kollision mit Quad(s) */\n\t\t\t\tfor (k=0;k<QUAD_CNT;k++) {\n\t\t\t\t\tQuads s = getQuadList()[k];\n\t\t\t\t\t\n\t\t\t\t\tif (\tp->s[1] <= s->pos[1]+QUAD_SIDE/2+2.5\n\t\t\t\t\t\t&&\tp->s[0] <= s->pos[0]+QUAD_SIDE/2+2.5\n\t\t\t\t\t\t&& \tp->s[0] >= s->pos[0]-QUAD_SIDE/2-2.5\n\t\t\t\t\t\t&& \tp->s[2] <= s->pos[2]+QUAD_SIDE/2+2.5\n\t\t\t\t\t\t&& \tp->s[2] >= s->pos[2]-QUAD_SIDE/2-2.5\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\n\t\t\t\t\t\tp->s[1] = s->pos[1]+QUAD_SIDE/2+2.5;\n\t\t\t\t\t\tmultiplyVectorScalar(p->v, 0, &(p->v));\n\t\t\t\t\t}\t\n\t\t\t\t}\n\t\t\t\t\n\t\t\t} else {\n\t\t\t\tParticle p2 = G_Particles[(i-1)*sqrtLen+j];\t\t\n\t\t\t\t\t\t\n\t\t\t\tcorrectConcreteParticleP2(p, p2, G_StructureSpringLengthInit);\n\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t}\n        \n\t}\n\t\n}\n\n\n/**\n * Fügt ein Partikel der Liste hinzu.\n */\nvoid addParticle (void)\n{\n    Particle p = malloc (sizeof(**G_Particles));\n    \n    G_Particles = realloc (G_Particles, sizeof(*G_Particles) * ++G_ParticleCnt);\n    \n    p->s[0] = rand()%(int)(5*WORLD_SIZE)/20.0 - rand()%(int)(5*WORLD_SIZE)/20.0;\n    p->s[1] = rand()%(int)(5*WORLD_SIZE)/20.0 - rand()%(int)(5*WORLD_SIZE)/20.0;\n    p->s[2] = rand()%(int)(5*WORLD_SIZE)/20.0 - rand()%(int)(5*WORLD_SIZE)/20.0;\n    \n    p->v[0] = 0.1;\n    p->v[1] = 0.0;\n    p->v[2] = 0.0;\n    \n    p->a[0] = 0.0;\n    p->a[1] = 0.0;\n    p->a[2] = 0.0;\n    \n    p->up[0] = 0.0;\n    p->up[1] = 0.0;\n    p->up[2] = 0.0;\n    \n    G_Particles[G_ParticleCnt-1] = p;\n}\n\n/**\n * Löscht das letzte Partikel\n */\n void deleteParticle (void)\n {\n    if (G_ParticleCnt >= 1) \n    {\n        free(G_Particles[G_ParticleCnt-1]);\n        G_Particles = realloc (G_Particles, sizeof(*G_Particles) * --G_ParticleCnt);\n    }\n }\n\n/**\n * Initialisiert die Partikel.\n */\nvoid initParticles(void)\n{\n\tint i,j;\n\tG_Particles = malloc (sizeof(*G_Particles) * G_ParticleCnt * G_ParticleCnt);\n\t\n\tfor (i=0;i<(int)(sqrt(G_ParticleCnt)+0.5);i++) {\n\t\tfor (j=0;j<(int)(sqrt(G_ParticleCnt)+0.5);j++) {\n\t\t\t\n\t\t\tParticle p = malloc (sizeof(**G_Particles));\n\t\t\t\n\t\t\tp->s[0] = PARTICLE_HEIGHT_INIT ;\n\t\t\tp->s[1] = i/((sqrt(G_ParticleCnt)))*WORLD_SIZE - WORLD_SIZE/2+0;\n\t\t\tp->s[2] = j/((sqrt(G_ParticleCnt)))*WORLD_SIZE - WORLD_SIZE/2;\n\t\t\t\n\t\t\t/*p->s[0] = i/((sqrt(G_ParticleCnt)))*WORLD_SIZE - WORLD_SIZE/2;\n\t\t\tp->s[1] = PARTICLE_HEIGHT_INIT;\n\t\t\tp->s[2] = j/((sqrt(G_ParticleCnt)))*WORLD_SIZE - WORLD_SIZE/2;*/\n\t\t\t\n\t\t\tp->v[0] = 0.0;\n\t\t\tp->v[1] = 0.0;\n\t\t\tp->v[2] = 0.0;\n\t\t\t\n\t\t\tp->a[0] = 0.0;\n\t\t\tp->a[1] = 0.0;\n\t\t\tp->a[2] = 0.0;\n\t\t\t\n\t\t\tp->up[0] = 0.0;\n\t\t\tp->up[1] = 0.0;\n\t\t\tp->up[2] = 0.0;\n\t\t\t\n\t\t\tp->m = PARTICLE_M;\n\t\t\tp->f[0] = 0.0;\n\t\t\tp->f[1] = 0.0;\n\t\t\tp->f[2] = 0.0;\n\t\t\t\n\t\t\tG_Particles[i*(int)(sqrt(G_ParticleCnt)+0.5) +j] = p;\n\t\t}\n\t}\n\t\n\tG_StructureSpringLengthInit = abs((i+1)/((sqrt(G_ParticleCnt)))*WORLD_SIZE - i/((sqrt(G_ParticleCnt)))*WORLD_SIZE);\n\tG_SheerSpringLengthInit = sqrt(pow(G_StructureSpringLengthInit, 2) + pow(G_StructureSpringLengthInit, 2));\n\tG_BendingSpringLengthInit = 2 * G_StructureSpringLengthInit;\n\t\n\tprintf (\"Strukturfeder-Länge: %f, Scherfeder-Länge: %f, Beugungsfeder-Länge: %f\\n\", G_StructureSpringLengthInit, G_SheerSpringLengthInit, G_BendingSpringLengthInit);\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "src/particle.h",
    "content": "#ifndef __PARTICLE_H__\n#define __PARTICLE_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * Programmlogik und Datenhaltung\n *\n * @author Maurice Tollmien\n */\n\n/* ---- System Header einbinden ---- */\n#ifdef WIN32\n#include <windows.h>\n#endif\n\n#ifdef MACOSX\n#include <OpenGL/glu.h>\n#else\n#include <GL/glu.h>\n#endif\n\n#include <stdio.h>\n#include <stdarg.h>\n\n#include \"types.h\"\n\n#define PARTICLE_HEIGHT_INIT\t40\t\n#define PARTICLE_CNT\t0\n#define PARTICLE_LEN\t1.0\n#define PARTICLE_M\t\t1.0\n#define K_WEAK\t\t\t1.0\n#define K_WEAK_INTERPOL\t0.05\n#define K_V\t\t\t\t1.5\n#define GAUSS\t\t\t10000.0\n#define CAMERA_PARTICLE_MULT 2.5\n\nParticle * getParticleList (void);\nint getParticleCnt (void);\nvoid initParticles(void);\nvoid calcParticleAttributesEuler (Spheres * spheres, int sphereCnt, double interval,int persecutorParticleMode, int cameraParticlePos);\nvoid addParticle (void); \nvoid deleteParticle (void);\nParticle getParticleAt(int i);\n\n#endif\n"
  },
  {
    "path": "src/scene.c",
    "content": "\n/**\n * @file\n * Hier wird vll gezeichnet...\n *\n * @author Maurice Tollmien, Tilman Nedele\n */\n\n/* ---- System Header einbinden ---- */\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <time.h>\n#include <math.h>\n#include <string.h>\n#include <stringOutput.h>\n\n#ifdef MACOSX\n#include <GLUT/glut.h>\n#else\n#include <GL/glut.h>\n#endif\n\n#include <GL/glu.h>\n\n/* ---- Eigene Header einbinden ---- */\n#include \"scene.h\"\n#include \"logic.h\"\n#include \"types.h\"\n#include \"water.h\"\n#include \"terrain.h\"\n#include \"vector.h\"\n\n\n/* ---- Globale Variablen für die Farben der Wände ------ */\nfloat G_R;\nfloat G_G;\nfloat G_B;\nfloat G_Alpha;\nfloat G_Shininess;\nint G_Emission;\n\n\n/* ---- Funktionen ---- */\n\n/**\n * Wird aufgerufen, wenn \"h\" gedrückt worden ist.\n * Gibt einen Text auf einem schwarzen Hintergrund auf dem Bildschirm aus\n */\nvoid printHelp (void)\n{\n    /* Textfarbe */\n    GLfloat textColor[3] = { 1.0f, 0.5f, 0.5f };\n\n    drawString (0.2f, 0.1f, textColor, HELP_OUTPUT_1);\n    drawString (0.2f, 0.125f, textColor, HELP_OUTPUT_2);\n    drawString (0.2f, 0.148f, textColor, HELP_OUTPUT_3);\n    drawString (0.2f, 0.171f, textColor, HELP_OUTPUT_4);\n    drawString (0.2f, 0.194f, textColor, HELP_OUTPUT_5);\n    drawString (0.2f, 0.217f, textColor, HELP_OUTPUT_6);\n    drawString (0.2f, 0.240f, textColor, HELP_OUTPUT_7);\n    drawString (0.2f, 0.263f, textColor, HELP_OUTPUT_8);\n    drawString (0.2f, 0.286f, textColor, HELP_OUTPUT_9);\n    drawString (0.2f, 0.311f, textColor, HELP_OUTPUT_10);\n    drawString (0.2f, 0.336f, textColor, HELP_OUTPUT_11);\n    drawString (0.2f, 0.361f, textColor, HELP_OUTPUT_12);\n    drawString (0.2f, 0.386f, textColor, HELP_OUTPUT_13);\n    drawString (0.2f, 0.411f, textColor, HELP_OUTPUT_14);\n    drawString (0.2f, 0.436f, textColor, HELP_OUTPUT_15);\n    drawString (0.2f, 0.461f, textColor, HELP_OUTPUT_16);\n    drawString (0.2f, 0.486f, textColor, HELP_OUTPUT_17);\n    drawString (0.2f, 0.505f, textColor, HELP_OUTPUT_18);\n    drawString (0.2f, 0.530f, textColor, HELP_OUTPUT_19);\n    drawString (0.2f, 0.555f, textColor, HELP_OUTPUT_20);\n    drawString (0.2f, 0.580f, textColor, HELP_OUTPUT_21);\n    drawString (0.2f, 0.605f, textColor, HELP_OUTPUT_22);\n    drawString (0.2f, 0.630f, textColor, HELP_OUTPUT_23);\n\n}\n\n\n\n/**\n * Setzt global eine Farbe!\n * @param color1,color2,color3 - RGB\n * @param alpha\n * @param shininess\n * @param emission\n */\nvoid setColor (float color1, float color2, float color3, float alpha, float shininess, int emission)\n{\n    float tmp[] = {0.0, 0.0, 0.0};\n    tmp[0] = color1;\n    tmp[1] = color2;\n    tmp[2] = color3;\n        \n    {\n        /* Material */\n        float matAmbient[] = {0.0, 0.0, 0.0, 0.0};\n        float matBlack[]= {0.0, 0.0, 0.0, 0.0};\n        float matDiffuse[] = {0.0, 0.0, 0.0, 0.0};\n        float matSpecular[] = {0.0, 0.0, 0.0, 0.0};\n        float matShininess[] = { 0.0 };\n        \n        matShininess[0] = shininess;\n        \n        matAmbient[0] = tmp[0];\n        matAmbient[1] = tmp[1];\n        matAmbient[2] = tmp[2];\n        matAmbient[3] = alpha;\n        \n        matSpecular[0] = tmp[0];\n        matSpecular[1] = tmp[1];\n        matSpecular[2] = tmp[2];\n        matSpecular[3] = alpha;\n        \n        matDiffuse[0] = tmp[0] - 0.7;\n        matDiffuse[1] = tmp[1] - 0.7;\n        matDiffuse[2] = tmp[2] - 0.7;\n        matDiffuse[3] = alpha;\n\n        /* Setzen der Material-Parameter */\n        glMaterialfv (GL_FRONT, GL_AMBIENT, matAmbient);\n        glMaterialfv (GL_FRONT, GL_DIFFUSE, matDiffuse);\n        glMaterialfv (GL_FRONT, GL_SPECULAR, matSpecular);\n        glMaterialfv (GL_FRONT, GL_SHININESS, matShininess);\n        if (emission)\n            glMaterialfv (GL_FRONT, GL_EMISSION, matSpecular);\n        else\n            glMaterialfv (GL_FRONT, GL_EMISSION, matBlack);\n    }\n}\n\n/**\n * Zeichnet Kugel mit mehr Parametern.\n * @param sliceCount - Anzahl der Unterteilungen\n * @param r - Radius\n */\nvoid drawSphere (int sliceCount, double r)\n{\n\tGLUquadricObj * body;\n    \n    body = gluNewQuadric ();\n    if (body == NULL)\n        exit (1);\n\n    /* Normalen fuer Quadrics berechnen lassen */\n    gluQuadricNormals (body, GLU_SMOOTH);\n    \n    gluSphere (body, r, sliceCount, sliceCount);\n\n    gluDeleteQuadric (body);\n}\n\n/**\n * Zeichnet ein Quadrat mit der Kantenlaenge 1, das aus mehreren kleineren\n * Quadraten zusammen gesetzt ist.\n * @param subDivs Anzahl der Unterteilungsschritte der Kanten.\n */\nstatic void\ndrawSquare (GLint subDivs)\n{\n  int x, y;\n\n  for (y = 0; y < subDivs + 1; y++)\n    {\n\t\tglNormal3f (0.0f, 0.0f, 1.0f);\n\t\tglBegin (GL_QUAD_STRIP);\n\t\t\n\t\tfor (x = 0; x <= subDivs + 1; x++)\n\t\t{\n\t\t/* Texturkoordinate,\n\t\tgilt nicht, wenn Texturkoordinaten automatisch generiert werden. */\n\t\t/*glTexCoord2f (x / (subDivs + 1.0f), y / (subDivs + 1.0f));*/\n\t\tglVertex3f (-0.5f + x / (subDivs + 1.0f),\n\t\t\t\t   0.5f - y / (subDivs + 1.0f),\n\t\t\t\t   0.0f);\n\n\t\t/* Texturkoordinate,\n\t\tgilt nicht, wenn Texturkoordinaten automatisch generiert werden. */\n\t\t/*glTexCoord2f (x / (subDivs + 1.0f), (y + 1) / (subDivs + 1.0f));*/\n\t\tglVertex3f (-0.5f +    x    / (subDivs + 1.0f),\n\t\t\t\t   0.5f - (y + 1) / (subDivs + 1.0f),\n\t\t\t\t   0.0f);\n\t\t}\n      glEnd ();\n    }\n\n}\n\n/**\n * Zeichnet einen Wuerfel mit Kantenlaenge 1.\n * @param subDivs Anzahl der Unterteilungsschritte der Kanten.\n */\nstatic void\ndrawCube (unsigned int subDivs, GLfloat radius)\n{\n  /* Frontflaeche */\n  glPushMatrix ();\n  {\n    glTranslatef (0.0f, 0.0f, radius);\n    drawSquare (subDivs);\n  }\n  glPopMatrix ();\n\n  /* rechte Seitenflaeche */\n  glPushMatrix ();\n  {\n    glRotatef (90.0f, 0.0f, 1.0f, 0.0f);\n    glTranslatef (0.0f, 0.0f, radius);\n    drawSquare (subDivs);\n }\n  glPopMatrix ();\n\n  /* Rueckseitenflaeche */\n  glPushMatrix ();\n  {\n    glRotatef (180.0f, 0.0f, 1.0f, 0.0f);\n    glTranslatef (0.0f, 0.0f, radius);\n    drawSquare (subDivs);\n  }\n  glPopMatrix ();\n\n\n  /* linke Seitenflaeche */\n  glPushMatrix ();\n  {\n    glRotatef (270.0f, 0.0f, 1.0f, 0.0f);\n    glTranslatef (0.0f, 0.0f, radius);\n    drawSquare (subDivs);\n  }\n  glPopMatrix ();\n\n  /* Deckelflaeche */\n  glPushMatrix ();\n  {\n    glRotatef (-90.0f, 1.0f, 0.0f, 0.0f);\n    glTranslatef (0.0f, 0.0f, radius);\n    drawSquare (subDivs);\n  }\n  glPopMatrix ();\n\n  /* Bodenflaeche */\n  /*glPushMatrix ();\n  {\n    glRotatef (90.0f, 1.0f, 0.0f, 0.0f);\n    glTranslatef (0.0f, 0.0f, radius);\n    drawSquare (subDivs);\n  }\n  glPopMatrix ();*/\n}\n\n/**\n * Zeichnet ein Quadrat mit den Ecken p1,p2,p3,p4 in der Farbe color=1/0\n * @param p1,p2,p3,p4 - Die Ecken\n * @param color - schwarz = 0 / weiß = 1\n */\nvoid drawVertex(CGPoint3f p1, CGPoint3f p2, CGPoint3f p3, CGPoint3f p4, int color)\n{\n     if (color)\n        setColor(1.0,1.0,1.0,G_Alpha,G_Shininess,G_Emission);\n    else\n        setColor(G_R,G_G,G_B,G_Alpha,G_Shininess,G_Emission);\n      glBegin (GL_QUADS);\n      {\n        glVertex3f(p1[0],p1[1],p1[2]);\n        glVertex3f(p2[0],p2[1],p2[2]);\n        glVertex3f(p3[0],p3[1],p3[2]);\n        glVertex3f(p4[0],p4[1],p4[2]);\n      }\n      glEnd();\n}\n\n/**\n * Zeichnet den Boden\n */\nvoid drawBottom(void)\n{\n    CGPoint3f p1 = {0.0,GROUND_HEIGHT,0.0},\n          p2 = {WORLD_SIZE,GROUND_HEIGHT,0.0},\n          p3 = {WORLD_SIZE,GROUND_HEIGHT,WORLD_SIZE},\n          p4 = {0.0,GROUND_HEIGHT,WORLD_SIZE};\n\n\t\n\t/*glDisable (GL_DEPTH_TEST);*/\n    /*glDisable(GL_CULL_FACE);*/\n    \n    glPushMatrix ();\n    {\n        glTranslatef(-(WORLD_SIZE/2), -WORLD_SIZE/2.0+0.1,-(WORLD_SIZE/2));\n\t\t/*setColor (0.0, 0.0, 0.0, 1.0, 40, 1);*/\n        drawRecursiveQuad(p1,p2,p3,p4,getQuadCount(),0);\n    }\n    glPopMatrix ();\n    \n    /*glEnable(GL_CULL_FACE);*/\n    /*glEnable (GL_DEPTH_TEST);*/\n}\n\n/**\n * Zeichnet die Wände\n */\nvoid drawSides(void) \n{\t\n\tglPushMatrix();\n\t{\n\t\tG_R = 1.0;\n\t\tG_G = 0.0;\n\t\tG_B = 0.0;\n\t\tG_Alpha = 1.0;\n\t\tG_Shininess = 40;\n\t\tG_Emission = 1;\n\t\tglRotatef(90,1,0,0);\n\t\tdrawBottom();\n\t}\n\tglPopMatrix();\n\tglPushMatrix();\n\t{\n\t\tG_R = 0.0;\n\t\tG_G = 1.0;\n\t\tG_B = 0.0;\n\t\tG_Alpha = 1.0;\n\t\tG_Shininess = 40;\n\t\tG_Emission = 1;\n\t\tglRotatef(90,1,0,0);\n\t\tglRotatef(180,0,0,1);\n\t\tdrawBottom();\n\t}\n\tglPopMatrix();\n\tglPushMatrix();\n\t{\n\t\tG_R = 0.0;\n\t\tG_G = 0.0;\n\t\tG_B = 1.0;\n\t\tG_Alpha = 1.0;\n\t\tG_Shininess = 40;\n\t\tG_Emission = 1;\n\t\tglRotatef(90,1,0,0);\n\t\tglRotatef(90,0,0,1);\n\t\tdrawBottom();\n\t}\n\tglPopMatrix();\n\tglPushMatrix();\n\t{\n\t\tG_R = 0.5;\n\t\tG_G = 0.5;\n\t\tG_B = 0.5;\n\t\tG_Alpha = 1.0;\n\t\tG_Shininess = 40;\n\t\tG_Emission = 1;\n\t\tglRotatef(90,1,0,0);\n\t\tglRotatef(90,0,0,-1);\n\t\tdrawBottom();\n\t}\n\tglPopMatrix();\n\t\n\t/* Oben! */\n\tglPushMatrix();\n\t{\n\t\tG_R = 1.0;\n\t\tG_G = 1.0;\n\t\tG_B = 0.0;\n\t\tG_Alpha = 1.0;\n\t\tG_Shininess = 40;\n\t\tG_Emission = 1;\n\t\tglRotatef(180,1,0,0);\n\t\tdrawBottom();\n\t}\n\tglPopMatrix();\n\t\n\t/* Unten! */\n\tglPushMatrix();\n\t{\n\t\tG_R = 0.0;\n\t\tG_G = 0.0;\n\t\tG_B = 0.0;\n\t\tG_Alpha = 1.0;\n\t\tG_Shininess = 40;\n\t\tG_Emission = 1;\n\t\tglRotatef(360,1,0,0);\n\t\tdrawBottom();\n\t}\n\tglPopMatrix();\n\t\n}\n\n\n/**\n * Zeichnet die Welt\n */\nvoid drawWorld() {\n\n\n    glDisable(GL_CULL_FACE);\n    glPushMatrix();\n    {\n\t\tsetColor (WHITE, 1.0, 30.0, 0);\n        /*glTranslatef(0,(30.0f)/2,0);*/\n        glScalef(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE);\n        drawCube(20,0.5f);\n    }\n    glPopMatrix();\n  glEnable(GL_CULL_FACE);\n}\n\n/**\n * Zeichnet die beiden Referenzkugeln\n */\nvoid drawSpheres(void)\n{\n\tint i;\n\tglEnable(GL_BLEND);\n\tglBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\n\t\n\t\tfor (i=0;i<SPHERE_CNT;i++)\n\t\t{\n\t\t\tglPushMatrix();\n\t\t\t{\n\t\t\t\tSpheres s = getSphereList()[i];\n\t\t\t\tglTranslatef(s->pos[0],s->pos[1],s->pos[2]);\n\t\t\t\n\t\t\t\tsetColor (s->color[0],s->color[1],s->color[2], SPHERE_TRANSPARENCY, 0.0, 1);\n\t\t\t\tglCullFace (GL_FRONT);\n\t\t\t\tdrawSphere (SLICE_CNT, SPHERE_R);\n\t\t\t\tglCullFace (GL_BACK);\n\t\t\t\tdrawSphere (SLICE_CNT, SPHERE_R);\n\t\t\t}\n\t\t\tglPopMatrix();\n\t\t}\n\t\n\tglDisable (GL_BLEND);\n\t\n}\n\nvoid drawQuads(void) \n{\n\t\n\tint i;\n\t\n\tfor (i=0;i<QUAD_CNT;i++)\n\t{\n\t\tglPushMatrix();\n\t\t{\n\t\t\tQuads s = getQuadList()[i];\n\t\t\tglTranslatef(s->pos[0],s->pos[1],s->pos[2]);\n\t\t\tglScalef(QUAD_SIDE, QUAD_SIDE, QUAD_SIDE);\n\t\t\t\n\t\t\tdrawCube (1, 0.5);\n\t\t\t\n\t\t}\n\t\tglPopMatrix();\n\t}\n\n}\n\n/**\n * Malt ein übergebenes Partikel in den Ursprung\n */\nvoid drawOneParticle(Particle p, int suspensionPoint)\n{  \n\tif (getParticleType() == sphere) {  \n\t\tif (suspensionPoint) \n\t\t\tsetColor (GREEN, 1.0, 0, 1);\n\t\telse\n\t\t\tsetColor (RED, 1.0, 0, 1);\n\t\t\n\t\tglPushMatrix();\n\t\t{\n\t\t\tglTranslatef(p->s[0],p->s[1],p->s[2]);\n\t\t\tdrawSphere (4, 0.8);\n\t\t}\n\t\tglPopMatrix();\n\t\t\t\t\n\t\tsetColor (WHITE, 1.0, 0, 1);\n\t}\n\t\t\t\n}\n\n/**\n * Malt die Normale --> Up-Vektor des Partikels\n */\nvoid drawParticleNormal (Particle p)\n{\n    \n    glBegin (GL_LINES);\n    {\n        CGVector3D up;\n        /*printf (\"scene: up: %f, %f, %f\\n\", p->up[0],p->up[1],p->up[2]);*/\n        up[0]=p->up[0];\n        up[1]=p->up[1];\n        up[2]=p->up[2];\n        normVector3D(up);\n        glVertex3f(p->s[0],p->s[1],p->s[2]);\n        glVertex3f(up[0]+p->s[0],up[1]+p->s[1],up[2]+p->s[2]);\n    }\n    glEnd ();\n}\n\nvoid drawFPS (void)\n{\n\tGLfloat textColor[3] = { 1.0f, 1.0f, 1.0f };\n\tchar * string = calloc ((strlen (\"FPS = \") + 4), sizeof(char));\n\tsprintf(string, \"FPS = %d\", getFPS());\n\t\n\tdrawString (0.6, 0.1, textColor, string);\n\t\n\tfree (string);\n}\n\nvoid drawWaterSurface(void) \n{\n\tWater * water = getWaterList();\n\tint i,j;\n\t\n\t/* Punkte anzeigen. */\n\tglPointSize(1.0);\n\tfor (i=0;i<WORLD_SIZE*WORLD_SIZE;i++) {\n\t\tglBegin (GL_POINTS);\n\t\t\tglVertex3f(water[i].x, water[i].y, water[i].z);\n\t\tglEnd();\n\t}\n\t\n\t\n\t\n}\n\nvoid drawTerrainSurface(void)\n{\n\tTerrain * terrain = getTerrainList();\n\tGLuint * indices = getTerrainIndices();\n\tint i,j;\n\t\n\t/* Punkte anzeigen. */\n\tif (0) {\n\t\tglPointSize(4.0);\n\t\tfor (i=0;i<TERRAIN_SIZE*TERRAIN_SIZE;i++) {\n\t\t\tglBegin (GL_POINTS);\n\t\t\t\tglVertex3f(terrain[i].x, terrain[i].y, terrain[i].z);\n\t\t\tglEnd();\n\t\t}\n\t}\n\t/* Linestrip. */\n\tif (1) {\n\t\t\n\t\tfor (i=0;i<TERRAIN_SIZE*TERRAIN_SIZE*3*2;i+=3) {\n\t\t\tglBegin(GL_TRIANGLES);\n\t\t\t\tglVertex3f(terrain[indices[i]].x, terrain[indices[i]].y, terrain[indices[i]].z);\n\t\t\t\tglVertex3f(terrain[indices[i+1]].x, terrain[indices[i+1]].y, terrain[indices[i+1]].z);\n\t\t\t\tglVertex3f(terrain[indices[i+2]].x, terrain[indices[i+2]].y, terrain[indices[i+2]].z);\n\t\t\tglEnd();\n\t\t}\n\t\t\n\t}\n}\n\t\n\n/**\n * Zeichen-Funktion.\n * Stellt die Szenerie rund um die Rennstrecke dar.\n */\nvoid drawScene (void)\n{\n    CGPoint4f \tlightPos2 = { 0.0f, 20.0f, 0.0f, 1.0f };\n       \n    CGPoint4f \tlightPos1 = { 0.0f, 5.0f, 10.0f, 1.0f };\n    CGPoint3f \tlightDir1  = { 0.0, -5.0, -10.0 };\n    \n\n    glLightfv (GL_LIGHT2, GL_POSITION, lightPos2);\n\n    glLightfv (GL_LIGHT1, GL_POSITION, lightPos1);\n    glLightfv (GL_LIGHT1, GL_SPOT_DIRECTION, lightDir1);\n\t\n    setColor (BLACK, 1.0, 0.0, 0);\n\t\n    if (!getHelpStatus()) \n    {\n        if (getLightStatus()){\n\t\t\t/*glEnable (GL_LIGHT1);*/\n            glEnable (GL_LIGHT2);\n        } else {\n\t\t\tglDisable (GL_LIGHT1);\n\t\t\tglDisable (GL_LIGHT2);\n        }\n\n        /* Zeichnet den Boden*/\n        G_R = 0.0;\n\t\tG_G = 0.0;\n\t\tG_B = 0.0;\n\t\tG_Alpha = 1.0;\n\t\tG_Shininess = 40;\n\t\tG_Emission = 1;\n        drawBottom();\n        \n        drawSides();\n        \n        /* Zeichnet die beiden Kugeln */\n        drawSpheres();\n        \n        drawQuads();\n                \n        /* Zeichnet die Partikel */\n        /*drawParticles();\n        \n        drawParticleCloth();*/\n        \n        drawWaterSurface();\n            \n        drawFPS ();\n        \n                \n    } else {\n        printHelp();\n    }\n    \n}\n\n/**\n * Initialisierung der Lichtquellen.\n * Setzt Eigenschaften der Lichtquellen (Farbe, Oeffnungswinkel, ...)\n */\nstatic void initLight (void)\n{\n\n    /* Farbe der zweiten Lichtquelle */\n\tCGPoint4f lightColor1[3] =\n\t{ {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f,\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t   1.0f}\n\t};\n    \n    /* Farbe der ersten Lichtquelle */\n    CGPoint4f lightColor2[3] =\n    { {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f,\n                                                           1.0f}\n    };\n    \n\t/* Oeffnungswinkel der zweiten Lichtquelle */\n\tGLdouble lightCutoff1 = 90.0f;\n\t/* Lichtverteilung im Lichtkegel der zweiten Lichtquelle */\n\tGLdouble lightExponent1 = 20.0f;\n    \n    float globalAmbientLight[] = {0.3, 0.3, 0.3, 1.0};\n    \n    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globalAmbientLight);\n    \n    /* Farbe der zweiten Lichtquelle setzen */\n\tglLightfv (GL_LIGHT1, GL_AMBIENT, lightColor1[0]);\n\tglLightfv (GL_LIGHT1, GL_DIFFUSE, lightColor1[1]);\n\tglLightfv (GL_LIGHT1, GL_SPECULAR, lightColor1[2]);\n    \n    /* Spotlight-Eigenschaften der zweiten Lichtquelle setzen */\n\tglLightf (GL_LIGHT1, GL_SPOT_CUTOFF, lightCutoff1);\n\tglLightf (GL_LIGHT1, GL_SPOT_EXPONENT, lightExponent1);\n    \n    /* Farbe der zweiten Lichtquelle setzen */\n\tglLightfv (GL_LIGHT2, GL_AMBIENT, lightColor2[0]);\n\tglLightfv (GL_LIGHT2, GL_DIFFUSE, lightColor2[1]);\n\tglLightfv (GL_LIGHT2, GL_SPECULAR, lightColor2[2]);\n\t\n\t/* Spotlight-Eigenschaften der zweiten Lichtquelle setzen */\n\tglLightf (GL_LIGHT2, GL_SPOT_CUTOFF, lightCutoff1);\n\tglLightf (GL_LIGHT2, GL_SPOT_EXPONENT, lightExponent1);\n}\n\n/**\n * Bei SPIEelbegin wird das SPIEelfeld komplett initialisiert\n * mit einem Hintergrund, einer Zeichenfarbe, Linienbreite.\n * Außerdem wird die Datenhaltung initialisiert (siehe initField (), initStones ()).\n * @return Ob ein Fehler aufgetreten ist.\n */\nint initScene (void)\n{\n\tglEnable (GL_DEPTH_TEST);\n\tglCullFace (GL_BACK);\n\tglEnable (GL_CULL_FACE);\n\tglEnable (GL_NORMALIZE);\n\tglEnable (GL_LIGHTING);\n\tinitLight ();\n\tinitGame ();\n\n\treturn 1;\n}\n\n\n\n/**\n * (De-)aktiviert den Wireframe-Modus.\n */\nvoid\ntoggleWireframeMode (void)\n{\n    /* Flag: Wireframe: ja/nein */\n    static GLboolean wireframe = GL_FALSE;\n\n    /* Modus wechseln */\n    wireframe = !wireframe;\n\n    if (wireframe)\n        glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);\n    else\n        glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);\n}\n\n"
  },
  {
    "path": "src/scene.h",
    "content": "#ifndef __SCENE_H__\n#define __SCENE_H__\n\n#define __DEBUG_GL_H__\n/**\n * @file\n * hier kann gezeichnet werden (Hoffentlich^^)\n *\n * @author Maurice Tollmien\n */\n\n/* ---- System Header einbinden ---- */\n#ifdef WIN32\n#include <windows.h>\n#endif\n\n#ifdef MACOSX\n#include <OpenGL/glu.h>\n#else\n#include <GL/glu.h>\n#endif\n\n#include <stdio.h>\n#include <stdarg.h>\n#include \"types.h\"\n\nvoid drawVertex(CGPoint3f p1, CGPoint3f p2, CGPoint3f p3, CGPoint3f p4, int color);\nvoid drawScene (void);\nvoid drawWaterSurface(void);\nvoid drawFPS (void);\nvoid drawSides(void);\nint initScene (void);\nvoid toggleWireframeMode (void);\n\n#endif\n"
  },
  {
    "path": "src/stringOutput.c",
    "content": "/**\n * @file\n * Einfache Funktion zum Zeichnen von Text fuer GLUT-Programme.\n */\n\n/* ---- System Header einbinden ---- */\n#include <string.h>\n#include <stdio.h>\n#include <stdarg.h>\n\n#ifdef MACOSX\n#include <GLUT/glut.h>\n#else\n#include <GL/glut.h>\n#endif\n\n/* ---- Eigene Header einbinden ---- */\n#include \"stringOutput.h\"\n\n/**\n * Zeichnen einer Zeichfolge in den Vordergrund. Gezeichnet wird mit Hilfe von\n * <code>glutBitmapCharacter(...)</code>. Kann wie <code>printf genutzt werden.</code>\n * @param x x-Position des ersten Zeichens 0 bis 1 (In).\n * @param y y-Position des ersten Zeichens 0 bis 1 (In).\n * @param color Textfarbe (In).\n * @param format Formatstring fuer die weiteren Parameter (In).\n */\nvoid\ndrawString (GLfloat x, GLfloat y, GLfloat * color, char *format, ...)\n{\n\n  GLint matrixMode;             /* Zwischenspeicher akt. Matrixmode */\n  va_list args;                 /* variabler Teil der Argumente */\n  char buffer[255];             /* der formatierte String */\n  char *s;                      /* Zeiger/Laufvariable */\n  va_start (args, format);\n  vsprintf (buffer, format, args);\n  va_end (args);\n\n  /* aktuelle Zeichenfarbe (u.a. Werte) sichern */\n  glPushAttrib (GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT);\n\n  /* aktuellen Matrixmode speichern */\n  glGetIntegerv (GL_MATRIX_MODE, &matrixMode);\n  glMatrixMode (GL_PROJECTION);\n\n  /* aktuelle Projektionsmatrix sichern */\n  glPushMatrix ();\n\n  /* neue orthogonale 2D-Projektionsmatrix erzeugen */\n  glLoadIdentity ();\n  gluOrtho2D (0.0, 1.0, 1.0, 0.0);\n\n  glMatrixMode (GL_MODELVIEW);\n\n  /* aktuelle ModelView-Matrix sichern */\n  glPushMatrix ();\n\n  /* neue ModelView-Matrix zuruecksetzen */\n  glLoadIdentity ();\n\n  /* Tiefentest ausschalten */\n  glDisable (GL_DEPTH_TEST);\n\n  /* Licht ausschalten */\n  glDisable (GL_LIGHTING);\n\n  /* Nebel ausschalten */\n  glDisable (GL_FOG);\n\n  /* Blending ausschalten */\n  glDisable (GL_BLEND);\n\n  /* Texturierung ausschalten */\n  glDisable (GL_TEXTURE_1D);\n  glDisable (GL_TEXTURE_2D);\n  /* glDisable (GL_TEXTURE_3D); */\n\n  /* neue Zeichenfarbe einstellen */\n  glColor4fv (color);\n\n  /* an uebergebenene Stelle springen */\n  glRasterPos2f (x, y);\n\n  /* Zeichenfolge zeichenweise zeichnen */\n  for (s = buffer; *s; s++)\n\n    {\n      glutBitmapCharacter (GLUT_BITMAP_HELVETICA_18, *s);\n    }\n\n  /* alte ModelView-Matrix laden */\n  glPopMatrix ();\n  glMatrixMode (GL_PROJECTION);\n\n  /* alte Projektionsmatrix laden */\n  glPopMatrix ();\n\n  /* alten Matrixmode laden */\n  glMatrixMode (matrixMode);\n\n  /* alte Zeichenfarbe und Co. laden */\n  glPopAttrib ();\n}\n"
  },
  {
    "path": "src/stringOutput.h",
    "content": "#ifndef _STRING_OUTPUT_H\n#define _STRING_OUTPUT_H\n/**\n * @file\n * Einfache Funktion zum Zeichnen von Text fuer GLUT-Programme.\n */\n\n/* ---- System Header einbinden ---- */\n#ifdef MACOSX\n#include <OpenGL/gl.h>\n#else\n#include <GL/gl.h>\n#endif\n\n/* ---- Funktionsprototypen ---- */\n\n/**\n * Zeichnen einer Zeichfolge in den Vordergrund. Gezeichnet wird mit Hilfe von\n * <code>glutBitmapCharacter(...)</code>. Kann wie <code>printf genutzt werden.</code>\n * @param x x-Position des ersten Zeichens 0 bis 1 (In).\n * @param y y-Position des ersten Zeichens 0 bis 1 (In).\n * @param color Textfarbe (In).\n * @param format Formatstring fuer die weiteren Parameter (In).\n */\nvoid drawString (GLfloat x, GLfloat y, GLfloat * color, char *format, ...);\n\n#endif\n"
  },
  {
    "path": "src/terrain.c",
    "content": "\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <math.h>\n/* ---- Eigene Header einbinden ---- */\n#include \"terrain.h\"\n#include \"logic.h\"\n#include \"vector.h\"\n#include \"types.h\"\n\nTerrain * G_TerrainList;\nGLuint * G_TerrainIndices;\n\nTerrain * G_TerrainCaustics;\n\nTerrain * getTerrainList(void){\n\treturn G_TerrainList;\n}\n\nTerrain * getTerrainCaustics(void) {\n\treturn G_TerrainCaustics;\n}\n\nGLuint * getTerrainIndices (void) \n{\n\treturn G_TerrainIndices;\n}\n\nvoid initTerrainIndices(void) {\n\t\n\tint i,j;\n\tint index = 0;\n\tfor (i=0;i<TERRAIN_SIZE*TERRAIN_SIZE;i++) {\t\t\n\t\tint atI = i % TERRAIN_SIZE;\n\t\tint atJ = i / TERRAIN_SIZE;\n\t\t\n\t\tif (atI == TERRAIN_SIZE-1 || atJ == TERRAIN_SIZE-1) {\n\t\t\tcontinue;\n\t\t}\n\t\t\n\t\tG_TerrainIndices[index]   = i;\n\t\tG_TerrainIndices[index+1] = i+1;\n\t\tG_TerrainIndices[index+2] = i+TERRAIN_SIZE+1;\n\t\t\n\t\tG_TerrainIndices[index+3] = i;\n\t\tG_TerrainIndices[index+4] = i+TERRAIN_SIZE+1;\n\t\tG_TerrainIndices[index+5] = i+TERRAIN_SIZE;\n\t\t\n\t\tindex += 6;\n\t}\n\t\n}\n\nvoid calcTerrainNormals(void) {\n\tint i;\n\tfor (i=0;i<TERRAIN_SIZE*TERRAIN_SIZE;i++) {\n\t\tint atI = i % TERRAIN_SIZE;\n\t\tint atJ = i / TERRAIN_SIZE;\n\t\t\n\t\tif (atI < 1 || atI >= TERRAIN_SIZE-1 || atJ < 1 || atJ >= TERRAIN_SIZE-1) {\n\t\t\tcontinue;\n\t\t}\n\t\t\n\t\tCGVector3D v1 = {G_TerrainList[i-TERRAIN_SIZE].x - G_TerrainList[i].x, G_TerrainList[i-TERRAIN_SIZE].y - G_TerrainList[i].y, G_TerrainList[i-TERRAIN_SIZE].z - G_TerrainList[i].z};\n\t\tCGVector3D v2 = {G_TerrainList[i-1].x - G_TerrainList[i].x, G_TerrainList[i-1].y - G_TerrainList[i].y, G_TerrainList[i-1].z - G_TerrainList[i].z};\n\t\tCGVector3D res1;\n\t\tcrossProduct3D(res1, v1, v2);\n\t\t\n\t\tCGVector3D v3 = {G_TerrainList[i+TERRAIN_SIZE].x - G_TerrainList[i].x, G_TerrainList[i+TERRAIN_SIZE].y - G_TerrainList[i].y, G_TerrainList[i+TERRAIN_SIZE].z - G_TerrainList[i].z};\n\t\tCGVector3D v4 = {G_TerrainList[i+1].x - G_TerrainList[i].x, G_TerrainList[i+1].y - G_TerrainList[i].y, G_TerrainList[i+1].z - G_TerrainList[i].z};\n\t\tCGVector3D res2;\n\t\tcrossProduct3D(res2, v3, v4);\n\t\t\n\t\tif (res1[1] < 0) {\n\t\t\tmultiplyVectorScalar(res1, -1, &res1);\n\t\t}\n\t\tif (res2[1] < 0) {\n\t\t\tmultiplyVectorScalar(res2, -1, &res2);\n\t\t}\n\t\tCGVector3D normal;\n\t\taddVectorVector(res1, res2, &normal);\n\t\t\n\t\tG_TerrainList[i].nx = normal[0];\n\t\tG_TerrainList[i].ny = normal[1];\n\t\tG_TerrainList[i].nz = normal[2];\n\t\t\n\t\tG_TerrainCaustics[i].nx = G_TerrainList[i].nx;\n\t\tG_TerrainCaustics[i].ny = G_TerrainList[i].ny;\n\t\tG_TerrainCaustics[i].nz = G_TerrainList[i].nz;\n\t\t\n\t}\n\t\n}\n\n/**\n * Kubische Interpolation.\n */\ndouble interpolateCube(double v0, double v1, double v2, double v3, double x) {\n\tdouble p = (v3 - v2) - (v0 - v1);\n\tdouble q = (v0 - v1) - p;\n\tdouble r = v2 - v0;\n\tdouble s = v1;\n\treturn p*pow(x, 3) + q*pow(x, 2) + r*x + s;\n}\n\n/**\n * Kosinus-Interpolation.\n */\ndouble interpolateCos(double a, double b, double x) {\n\tdouble ft = x * 3.1415927;\n\tdouble f  = (1 - cos(ft)) * 0.5;\n\treturn a*(1-f) + b*f;\n}\n\n/**\n * Erzeugt random-Noise-Wert zwischen 0..1\n */\ndouble noise(int x, int y) {\n\tlong n = x + y * 57;\n\tn = (n<<13) ^ n;\n\treturn (1.0 - ((n * (n*n*15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);\n}\n\n\n/**\n * Erzeugt Noise... Etwas angepasst und smoothed.\n */\ndouble smoothedNoise(float x, float y) {\n\tdouble corners \t= ( noise(x-1, y-1) + noise(x+1, y-1) + noise(x-1, y+1) + noise(x+1, y+1) ) / 16.0;\n\tdouble sides\t= ( noise(x-1, y  ) + noise(x+1, y  ) + noise(x  , y-1) + noise(x  , y+1) ) / 8;\n\tdouble center\t= noise(x,y) / 4;\n\treturn corners + sides + center;\n}\n\n/**\n * Interpoliert das errechneten Noise, um perfekte fließende Übergänge zu erreichen (je nach Interpolationsart).\n */\ndouble interpolatedNoise(float x, float y) {\n\t\n\tint intX \t\t\t= (int)x;\n\tdouble fractionalX \t= x - intX;\n\tint intY\t\t\t= (int)y;\n\tdouble fractionalY \t= y - intY;\n\t\n\tdouble v1 = smoothedNoise (intX\t\t, intY \t\t);\n\tdouble v2 = smoothedNoise (intX + 1\t, intY \t\t);\n\tdouble v3 = smoothedNoise (intX\t\t, intY + 1\t);\n\tdouble v4 = smoothedNoise (intX + 1\t, intY + 1\t);\n\t\n\tdouble i1 = interpolateCos(v1, v2, fractionalX);\n\tdouble i2 = interpolateCos(v3, v4, fractionalX);\n\t\n\treturn interpolateCos(i1, i2, fractionalY);\n}\n\n/**\n * Berechnet einen Perlin-Noise-Wert für eine beliebige Position auf dem Feld!\n */\ndouble perlinNoise2D(float x, float y) {\n\tdouble \ttotal  \t= 0.0;\n\tdouble \tp \t\t= PERSISTENCE;\n\tint \tn\t\t= OCTAVES_COUNT;\n\tint i;\n\t\n\tfor (i = 0;i<n;i++) {\n\t\t\n\t\tdouble frequency = pow(2, i);\n\t\tdouble amplitude = pow(p, i);\n\t\t\n\t\ttotal += interpolatedNoise (x * frequency, y * frequency) * amplitude;\n\t\t\n\t}\n\t\n\treturn total;\n}\n\ndouble gauss(float x, float y, float offset) {\n\tfloat a = 3.0;\n\tfloat e = 2.71828182846;\n\tfloat spread = 25.0;\n\t\n\tx = x + offset;\n\ty = y + offset;\n\t\n\tfloat term = -(pow(x,2)/(2*spread) + pow(y,2)/(2*spread));\n\treturn -a * pow(e, term);\n}\n\nvoid initTerrain(void) {\n\t\n\tint i,j;\n\t\n\tdouble min, max;\n\t\n\tG_TerrainList = calloc(TERRAIN_SIZE*TERRAIN_SIZE, sizeof(*G_TerrainList));\n\tG_TerrainCaustics = calloc(TERRAIN_SIZE*TERRAIN_SIZE, sizeof(*G_TerrainList));\n\tG_TerrainIndices = calloc(TERRAIN_SIZE*TERRAIN_SIZE*2*3, sizeof(*G_TerrainIndices));\n\n\tfor (i=0;i<(TERRAIN_SIZE)*(TERRAIN_SIZE);i++) {\n\t\tint xCoord = i / TERRAIN_SIZE;\n\t\tint zCoord = i % TERRAIN_SIZE;\n\t\t\n\t\tG_TerrainList[i].x = (xCoord - TERRAIN_SIZE/2) * TERRAIN_DISTANCE;\n\t\t\n\t\tfloat noiseAtX = (float)xCoord/10.0;\n\t\tfloat noiseAtZ = (float)zCoord/10.0;\n\t\t\n\t\tG_TerrainList[i].y = \t(perlinNoise2D(noiseAtX, noiseAtZ)*TERRAIN_DIMENSION\n\t\t\t\t\t\t\t\t/* Die 0.8 ist ein manueller Versatz, damit die Wasserkante nicht sichtbar ist. */\n\t\t\t\t\t\t\t\t+ gauss(noiseAtX, noiseAtZ, -TERRAIN_SIZE*TERRAIN_DISTANCE*0.5*0.1*0.9) * GAUSS_DIMENSION\n\t\t\t\t\t\t\t\t- 2.0 * gauss(noiseAtX, noiseAtZ, 0.0) * GAUSS_DIMENSION) \n\t\t\t\t\t\t\t\t+ 14.0;\n\t\tG_TerrainList[i].z = (zCoord - TERRAIN_SIZE/2) * TERRAIN_DISTANCE;\n\t\t\n\t\tG_TerrainList[i].s = (float)xCoord / (float)TERRAIN_SIZE;\n\t\tG_TerrainList[i].t = (float)zCoord / (float)TERRAIN_SIZE;\n\t\t\n\t\tG_TerrainList[i].nx = 0.0;\n\t\tG_TerrainList[i].ny = 1.0;\n\t\tG_TerrainList[i].nz = 0.0;\n\t\t\n\t\tmin = G_TerrainList[i].y < min ? G_TerrainList[i].y : min;\n\t\tmax = G_TerrainList[i].y > max ? G_TerrainList[i].y : max;\n\t\t\n\t\tG_TerrainCaustics[i].x = G_TerrainList[i].x;\n\t\tG_TerrainCaustics[i].y = G_TerrainList[i].y;\n\t\tG_TerrainCaustics[i].z = G_TerrainList[i].z;\n\t\tG_TerrainCaustics[i].nx = G_TerrainList[i].nx;\n\t\tG_TerrainCaustics[i].ny = G_TerrainList[i].ny;\n\t\tG_TerrainCaustics[i].nz = G_TerrainList[i].nz;\n\t\tG_TerrainCaustics[i].s = G_TerrainList[i].s;\n\t\tG_TerrainCaustics[i].t = G_TerrainList[i].t;\t\t\n\t\t\n\t}\n\t\n\tprintf (\"Terrain-Height min: %f, max: %f\\n\", min, max);\n\t\n\tinitTerrainIndices();\n\tcalcTerrainNormals();\n\t\n}\n"
  },
  {
    "path": "src/terrain.h",
    "content": "#ifndef __TERRAIN_H__\n#define __TERRAIN_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * Programmlogik und Datenhaltung\n *\n * @author Maurice Tollmien\n */\n\n/* ---- System Header einbinden ---- */\n#ifdef WIN32\n#include <windows.h>\n#endif\n\n#ifdef MACOSX\n#include <OpenGL/glu.h>\n#else\n#include <GL/glu.h>\n#endif\n\n#include <stdio.h>\n#include <stdarg.h>\n\n#include \"types.h\"\n\n/* Maximale Ausdehnung (Mittig!) */\n#define TERRAIN_SIZE\t200\n/* Wie groß das Noise abgebildet werden soll */\n#define TERRAIN_DIMENSION\t18.0\n#define GAUSS_DIMENSION\t\t10.0\n\n#define TERRAIN_DISTANCE\t1.0\n\n#define PERSISTENCE\t\t0.25\n#define OCTAVES_COUNT\t32\n\nTerrain * getTerrainList(void);\nvoid initTerrain(void);\nTerrain * getTerrainCaustics(void);\nGLuint * getTerrainIndices (void);\n\n#endif\n\n"
  },
  {
    "path": "src/textureDepthFragmentShader.frag",
    "content": "#version 330 \n\nin vec2 texcoords; \nuniform sampler2D texsampler; \nout vec4 Color; \n\nfloat linearizeDepth (float depth) {\n\tfloat nearPlane = 0.1, farPlane = 1000.0;\n\treturn (2*nearPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane));\n}\n\nfloat linearizeDepthExtreme (float depth) {\n\tfloat nearPlane = 0.1, farPlane = 1000.0;\n\tfloat res = (2*nearPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane));\n\tres = (res+0.3)*(res+0.3) - 0.5;\n\treturn res;\n}\n\nvoid main(){\n\tColor = vec4(linearizeDepthExtreme(texture(texsampler, texcoords).x)); \n}\n"
  },
  {
    "path": "src/textureFragmentShader.frag",
    "content": "#version 330 \n\nin vec2 texcoords; \nin vec3 normal;\nin float height;\nin vec3 causticNormal;\nuniform sampler2D texSand; \nuniform sampler2D texGrass; \nuniform sampler2D texRocks; \nuniform sampler2D texSnow; \nuniform sampler2D texForest; \nuniform sampler2D texTundra; \nout vec4 Color; \n\nfloat getLightValue(vec3 normalAt, vec3 sun, vec3 sun2, float lightUp) {\n\tfloat light  = max(0,dot(normalAt, sun));\n\tfloat light1 = max(0,dot(normalAt, sun2));\n\treturn mix(min(1,light + lightUp), min(1,light1 + lightUp), 0.5);\n}\n\nvec4 calcTexChange (float height, float min, float max, vec4 tex1, vec4 tex2) {\n\tfloat aspect = (height-min) / (max-min);\n\treturn mix(tex1, tex2, aspect);\n}\n\nvoid main(){ \t\n\tfloat \tsandGrassFrom \t= -3.0, sandGrassTo \t\t= 3.0,\n\t\t\tgrassForestFrom = 4.0,  grassForestTo \t= 7.0,\n\t\t\tforestTundraFrom = 16.0, forestTundraTo = 25.0,\n\t\t\ttundraRocksFrom = 25.0, tundraRocksTo\t= 30.0,\n\t\t\trocksSnowFrom \t= 40.0, rocksSnowTo\t\t= 60.0;\n\t\n\tvec3 sun  = vec3(1,1,1);\n\tvec3 sun2 = vec3(-1,1,1);\n\tvec4 sand  = texture(texSand , texcoords); \n\tvec4 grass = texture(texGrass, texcoords*3.0); \n\tvec4 forest = texture(texForest, texcoords*3.0);\n\tvec4 rocks = texture(texRocks, texcoords);\n\tvec4 tundra = texture(texTundra, texcoords*5.0);\n\tvec4 snow = texture(texSnow, texcoords*5.0);\n\tvec4 color;\n\t\n\tif (height < sandGrassFrom) {\n\t\tcolor = sand;\n\t} else if (height < sandGrassTo) {\n\t\tcolor = calcTexChange(height, sandGrassFrom, sandGrassTo, sand, grass);\n\t} else if (height < grassForestFrom) {\n\t\tcolor = grass;\n\t} else if (height < grassForestTo) {\n\t\tcolor = calcTexChange(height, grassForestFrom, grassForestTo, grass, forest);\n\t} else if (height < forestTundraFrom) {\n\t\tcolor = forest;\n\t} else if (height < forestTundraTo) {\n\t\tcolor = calcTexChange(height, forestTundraFrom, forestTundraTo, forest, tundra);\n\t} else if (height < tundraRocksFrom) {\n\t\tcolor = tundra;\n\t} else if (height < tundraRocksTo) {\n\t\tcolor = calcTexChange(height, tundraRocksFrom, tundraRocksTo, tundra, rocks);\n\t} else if (height < rocksSnowFrom) {\n\t\tcolor = rocks;\n\t} else if (height < rocksSnowTo) {\n\t\tcolor = calcTexChange(height, rocksSnowFrom, rocksSnowTo, rocks, snow);\n\t} else {\n\t\tcolor = snow;\n\t}\n\t\t\n\tcolor = color * getLightValue(normal, sun, sun2, 0.3);\n\t\n\t// Caustics\n\t//color = color * getLightValue(causticNormal, sun, sun2, 0.5);\n\t//float amount = dot(causticNormal, sun);\n\t//vec4 white = vec4(1,1,1,1);\n\t//vec4 caustics = mix(color, white, amount);\n\t\n\tColor = color;\n}\n"
  },
  {
    "path": "src/textureVertexShader.vert",
    "content": "#version 330 \n\t\t\nlayout (location = 0) in vec3 vertPos; \nlayout (location = 1) in vec2 tex; \nlayout (location = 2) in vec3 normalIn; \nlayout (location = 3) in vec3 causticNormal;\nuniform mat4 viewMatrix, projMatrix; \nout vec2 texcoords; \nout vec3 normal;\nout float height;\nout vec3 caustic;\n\nvoid main(){ \n\tgl_Position =  projMatrix * viewMatrix * vec4(vertPos, 1.0); \n\ttexcoords = tex; \n\tnormal = normalize(normalIn);\n\theight = vertPos.y;\n\tcaustic = normalize(causticNormal);\n}\n"
  },
  {
    "path": "src/types.h",
    "content": "#ifndef __TYPES_H__\n#define __TYPES_H__\n\n/**\n * @file\n * Typenschnittstelle.\n * Das Modul kapselt die Typdefinitionen und globalen Konstanten des Programms.\n *\n * @author Maurice Tollmien\n */\n\n/* ---- System Header einbinden ---- */\n#ifdef WIN32\n#include <windows.h>\n#endif\n\n#ifdef MACOSX\n#include <OpenGL/gl.h>\n#else\n#include <GL/gl.h>\n#endif\n\n/* ---- Eigene Konstanten */\n\n#define REFRACTION\t\t30\n\n#define GROUND_HEIGHT\t0.3\n\n#define CAMERA_X        -50.1\n#define CAMERA_Y        50.0\n#define CAMERA_Z        75.0\n#define CAMERA_SPEED    15.0\n\n#define CAMERA_MOVEMENT_SPEED\t4.0\n#define CAMERA_ZOOM_SPEED 10.0\n\n#define COUNTOWNTEX 2\n#define WORLD_SIZE 150\n\n#define SLICE_CNT\t50\n\n#define E\t\t\t2.71828183\n#define PI             3.14159265  \n#define EPS\t\t0.0001\n\n/** Anzahl der Aufrufe der Timer-Funktion pro Sekunde */\n#define TIMER_CALLS_PS      120\n\n/** Reihen des Images */\n#define IMAGE_ROWS  128\n#define IMAGE_COLS  128\n\n#define SPHERE_MOVE_SPEED\t-35\n#define SPHERE_R\t80.0\n#define SPHERE_TRANSPARENCY\t\t0.8\n#define SPHERE_CNT\t0\n\n#define QUAD_CNT\t0\n#define QUAD_SIDE\t60\n\n#define RED                     0.7, 0.0, 0.0\n#define BLUE                    0.0, 0.0, 0.7\n#define GREEN                   0.0, 0.7, 0.0\n#define BLACK                   0.0, 0.0, 0.0\n#define WHITE                   1.0, 1.0, 1.0\n#define GREY                    0.4, 0.4, 0.4 \n#define YELLOW                  0.7, 0.7, 0.0\n\n/* Text */\n/** Textausgabe, wenn das SPIEel zu ende ist, weil kein Stein mehr verfuegbar ist */\n#define HELP_OUTPUT_1       \"====== U'r blinded by pure AWESOMENESS!!!!! ======\"\n#define HELP_OUTPUT_2       \"|________________________________________________|\"\n#define HELP_OUTPUT_3       \"q/Q    beendet das Spiel.\"\n#define HELP_OUTPUT_4       \"r        beginnt ein neues Spiel im Ausgangszustand.\"\n#define HELP_OUTPUT_5       \"h/H     oeffnet/schliesst den Hilfemodus.\"\n#define HELP_OUTPUT_6       \"+/-     Aendert die Anzahl der Quadrate auf dem Boden\"\n#define HELP_OUTPUT_7       \"n/N     Kamera zum naechsten Partikel wechseln.\"\n#define HELP_OUTPUT_8       \"m/M   Kugeln in Bewegung setzten.\"\n#define HELP_OUTPUT_9       \"t/T    Textur wechseln.\"\n#define HELP_OUTPUT_10       \"p/P   Partikel einfrieren.\"\n#define HELP_OUTPUT_11       \"f/F    Ansicht der Partikel wechseln.\"\n#define HELP_OUTPUT_12       \"b      Kugeln bewegen sich nach Bezier.\"\n#define HELP_OUTPUT_13       \"B      Bezier-Kurven der Kugeln werden angezeigt.\"\n#define HELP_OUTPUT_14       \"s/S   Schatten zeichnen an/aus.\"\n#define HELP_OUTPUT_15      \"k/K    Kamera-Modus wechseln.\"\n#define HELP_OUTPUT_16       \"v/V   Verfolger-Modus an/aus.\"\n#define HELP_OUTPUT_17       \"x/X   Abstand fuer Bezier-Kontrollpunkte erhoehen.\"\n#define HELP_OUTPUT_18       \"y/Y   Abstand fuer Bezier-Kontrollpunkte verkleinern.\"\n#define HELP_OUTPUT_19       \"f1    Wireframe an/aus.\"\n#define HELP_OUTPUT_20       \"f2    Licht an/aus.\"\n#define HELP_OUTPUT_21       \"f3    Texturen an/aus.\"\n#define HELP_OUTPUT_22       \"Maus + rechte Maustaste    Abstand zum Mittelpunkt.\"\n#define HELP_OUTPUT_23       \"Maus + linke Maustaste    Bewegung im Raum.\"\n\n\n/* Tastatur */\n/** Keyboardtaste ESC definieren */\n#define ESC     27\n/** Keyboardtaste SPACE definieren */\n#define SPACE   32\n\n/** Datentyp fuer  den aktuellen SPIEelmodus */\nenum e_gameIntiType { OFF, ON };\ntypedef enum e_gameIntiType InitType;\n\n/** Mausereignisse. */\nenum e_MouseEventType\n{ mouseButton, mouseMotion, mousePassiveMotion };\n/** Datentyp fuer Mausereignisse. */\ntypedef enum e_MouseEventType CGMouseEventType;\n\n/** Mausereignisse. */\nenum e_MouseInterpretType\n{ NONE, MOVE, ZOOM};\n/** Datentyp fuer Mausereignisse. */\ntypedef enum e_MouseInterpretType MouseInterpretType;\n\n/** Datentyp fuer die Texturart */\nenum e_textureType\n{ NORMALTEXTURE, CHECKER, DIAGONAL };\n/** Datentyp die Texturart */\ntypedef enum e_textureType textureType;\n\n/** Datentyp fuer  den aktuellen SPIEelmodus */\nenum e_gameModi { normal, help };\ntypedef enum e_gameModi GameMode;\n\n/** Datentyp fuer die Verlaengerung/Verkuerzung des Kameravektors */\nenum e_cameraVector { closer, further };\ntypedef enum e_cameraVector CameraVector;\n\n/** Datentyp fuer die Richtungsaenderungen */\nenum e_gameDirection {left, right, up, down};\ntypedef enum e_gameDirection Directions;\n\n/** Punkt im 3D-Raum (homogene Koordinaten) */\ntypedef GLfloat CGPoint4f[4];\ntypedef GLfloat CGPoint3f[3];\ntypedef CGPoint3f CGColor;\n\n/** Datentyp fuer einen Vektor */\ntypedef double Vector4D[4];\ntypedef Vector4D Punkt4D;\n\n/** Vektor im 3D-Raum */\ntypedef GLfloat CGVector3D[3];\n\ntypedef double Vertex[6];\n\ntypedef int Movement[3];\n\ntypedef double VertexTexture[2];\n\nenum e_particleType {line, sphere};\ntypedef enum e_particleType ParticleType;\n\ntypedef struct {\n\tGLfloat x,y,z;\n\tGLfloat s,t;\n\tGLfloat nx, ny, nz;\n\tGLint fix;\n} Water;\n\ntypedef struct {\n\tGLfloat x,y,z;\n\tGLfloat s,t;\n\tGLfloat nx, ny, nz;\n} Terrain;\n\n/** Kugeln */\ntypedef struct X * Spheres;\nstruct X\n{\n\t/* Position im Raum */\n    CGPoint3f pos;\n    /* Richtungsvektor, Geschwindigkeit in eine Richtung */\n    CGVector3D newPos;   \n    /* Farbe */\n   CGVector3D color; \n    /* Bezier */\n    Vertex * interpolatedPoints;\n    /* Bezier */\n    Vertex * interpolatedPointsAll;\n\n    Vertex * controlPoints;\n    /* Bezier t */\n    double t;\n};\n\n/** Kugeln */\ntypedef struct Z * Quads;\nstruct Z\n{\n\t/* Position im Raum */\n    CGPoint3f pos;\n};\n\n\n/** Partikel */\ntypedef struct Y * Particle;\nstruct Y\n{\n\t/* Position im Raum */\n    CGPoint3f s;\n    /* Geschwindigkeitsvektor */\n    CGVector3D v;   \n    /* Beschleunigungsvektor */\n\tCGVector3D a;\n\t/* Kraft - intern */\n\tCGVector3D f;\n\t/* Masse */\n\tdouble m;\n\t/* Noch was? */\n\t/* Upvektor */ \n\tCGVector3D up;\n};\n\n#endif\n"
  },
  {
    "path": "src/vector.c",
    "content": "/**\n * @file\n * Hier ist die Datenhaltung und Programmlogik\n *\n * @author Tilman Nedele, Maurice Tollmien\n */\n\n/* ---- System Header einbinden ---- */\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <math.h>\n#include <stringOutput.h>\n#include <assert.h>\n\n#ifdef MACOSX\n#include <GLUT/glut.h>\n#else\n#include <GL/glut.h>\n#endif\n\n/* ---- Eigene Header einbinden ---- */\n#include \"types.h\"\n\n\n/**\n * Printet einen Vector aus.\n */\nvoid printVector (CGVector3D a)\n{\n\tint i;\n\tprintf(\"\\nprintVector:\\n\");\n\tfor (i=0;i<3;i++)\n\t\tprintf(\"%.1f\\n\", a[i]);\n\tprintf(\"\\n\");\n}\n\n/**\n * Konvertierungsfunktion,\n * wandelt drei Koordinaten in den dazugehörigen Vektor um\n * @param x\n * @param y\n * @param z\n */\nvoid toVector3D(CGVector3D vector, GLfloat x, GLfloat y, GLfloat z)\n{\n  vector[0] = x;\n  vector[1] = y;\n  vector[2] = z;\n}\n\n/**\n * Berechnet die Länge es Vektors\n * @param v\n *@return float\n */\nfloat vectorLength3D(CGVector3D vector)\n{\n  return sqrt((vector[0]*vector[0])+\n              (vector[1]*vector[1])+\n              (vector[2]*vector[2]));\n}\n\n/**\n * Normiert eine Vektor\n * @param v der zu normierende Vektor\n * @return der normierte Vektor\n */\nvoid normVector3D(CGVector3D vector)\n{\n  float l = vectorLength3D(vector);\n  if (l != .0f)\n    toVector3D(vector, vector[0]/l, vector[1]/l, vector[2]/l);\n}\n\n/**\n * Berechnet das Kreuzprodukt zweier Vektoren\n * @param\n * @param\n * @return\n */\nvoid crossProduct3D(CGVector3D product, CGVector3D a, CGVector3D b)\n{\n  toVector3D(product, (a[1]*b[2] - a[2]*b[1]),\n                      (a[2]*b[0] - a[0]*b[2]),\n                      (a[0]*b[1] - a[1]*b[0]));\n}\n\n/**\n * Multipliziert zwei Vektoren miteinander (Skalarprodukt)\n */\ndouble multiplyVectorVector (CGVector3D a, CGVector3D b)\n{\n\tint i;\n\tdouble res = 0.0;\n\tfor (i=0;i<3;i++)\n\t\tres += a[i]*b[i];\n\treturn res;\n}\n\n/**\n * Multipliziert einen Vektor mit einem Skalar.\n */\nvoid multiplyVectorScalar (CGVector3D a, double s, CGVector3D * res)\n{\n\tint i;\n\tfor (i=0;i<3;i++)\n\t\t(*res)[i] = a[i]*s;\n}\n\ndouble scalarProduct (CGVector3D a, CGVector3D b)\n{\n\treturn a[0]*b[0] + a[1]*b[1] + a[2]*b[2];\t\n}\n\n/**\n * Zieht b von a ab, also: a-b\n */\nvoid subtractVectorVector (CGVector3D a, CGVector3D b, CGVector3D * res)\n{\n\tint i;\n\tfor (i=0;i<3;i++)\n\t\t(*res)[i] = a[i] - b[i];\n}\n\n/**\n * Teilt den Vector a durch s.\n */\nvoid divideVectorScalar (CGVector3D a, double s, CGVector3D * res)\n{\n\tint i;\n\tfor (i=0;i<3;i++)\n\t\t(*res)[i] = a[i] / s;\n}\n\n/**\n * Addiert a und b und schreibt das Ergebnis in res.\n */\nvoid addVectorVector (CGVector3D a, CGVector3D b, CGVector3D * res)\n{\n\tint i;\n\tfor (i=0;i<3;i++)\n\t\t(*res)[i] = a[i] + b[i];\n}\n\n/**\n * Wandelt eine Zahl (Grad) in Radiant.\n * deg muss im Wertebereich 0..359 liegen!\n */\ndouble degToRad (double deg)\n{\n\treturn deg*PI/180.0;\n}\n\n/**\n * Wandelt eine Zahl (Radiant) in Grad um.\n * deg muss im Wertebereich 0..PI liegen!\n */\ndouble radToDeg (double rad)\n{\n\treturn rad*180.0/PI;\n}\n\n/**\n * Berechnet den Winkel zwischen zwei Vektoren und gibt das Ergebnis in \n * ° zurück (nicht radiant!).\n */\ndouble angleVectorVector (CGVector3D a, CGVector3D b)\n{\n\treturn radToDeg (acos (multiplyVectorVector (a, b) / (vectorLength3D(a)*vectorLength3D(b))));\n}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "src/vector.h",
    "content": "#ifndef __VECTOR_H__\n#define __VECTOR_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * Programmlogik und Datenhaltung\n *\n * @author Maurice Tollmien\n */\n\n/* ---- System Header einbinden ---- */\n#ifdef WIN32\n#include <windows.h>\n#endif\n\n#ifdef MACOSX\n#include <OpenGL/glu.h>\n#else\n#include <GL/glu.h>\n#endif\n\n#include <stdio.h>\n#include <stdarg.h>\n\n#include \"types.h\"\n\n/* eig. Funktionen */\n\n/**\n * Konvertierungsfunktion,\n * wandelt drei Koordinaten in den dazugehörigen Vektor um\n * @param x\n * @param y\n * @param z\n */\nvoid toVector3D(CGVector3D vector, GLfloat x, GLfloat y, GLfloat z);\n/**\n * Berechnet die Länge es Vektors\n * @param v\n *@return float\n */\nfloat vectorLength3D(CGVector3D vector);\n\n/**\n * Normiert eine Vektor\n * @param v der zu normierende Vektor\n * @return der normierte Vektor\n */\nvoid normVector3D(CGVector3D vector);\n\n/**\n * Berechnet das Kreuzprodukt zweier Vektoren\n * @param\n * @param\n * @return\n */\nvoid crossProduct3D(CGVector3D product, CGVector3D a, CGVector3D b);\n\ndouble multiplyVectorVector (CGVector3D a, CGVector3D b);\nvoid multiplyVectorScalar (CGVector3D a, double s, CGVector3D * res);\nvoid subtractVectorVector (CGVector3D a, CGVector3D b, CGVector3D * res);\nvoid divideVectorScalar (CGVector3D a, double s, CGVector3D * res);\nvoid addVectorVector (CGVector3D a, CGVector3D b, CGVector3D * res);\nvoid printVector (CGVector3D a);\ndouble angleVectorVector (CGVector3D a, CGVector3D b);\ndouble radToDeg (double rad);\ndouble degToRad (double deg);\ndouble scalarProduct (CGVector3D a, CGVector3D b);\n\n#endif\n"
  },
  {
    "path": "src/water.c",
    "content": "\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <math.h>\n/* ---- Eigene Header einbinden ---- */\n#include \"water.h\"\n#include \"particle.h\"\n#include \"logic.h\"\n#include \"vector.h\"\n#include \"types.h\"\n#include \"terrain.h\"\n\nWater * G_WaterList;\nWater * G_TmpWaterList;\nfloat ** G_V;\n\nGLuint * G_WaterIndices;\n\nint normalList = 1;\nint G_IsMoving = 1;\nint G_randomize = 0;\n\nWater * getWaterList(void){\n\treturn G_WaterList;\n}\n\nvoid calcWaterAttributes (double interval) {\n\t\n\tint i,j;\n\tdouble f;\n\t\n\tif (G_IsMoving) {\n\t\t\n\t\tfor (i=0;i<WORLD_SIZE*WORLD_SIZE;i++) {\t\t\n\t\t\tint atI = i % WORLD_SIZE;\n\t\t\tint atJ = i / WORLD_SIZE;\n\t\t\t\n\t\t\tif (0 && G_WaterList[i].fix && fabs(G_WaterList[i].y - WATER_HEIGHT_INIT) > 0.1) {\n\t\t\t\tprintf (\"Wasser: fix=%d, Y now=%f, Y init=%f\\n\", G_WaterList[i].fix, G_WaterList[i].y, (double)WATER_HEIGHT_INIT);\n\t\t\t}\n\t\t\t\n\t\t\tif (atI == 0 || atI == WORLD_SIZE-1 || atJ == 0 || atJ == WORLD_SIZE-1\n\t\t\t\t) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t\n\t\t\tf = WATER_SPEED * WATER_SPEED * (\tG_WaterList[i - WORLD_SIZE].y + \n\t\t\t\t\t\t\t\t\t\t\t\tG_WaterList[i + WORLD_SIZE].y + \n\t\t\t\t\t\t\t\t\t\t\t\tG_WaterList[i + 1].y + \n\t\t\t\t\t\t\t\t\t\t\t\tG_WaterList[i - 1].y - 4 *\n\t\t\t\t\t\t\t\t\t\t\t\tG_WaterList[i].y\n\t\t\t\t\t\t\t\t\t\t\t) / WATER_WIDTH;\n\t\t\t\n\t\t\tG_V[atI][atJ] += f * interval;\n\t\t\t\n\t\t\tif (!G_WaterList[i].fix)\n\t\t\t\tG_TmpWaterList[i].y = G_WaterList[i].y + G_V[atI][atJ] * interval;\n\t\t\telse\n\t\t\t\tG_TmpWaterList[i].y = WATER_HEIGHT_INIT;\n\t\t\t\t\n\t\t\tif (G_randomize) {\n\t\t\t\tG_TmpWaterList[i].y = WATER_HEIGHT_INIT + WATER_DISTORTION - WATER_DISTORTION;\n\t\t\t\tG_WaterList[i].y = WATER_HEIGHT_INIT + WATER_DISTORTION - WATER_DISTORTION;\n\t\t\t}\n\t\t\t\n\t\t\t\n\t\t\tCGVector3D v1 = {G_WaterList[i-WORLD_SIZE].x - G_WaterList[i].x, G_WaterList[i-WORLD_SIZE].y - G_WaterList[i].y, G_WaterList[i-WORLD_SIZE].z - G_WaterList[i].z};\n\t\t\tCGVector3D v2 = {G_WaterList[i-1].x - G_WaterList[i].x, G_WaterList[i-1].y - G_WaterList[i].y, G_WaterList[i-1].z - G_WaterList[i].z};\n\t\t\tCGVector3D res1;\n\t\t\tcrossProduct3D(res1, v1, v2);\n\t\t\t\n\t\t\tCGVector3D v3 = {G_WaterList[i+WORLD_SIZE].x - G_WaterList[i].x, G_WaterList[i+WORLD_SIZE].y - G_WaterList[i].y, G_WaterList[i+WORLD_SIZE].z - G_WaterList[i].z};\n\t\t\tCGVector3D v4 = {G_WaterList[i+1].x - G_WaterList[i].x, G_WaterList[i+1].y - G_WaterList[i].y, G_WaterList[i+1].z - G_WaterList[i].z};\n\t\t\tCGVector3D res2;\n\t\t\tcrossProduct3D(res2, v3, v4);\n\t\t\t\n\t\t\tif (res1[1] < 0) {\n\t\t\t\tmultiplyVectorScalar(res1, -1, &res1);\n\t\t\t}\n\t\t\tif (res2[1] < 0) {\n\t\t\t\tmultiplyVectorScalar(res2, -1, &res2);\n\t\t\t}\n\t\t\tCGVector3D normal;\n\t\t\taddVectorVector(res1, res2, &normal);\n\t\t\t\n\t\t\tG_TmpWaterList[i].nx = normal[0];\n\t\t\tG_TmpWaterList[i].ny = normal[1];\n\t\t\tG_TmpWaterList[i].nz = normal[2];\n\t\t\t\n\t\t\t/* Caustics durch die Normalen des Wasser auf der Bodenfläche. */\n\t\t\tint waterTerrainOffset = (TERRAIN_SIZE - WORLD_SIZE)/2;\n\t\t\tTerrain * terrainCaustics = getTerrainCaustics();\n\t\t\t/*terrainCaustics[(atI + waterTerrainOffset) * TERRAIN_SIZE + (atJ + waterTerrainOffset)].nx = normal[0]; \n\t\t\tterrainCaustics[(atI + waterTerrainOffset) * TERRAIN_SIZE + (atJ + waterTerrainOffset)].ny = normal[1]; \n\t\t\tterrainCaustics[(atI + waterTerrainOffset) * TERRAIN_SIZE + (atJ + waterTerrainOffset)].nz = normal[2]; */\n\t\t\t\n\t\t}\n\t\t\n\t\tWater * tmp;\n\t\ttmp = G_TmpWaterList;\n\t\tG_TmpWaterList = G_WaterList;\n\t\tG_WaterList = tmp;\n\t}\n\t\n\tG_randomize = 0;\n\t\n}\n\n/**\n * Guckt, wo/ob Wasserpunkte einen Mindestabstand zu Landpunkten unterschreiten\n * und setzt diese auf fix, sodass quasi ein Wasserrand entsteht.\n */\nvoid calcFixWaterPoints(Terrain * terrain) \n{\n\tint w,t;\n\tdouble eps = 1.0;\n\t\n\tfor (t = 0; t < TERRAIN_SIZE*TERRAIN_SIZE; t++) {\n\t\tfor (w = 0; w < WORLD_SIZE*WORLD_SIZE; w++) {\n\t\t\t\n\t\t\tif (fabs(terrain[t].x - G_WaterList[w].x) < eps && \n\t\t\t\tfabs(terrain[t].y - G_WaterList[w].y) < eps && \n\t\t\t\tfabs(terrain[t].z - G_WaterList[w].z) < eps\n\t\t\t\t) {\n\t\t\t\tG_WaterList[w].fix\t= 1;\n\t\t\t\tG_WaterList[w].y \t= WATER_HEIGHT_INIT;\n\t\t\t}\n\t\t}\n\t}\n}\n\nvoid setRandomize(void) {\n\tG_randomize = 1;\n}\n\nvoid pushSomeWaterDown(void)\n{\n\t\n\tint i,j;\n\t\n\tfor (i=WORLD_SIZE/2-4;i<WORLD_SIZE/2+5;i++) {\n\t\tfor (j=WORLD_SIZE/2-4;j<WORLD_SIZE/2+5;j++) {\n\t\t\tif (!G_WaterList[i*WORLD_SIZE+j].fix)\n\t\t\t\tG_WaterList[i*WORLD_SIZE+j].y -= 5.0;\t\t\t\n\t\t}\n\t}\n\t\n}\n\nvoid toggleWaterMovement(void) \n{\n\tG_IsMoving = !G_IsMoving;\n}\n\nGLuint * getWaterIndices (void) \n{\n\treturn G_WaterIndices;\n}\n\nvoid initWaterIndices(void) {\n\t\n\tint i,j;\n\tint index = 0;\n\tfor (i=0;i<WORLD_SIZE*WORLD_SIZE;i++) {\t\t\n\t\tint atI = i % WORLD_SIZE;\n\t\tint atJ = i / WORLD_SIZE;\n\t\t\n\t\tif (atI == WORLD_SIZE-1 || atJ == WORLD_SIZE-1) {\n\t\t\tcontinue;\n\t\t}\n\t\t\n\t\tG_WaterIndices[index]   = i;\n\t\tG_WaterIndices[index+1] = i+1;\n\t\tG_WaterIndices[index+2] = i+WORLD_SIZE+1;\n\t\t\n\t\tG_WaterIndices[index+3] = i;\n\t\tG_WaterIndices[index+4] = i+WORLD_SIZE+1;\n\t\tG_WaterIndices[index+5] = i+WORLD_SIZE;\n\t\t\n\t\tindex += 6;\t\t\t\n\t}\n\t\n}\n\nvoid initWater(void) {\n\t\n\tint i,j;\n\t\n\tG_V = calloc(WORLD_SIZE, sizeof(*G_V));\n\tG_WaterList = calloc(WORLD_SIZE*WORLD_SIZE, sizeof(*G_WaterList));\n\tG_TmpWaterList = calloc(WORLD_SIZE*WORLD_SIZE, sizeof(*G_TmpWaterList));\n\tG_WaterIndices = calloc(WORLD_SIZE*WORLD_SIZE*2*3, sizeof(*G_WaterIndices));\n\t\n\tfor (i=0;i<WORLD_SIZE;i++) {\n\t\tG_V[i] = calloc(WORLD_SIZE, sizeof(**G_V));\n\t}\n\t\n\tfor (i=0;i<WORLD_SIZE*WORLD_SIZE;i++) {\n\t\tint xCoord = i / WORLD_SIZE;\n\t\tint zCoord = i % WORLD_SIZE;\n\t\t\n\t\tG_WaterList[i].x = xCoord - WORLD_SIZE/2;\n\t\tG_WaterList[i].y = WATER_HEIGHT_INIT /*+ WATER_DISTORTION - WATER_DISTORTION*/;\n\t\tG_WaterList[i].z = zCoord - WORLD_SIZE/2;\n\t\t\n\t\tG_WaterList[i].s = (float)xCoord / (float)WORLD_SIZE;\n\t\tG_WaterList[i].t = (float)zCoord / (float)WORLD_SIZE;\n\t\t\n\t\tG_WaterList[i].nx = 0.0;\n\t\tG_WaterList[i].ny = 1.0;\n\t\tG_WaterList[i].nz = 0.0;\n\t\t\n\t\tG_WaterList[i].fix = 0;\n\t\t\n\t\tG_TmpWaterList[i].x = G_WaterList[i].x;\n\t\tG_TmpWaterList[i].y = G_WaterList[i].y;\n\t\tG_TmpWaterList[i].z = G_WaterList[i].z;\n\t\t\n\t\tG_TmpWaterList[i].s = G_WaterList[i].s;\n\t\tG_TmpWaterList[i].t = G_WaterList[i].t;\t\t\n\t\t\n\t\tG_TmpWaterList[i].nx = G_WaterList[i].nx;\t\t\n\t\tG_TmpWaterList[i].ny = G_WaterList[i].ny;\t\t\n\t\tG_TmpWaterList[i].nz = G_WaterList[i].nz;\t\n\t\t\n\t\tG_TmpWaterList[i].fix = 0;\t\n\t\t\n\t\tG_V[xCoord][zCoord] = 0.0;\n\t\t\n\t\t\n\t}\n\t\n\tinitWaterIndices();\t\n}\n"
  },
  {
    "path": "src/water.h",
    "content": "#ifndef __WATER_H__\n#define __WATER_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * Programmlogik und Datenhaltung\n *\n * @author Maurice Tollmien\n */\n\n/* ---- System Header einbinden ---- */\n#ifdef WIN32\n#include <windows.h>\n#endif\n\n#ifdef MACOSX\n#include <OpenGL/glu.h>\n#else\n#include <GL/glu.h>\n#endif\n\n#include <stdio.h>\n#include <stdarg.h>\n\n#include \"types.h\"\n#include \"terrain.h\"\n\n#define WATER_HEIGHT_INIT\t0\n#define WATER_SPEED \t\t3\n#define WATER_WIDTH\t\t\t1\n#define WATER_DISTORTION\t(rand()%1000) / 4000.0\n\nWater * getWaterList(void);\nvoid initWater(void);\nvoid calcWaterAttributes (double interval);\nvoid pushSomeWaterDown(void);\nvoid toggleWaterMovement(void);\nGLuint * getWaterIndices (void);\nvoid calcFixWaterPoints(Terrain * terrain);\nvoid setRandomize(void);\n\n#endif\n\n"
  },
  {
    "path": "src/waterFragmentShader.frag",
    "content": "#version 330 \n\t\t\n\nin vec3 pos_vec; \nin vec3 normal; \nin vec3 pos_cam;\nin vec3 backgroundColor;\nin float height;\nuniform sampler2D texsampler; \nuniform sampler2D texsamplerDepth; \nuniform samplerCube texsamplerCube; \nuniform mat4 viewMatrix, projMatrix; \nout vec4 Color; \n\nfloat linearizeDepth2 (float depth) {\n\tfloat nearPlane = 0.1, farPlane = 1000.0;\n\treturn (2*nearPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane));\n}\n\nfloat linearizeDepth (float depth) {\n\tfloat nearPlane = 0.1, farPlane = 1000.0;\n\tfloat res = (2*nearPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane));\n\tres = (res+0.3)*(res+0.3) - 0.5;\n\treturn res;\n}\n\n// Umwandlung einer Weltkoordinate in Screenkoordinate!\nvec3 getScreenPos (vec3 worldPos) {\n\tvec4 screenPos \t= projMatrix * viewMatrix * vec4(worldPos, 1.0);\n\tvec3 screenPos3\t= screenPos.xyz / screenPos.w;\n\treturn (screenPos3 + vec3(1.0)) / 2.0;\n}\n\nvec3 cubeMapRefl (vec3 reflectionWorld) {\n\treturn texture(texsamplerCube, reflectionWorld).rgb;\n}\n\nvec3 cubeMapRefr (vec3 refractionWorld) {\n\treturn texture(texsamplerCube, refractionWorld).rgb;\n}\n\n// Tiefe des Wassers an dem Fragment:\nvec3 calcWaterDependentDarkness(vec3 color, float maxDepth) {\n\t// zwischen 0 und 1.\n\tvec3 screenPos\t\t= getScreenPos(pos_vec);\n\tvec2 screenTexPos \t= screenPos.xy;\n\t\n\tfloat texDepth = texture(texsamplerDepth, screenTexPos).x;\n\tfloat worldDepth = screenPos.z;\n\t\n\tfloat depth = worldDepth - texDepth;\n\tvec3 black = vec3(0.0);\n\t\n\t/*if (depth <= 1.0 && depth >= 0.0) {\n\t\treturn vec3(1,0,0);\n\t} else\n\t\treturn vec3(1.0);*/\n\treturn vec3(texDepth);\n\t\n\treturn mix(black, color, 1.0-depth);\n}\n\nvec3 raytrace(in vec3 reflectionWorld, in int maxCount, in float stepSize) {\n\tvec3 color = vec3(1.0); \t\n\tvec3 testVec = pos_vec;\n\t\n\tvec3 reflectionVector = reflectionWorld * stepSize;\n\t\n\tvec3 screenPos\t\t= getScreenPos(testVec);\n\tvec2 screenTexPos \t= screenPos.xy;\n\t\n\t\n\tfloat texDepth = texture(texsamplerDepth, screenTexPos).x;\n\tfloat worldDepth = screenPos.z;\n\t\n\tbool run = true;\n\tint count = 0;\n\n\twhile (run) {\n\t\t\n\t\ttexDepth = texture(texsamplerDepth, screenTexPos).x;\n\t\tworldDepth = screenPos.z;\n\t\t\n\t\tif (texDepth <= worldDepth) {\n\t\t\tcolor = texture(texsampler, screenTexPos).rgb;\n\t\t\tbreak;\n\t\t}\n\t\t\n\t\ttestVec \t\t= testVec + reflectionVector;\n\t\tscreenPos\t\t= getScreenPos(testVec);\n\t\tscreenTexPos \t= screenPos.xy;\n\t\t\n\t\tcount = count+1;\n\t\trun = \tscreenTexPos.x < 1.0 && screenTexPos.x >= 0.0 &&\n\t\t\t\tscreenTexPos.y < 1.0 && screenTexPos.y >= 0.0 && count < maxCount;\n\t}\n\t\n\tif (!run) {\n\t\tcolor = cubeMapRefl(testVec);\n\t\t// Cheating\n\t\t//color = vec3(0,1,1);\n\t}\n\t\n\treturn color;\n} \n\nfloat getFresnelFactor (void) {\n\tfloat fresnelPower = 3; \n\tfloat fresnelScale = 5.0; \n\tfloat fresnelBias  = 0.05373; \n\treturn fresnelBias + fresnelScale * pow(1 + dot(normalize(pos_vec - pos_cam), normal), fresnelPower);\n}\n\nfloat calcStepSize(float stepSize, float max, vec3 n, vec3 cam) {\n\tfloat scalarProduct = dot(n, cam);\n\tfloat res = 0.0;\n\t\n\tres = (1.0 - scalarProduct) * (max-stepSize);\n\t\n\treturn res + stepSize;\n}\n\nvoid main(){ \n\tconst int maxCount = 250;\n\tconst float ratio = 1.0 / 1.3333; \n\tfloat stepSize = 20.0;\n\tfloat maxStepSize = 400.0;\n\tfloat maxDepth = 0.9;\n\tvec4 black = vec4(0,0,0,0);\n\t\n\tvec3 eyePosition = normalize(pos_vec - pos_cam);\n\t\n\tvec3 reflectionWorld = normalize (reflect(eyePosition, normal));\n\tvec3 refractionWorld = normalize (refract(eyePosition, normal, ratio));\n\t\n\t// Nicht physikalisch korrekte Anpassung, dass mehr Geometrie gespiegelt wird!\n\treflectionWorld = reflectionWorld + vec3(0, -0.15, 0);\n\t\n\t// Stepsize anpassen an das Verhältnis der Normalen zum Blickvektor\n\tstepSize = calcStepSize(stepSize, maxStepSize, -normal, eyePosition);\n\t\n\tvec3 reflectedColor = raytrace(reflectionWorld, maxCount, stepSize); \n\tvec3 refractedColor = raytrace(refractionWorld, maxCount, stepSize);\n\t\n\t//refractedColor = calcWaterDependentDarkness(refractedColor, maxDepth);\n\t\n\tvec4 screenSpaceReflection = vec4(reflectedColor, 1.0);\n\tvec4 screenSpaceRefraction = vec4(refractedColor, 1.0);\n\t\n\tscreenSpaceRefraction = mix(black, screenSpaceRefraction, 0.5);\n\t\n\tvec4 tmpColor = mix (screenSpaceRefraction, screenSpaceReflection, getFresnelFactor());\n\ttmpColor = mix (black, tmpColor, 0.8);\n\t\n\t// Wenn das Wasser tief wird.\n\tif (height < 0.0) {\n\t\tfloat aspect = (height+8.0) / 8.0;\n\t\ttmpColor = mix(black, tmpColor, aspect);\n\t\ttmpColor = vec4(0.0);\n\t}\n\t\n\tColor = tmpColor;\n\t//Color = screenSpaceReflection;\n\t//Color = screenSpaceRefraction;\n}\n"
  },
  {
    "path": "src/waterVertexShader.vert",
    "content": "#version 330 \n\t\t\nlayout (location = 0) in vec3 vertPos; \nlayout (location = 1) in vec3 normal_in; \nlayout (location = 2) in vec3 terrain;\nuniform mat4 viewMatrix, projMatrix; \nuniform vec3 cameraPos; \nout vec3 pos_vec; \nout vec3 normal; \nout vec3 pos_cam; \nout float height;\n\nvoid main(){ \n\tvec3 newPos = vec3(vertPos - pos_cam); \n\tgl_Position =  projMatrix * viewMatrix * vec4(vertPos, 1.0); \n\tpos_vec = vertPos; \n\tnormal   = normalize(normal_in); \n\tpos_cam = cameraPos; \n\theight = terrain.y;\n}\n"
  }
]