Full Code of MauriceGit/Water_Simulation for AI

master 713c72e4d31a cached
33 files
136.7 KB
45.3k tokens
168 symbols
1 requests
Download .txt
Repository: MauriceGit/Water_Simulation
Branch: master
Commit: 713c72e4d31a
Files: 33
Total size: 136.7 KB

Directory structure:
gitextract_532xa9lh/

├── LICENSE
├── README.md
└── src/
    ├── Makefile
    ├── Makefile.common
    ├── Makefile.depend
    ├── colorFragmentShader.frag
    ├── colorVertexShader.vert
    ├── imageLoader.c
    ├── imageLoader.h
    ├── io.c
    ├── io.h
    ├── logic.c
    ├── logic.h
    ├── main.c
    ├── particle.c
    ├── particle.h
    ├── scene.c
    ├── scene.h
    ├── stringOutput.c
    ├── stringOutput.h
    ├── terrain.c
    ├── terrain.h
    ├── textureDepthFragmentShader.frag
    ├── textureFragmentShader.frag
    ├── textureVertexShader.vert
    ├── types.h
    ├── vector.c
    ├── vector.h
    ├── water
    ├── water.c
    ├── water.h
    ├── waterFragmentShader.frag
    └── waterVertexShader.vert

================================================
FILE CONTENTS
================================================

================================================
FILE: LICENSE
================================================
Copyright (c) 2015, 2016 Maurice Tollmien <maurice.tollmien@gmail.com>

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.


================================================
FILE: README.md
================================================
# Water-Simulation with Realtime Reflections/Refractions from the Surface
This project consists of several smaller projects joined together. Everything is done completely from
scratch. No external libraries or dependencies (except basic OpenGL) are needed to run this simulation.

The final result looks like that:

![Water-Simulation](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished3.png "Water-Simulation with reflections/refractions")

## **Water Simulation**

The water simulation itself is a pressure based height field.

The water's surface is divided into a small grid of points. Each height represents
the pressure at that point. For each time step the pressure is divided and continued on to
the next water point. The calculation itself is similar to image processing calculations,
where a kernel over each pixel calculates the color at that pixel.

A height field water simulation looks very real for smaller waves and distorted water surfaces.
But because of using a height-field (real time efficiency and simplicity to implement) there is no
possibility of calculating single drops or any kind of detachment of waterbodies from the surface.
Also no overlapping waves or such things are possible.

Example with random displacement added to the water's surface, creating very small waves (distortion):

![Water-Distortion](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished6.png "Small distortions")

Example with some small spreading waves:

![Spreading waves](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished7.png "Spreading waves")

Example with waves bouncing back from the shore:

![Bouncing waves](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished1.png "Waves bouncing from the shore")


## **Reflections / Refractions (Screenspace)**

Both the reflection and refraction of the water's surface is calculated in screen space with OpenGL fragment shaders.

The main benefit of using screenspace reflections/refractions is, that it takes a constant time to calculate and doesn't depend
on the complexity of the scene. Another benefit is, that both the reflection and refraction can be calculated using
the exact same calculations.

- For each frame, two textures (color-texture and depth-texture) are created from the point of view and provided to the
  OpenGL fragment shader.

- For each pixel, the position of each reflection/refraction-point is provided in world-coordinates to the fragment shader.

- A step-size is determined (could also be constant).

- For each step, the reflection-vector is scaled with the determinded step-size and transformed into screenspace.
  We now have two vectors. One is the reflection-vector in world coordinates and the same one transformed into screen space.

- Because we look at the same scene which is saved into the texture, we can now sample the depth-texture and get the depth
  of the scene at the point of the scaled reflection-vector.

- We continue the scaling of the reflection-vector until the depth of the sampled depth-texture is smaller than the
  z-coordinate (depth) of the reflection-vector in world coordinates. In this case we know, that we hit something which should
  be displayed as the reflection for the original fragment.

- We can then take the transformed reflection-vector and sample the color texture. The result should be the color of the
  reflection. We take that color and are finished.

Positive features: Works in real time looks good most of the time.

Negative features: Actually takes longer to calculate, if there are no reflections, is not always correct, not defined
for situations where the reflection goes outside the screenspace and can only reflect objects which are on the screen!
(Also there are incorrect reflections if there is an object between the camera and the water's surface.)

Water refraction:

![Refraction](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished2.png "Water-Refraction looking good!")

Reflection and refraction with no waves at all:

![No Wave-Reflection](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished5.png "Water-Reflection, no waves")

Refraction and Reflection of smaller waves from above:

![Small waves](https://github.com/MauriceGit/Water_Simulation/blob/master/Screenshots/finished4.png "Water-Refraction/Reflection with small waves")

## **Terrain Modelling**

The terrain is modelled using a 2D-Perlin-Noise-function (implemented from scratch!).
It overlays different frequences of sinus and cosinus waves.
The perlin-noise height field is then textured based on the current height (Overlapping of different textures).
The mountain like hill is added by adding a gauss function to the perlin-noise output.
The same goes for the valley where the water is.

## **Install && Run**

I 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
tested.

### **Requirements**

The following system-attributes are required for running this simulation:

- A graphics card supporting OpenGL version 3.3 (For the shaders).

- Unix-Libraries: xorg-dev, freeglut3-dev and mesa-common-dev

### **Running**

Compiling and running is pretty straight forward.

- make

- ./water

While the simulation runs, you can move around (always looking to the center!) with your mouse (left-klick and move).

Initializing a random movement (choppy water) is done with 'r'.

Creating one/several waves can be done by pressing 'n'.

















================================================
FILE: src/Makefile
================================================
# Quelldateien
SRCS             = imageLoader.c vector.c main.c scene.c io.c water.c terrain.c logic.c stringOutput.c 

# ausfuehrbares Ziel
TARGET           = water

# Ist libz verfgbar?
HAVE_LIBZ = yes


# Basis-Makefile einbinden
-include ./Makefile.common


# Precompiler flags
# Pfad der Schnittstelle des ImageLoaders hinzufuegen
CPPFLAGS_COMMON  += -I$(IMGLOADER_DIR)/include

# Linker flags
# Pfad der ImageLoader-Bibliothek hinzufuegen
LDFLAGS_COMMON  += -L$(IMGLOADER_DIR)/lib


# Wenn libz verfuegbar ist, muessen wir sie mit einlinken, um die
# Bibliothek auch zum Laden von PNG-Bildern verwenden zu koennen.
ifeq ($(HAVE_LIBZ),yes)
LDLIBS += -lz
endif


.PHONY: distcleanimageloader


# TARGETS

# Regel zur Erstellung der ImageLoader-Bibliothek
$(IMGLOADER_DIR)/lib/$(IMGLOADER_LIB):
	(cd $(IMGLOADER_DIR) && ./configure)
	$(MAKE) -C $(IMGLOADER_DIR)

# Vollstaendiges Aufraeumen beinhaltet auch Aufraeumen des ImageLoaders
distclean: distcleanimageloader

# Regel zum Aufraeumen des ImageLoaders
distcleanimageloader:
	if [ -f $(IMGLOADER_DIR)/Makefile ]; then $(MAKE) -C $(IMGLOADER_DIR) HAVE_LIBZ=$(HAVE_LIBZ) distclean; fi


================================================
FILE: src/Makefile.common
================================================
# Objektdateien
OBJS             = $(SRCS:.c=.o)

# Compiler
CC               = gcc

# Precompiler flags
CPPFLAGS_LINUX   =
CPPFLAGS_LINUX64 =
CPPFLAGS_MACOSX  = -DMACOSX
CPPFLAGS_COMMON  = -I./
CPPFLAGS         = $(CPPFLAGS_COMMON) $(CPPFLAGS_$(OS))

# Compiler flags
CFLAGS_LINUX   =
CFLAGS_LINUX64 =
CFLAGS_MACOSX  =
CFLAGS_COMMON  = -Wextra -ansi
CFLAGS         = $(CFLAGS_COMMON) $(CFLAGS_$(OS))

# Linker
LD               = gcc

# Linker flags
LDFLAGS_LINUX    = -L/usr/X11R6/lib -L/usr/lib
LDFLAGS_LINUX64  = -L/usr/X11R6/lib64
LDFLAGS_MACOSOX  =
LDFLAGS_COMMON   =
LDFLAGS          = $(LDFLAGS_COMMON) $(LDFLAGS_$(OS))

# Linker libraries
XLIBS            = -lXmu -lXi -lX11
GLLIBS           = -lglut -lGLU -lGL

LDLIBS_LINUX     = $(GLLIBS) #$(XLIBS)
LDLIBS_LINUX64   = $(GLLIBS) #$(XLIBS)
LDLIBS_MACOSX    = -framework OpenGL -framework GLUT -framework Foundation
LDLIBS_COMMON    = -lm
LDLIBS           = $(LDLIBS_COMMON) $(LDLIBS_$(OS))

# welches Betriebssystem?
ifeq ($(findstring Linux,$(shell uname -s)),Linux)
  OS = LINUX
  ifeq ($(shell uname -m),x86_64)
    OS = LINUX64
  endif
else
  ifeq ($(shell uname -s),Darwin)
    OS = MACOSX
  endif
endif

# Debugging-Informationen aktivieren
DEBUG = yes

# Wenn Debugging-Informationen aktiviert werden sollen, entsprechende
# Praeprozessorflags setzen
ifeq ($(DEBUG),yes)
CPPFLAGS_COMMON+=-g -DDEBUG
endif


.SUFFIXES: .o .c
.PHONY: all clean distclean depend


# TARGETS
all: depend $(TARGET)

doc:
	doxygen ../common/Doxyfile

# Linken des ausfuehrbaren Programms
$(TARGET): $(OBJS)
	$(LD) $(LDFLAGS) $(OBJS) $(LDLIBS) -o $(TARGET)

# Kompilieren der Objektdateien
%.o: %.c
	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $*.o $*.c

# einfaches Aufraeumen
clean:
	rm -f $(TARGET)
	rm -f $(OBJS)

# alles loeschen, was erstellt wurde
distclean: clean
	rm -f *~
	rm -f Makefile.depend
	rm -rf doc
	rm -rf doxygen.log

# Abhaengigkeiten automatisch ermitteln
depend:
	@rm -f Makefile.depend
	@echo -n "building Makefile.depend ... "
	@$(foreach SRC, $(SRCS), ( $(CC) $(CPPFLAGS) $(SRC) -MM -g0 ) 1>> Makefile.depend;)
	@echo "done"

# zusaetzliche Abhaengigkeiten einbinden
-include Makefile.depend



================================================
FILE: src/Makefile.depend
================================================
imageLoader.o: imageLoader.c imageLoader.h
vector.o: vector.c stringOutput.h types.h
main.o: main.c io.h scene.h types.h
scene.o: scene.c stringOutput.h scene.h types.h logic.h water.h terrain.h \
 vector.h
io.o: io.c io.h scene.h types.h logic.h water.h terrain.h vector.h \
 imageLoader.h
water.o: water.c water.h types.h terrain.h particle.h logic.h vector.h
terrain.o: terrain.c terrain.h types.h logic.h vector.h
logic.o: logic.c stringOutput.h logic.h types.h vector.h scene.h water.h \
 terrain.h
stringOutput.o: stringOutput.c stringOutput.h


================================================
FILE: src/colorFragmentShader.frag
================================================
#version 330 

in vec3 color; 
out vec4 Color; 
uniform vec3 colorIn; 

void main(){ 
	Color = vec4(colorIn, 1.0); 
}


================================================
FILE: src/colorVertexShader.vert
================================================
#version 330 

layout (location = 0) in vec3 vertPos; 
uniform mat4 viewMatrix, projMatrix; 

void main(){ 
	gl_Position =  projMatrix * viewMatrix * vec4(vertPos, 1.0); 
}


================================================
FILE: src/imageLoader.c
================================================

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <math.h>
/* ---- Eigene Header einbinden ---- */
#include "imageLoader.h"

int error(FILE * f, char * name, char * errorMessage) {
	printf("%s: %s.\n", errorMessage, name);
	fclose(f);
	return 0;
}

/* Loads image for texture creation.*/
int imageLoad(char *filename, Image *image) {
    FILE *file;
    unsigned long size;                 /* size of the image in bytes.*/
    unsigned long i;                    /* standard counter.*/
    unsigned short int planes;          /* number of planes in image (must be 1) */
    unsigned short int bpp;             /* number of bits per pixel (must be 24)*/
    char temp;                          /* used to convert bgr to rgb color.*/

	image->sizeX = 0;
	image->sizeY = 0;

    /* make sure the file is there*/
    if ((file = fopen(filename, "rb")) == NULL)
		return error(file, "File Not Found", filename);
    
    /* seek through the bmp header, up to the width/height:*/
    fseek(file, 18, SEEK_CUR);

    /* read the width*/
    if ((i = fread(&image->sizeX, 4, 1, file)) != 1) 
		return error(file, "Error reading width from", filename);
		
    printf("Width of %s: %lu\n", filename, image->sizeX);
    
    /* read the height */
    if ((i = fread(&image->sizeY, 4, 1, file)) != 1) 
		return error(file, "Error reading height from", filename); 
		
    printf("Height of %s: %lu\n", filename, image->sizeY);
    
    /* calculate the size (assuming 24 bits or 3 bytes per pixel).*/
    size = image->sizeX * image->sizeY * 3;

    /* read the planes*/
    if ((fread(&planes, 2, 1, file)) != 1) 
		return error(file, "Error reading planes from", filename);
		
    if (planes != 1)
		return error(file, "Planes from file is not 1", filename);

    /* read the bpp */
    if ((i = fread(&bpp, 2, 1, file)) != 1) 
		return error(file, "Error reading bpp from", filename);
		
    if (bpp != 24) 
		return error(file, "Bpp from file is not 24\n", filename);
	
    /* seek past the rest of the bitmap header.*/
    fseek(file, 24, SEEK_CUR);

    /* read the data. */
    image->data = malloc(size);
    if (image->data == NULL) 
		return error(file, "Error allocating memory for color-corrected image data", filename);
		
    if ((i = fread(image->data, size, 1, file)) != 1) 
		return error(file, "Error reading image data from", filename);

    for (i=0;i<size;i+=3) 
	{ 
		temp = image->data[i];
		image->data[i] = image->data[i+2];
		image->data[i+2] = temp;
    }

	fclose(file);

    return 1;
}


================================================
FILE: src/imageLoader.h
================================================
#ifndef __IMAGE_H__
#define __IMAGE_H__
#define __DEBUG_GL_H__
/**
 * @file
 * Programmlogik und Datenhaltung
 *
 * @author Maurice Tollmien
 */

/* ---- System Header einbinden ---- */
#ifdef WIN32
#include <windows.h>
#endif

#ifdef MACOSX
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif

#include <stdio.h>
#include <stdarg.h>

typedef struct {
	long unsigned int sizeX, sizeY;
	unsigned char * data;
} Image;

int imageLoad(char *filename, Image *image);

#endif



================================================
FILE: src/io.c
================================================


/**
 * @file
 * Hier sind alle CallBack-Funktionen
 *
 * @author Maurice Tollmien, Tilman Nedele
 */

/* ---- System Header einbinden ---- */
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <math.h>

#ifdef MACOSX
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

/* ---- Eigene Header einbinden ---- */
#include "io.h"
#include "scene.h"
#include "logic.h"
#include "water.h"
#include "terrain.h"
#include "vector.h"
#include "imageLoader.h"

/* ---- Eigene Funktionen ---- */

/* Texturen und Framebuffer */
GLuint 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;

/* Shader-ID's */
GLuint G_ShaderID, G_ShaderIDSimple, G_ShaderColor, G_ShaderIDSimpleD;

/* Geometrie-Buffer */
GLuint G_arrayBuffer, G_TexCube, G_cubeBuffer, G_SurfaceBuffer, G_WaterBuffer, G_WaterBufferIndex, G_ObjectsBuffer, G_TerrainBuffer, G_TerrainBufferIndex, G_CausticsBuffer;

/* Cube-Map */
GLuint G_TexCubeFront, G_TexCubeBack, G_TexCubeBottom, G_TexCubeTop, G_TexCubeLeft, G_TexCubeRight;

/* Shader-Variablen */
GLuint G_projMatrixLoc, G_viewMatrixLoc, G_sampler2dLoc, G_samplerDepth2dLoc, G_cameraPosLoc, G_colorIn, G_samplerCubeLoc;

int view = 1;
int G_Width = 1024;
int G_Height = 1024;
int G_fullScreen = 1;

GLfloat G_data[] = {
				-1.0, -1.0, 0.0,		0.0, 0.0,	
				1.0, -1.0, 0.0,			1.0, 0.0,	
				1.0, 1.0, 0.0,			1.0, 1.0,
				-1.0, -1.0, 0.0,		0.0, 0.0,
				1.0, 1.0, 0.0,			1.0, 1.0,
				-1.0, 1.0, 0.0,			0.0, 1.0
			};

float G_Surface[] = {
	-75, 0.0, -75,
	-75, 0.0, 75,
	75, 0.0, 75,
	-75, 0.0, -75,
	75, 0.0, 75,
	75, 0.0, -75
};

GLfloat G_Objects[] = {
	-30.0, -30.0, -30.0,	
	30.0, -30.0, -30.0,	
	30.0, 30.0, -30.0,
	-30.0, -30.0, -30.0,
	30.0, 30.0, -30.0,
	-30.0, 30.0, -30.0
};

float G_points[] = {
			  -100.0f,  100.0f, -100.0f,
			  -100.0f, -100.0f, -100.0f,
			   100.0f, -100.0f, -100.0f,
			   100.0f, -100.0f, -100.0f,
			   100.0f,  100.0f, -100.0f,
			  -100.0f,  100.0f, -100.0f,
			  
			  -100.0f, -100.0f,  100.0f,
			  -100.0f, -100.0f, -100.0f,
			  -100.0f,  100.0f, -100.0f,
			  -100.0f,  100.0f, -100.0f,
			  -100.0f,  100.0f,  100.0f,
			  -100.0f, -100.0f,  100.0f,
			  
			   100.0f, -100.0f, -100.0f, 
			   100.0f, -100.0f,  100.0f,
			   100.0f,  100.0f,  100.0f,
			   100.0f,  100.0f,  100.0f,
			   100.0f,  100.0f, -100.0f,
			   100.0f, -100.0f, -100.0f,
			   
			  -100.0f, -100.0f,  100.0f,
			  -100.0f,  100.0f,  100.0f,
			   100.0f,  100.0f,  100.0f,
			   100.0f,  100.0f,  100.0f,
			   100.0f, -100.0f,  100.0f,
			  -100.0f, -100.0f,  100.0f,
			  
			  -100.0f,  100.0f, -100.0f,
			   100.0f,  100.0f, -100.0f,
			   100.0f,  100.0f,  100.0f,
			   100.0f,  100.0f,  100.0f,
			  -100.0f,  100.0f,  100.0f,
			  -100.0f,  100.0f, -100.0f,
			  
			  -100.0f, -100.0f, -100.0f,
			  -100.0f, -100.0f,  100.0f,
			   100.0f, -100.0f, -100.0f,
			   100.0f, -100.0f, -100.0f,
			  -100.0f, -100.0f,  100.0f,
			   100.0f, -100.0f,  100.0f
			};


/**
 * Timer-Callback.
 * Initiiert Berechnung der aktuellen Position und Farben und anschliessendes
 * Neuzeichnen, setzt sich selbst erneut als Timer-Callback.
 * @param lastCallTime Zeitpunkt, zu dem die Funktion als Timer-Funktion
 *   registriert wurde (In).
 */
static void
cbTimer (int lastCallTime)
{
	/* Seit dem Programmstart vergangene Zeit in Millisekunden */
	int thisCallTime = glutGet (GLUT_ELAPSED_TIME);
    
	/* Seit dem letzten Funktionsaufruf vergangene Zeit in Sekunden */
	double interval = (double) (thisCallTime - lastCallTime) / 1000.0f;
		
	calcTimeRelatedStuff(interval);
			
	/* Wieder als Timer-Funktion registrieren */
	glutTimerFunc (1000 / TIMER_CALLS_PS, cbTimer, thisCallTime);

	/* Neuzeichnen anstossen */
	glutPostRedisplay ();
    
}

/**
 * Setzen der Projektionsmatrix.
 * Setzt die Projektionsmatrix unter Berücksichtigung des Seitenverhaeltnisses
 * des Anzeigefensters, sodass das Seitenverhaeltnisse der Szene unveraendert
 * bleibt und gleichzeitig entweder in x- oder y-Richtung der Bereich von -1
 * bis +1 zu sehen ist.
 * @param aspect Seitenverhaeltnis des Anzeigefensters (In).
 */
static void
setProjection (GLdouble aspect)
{
  /* Nachfolgende Operationen beeinflussen Projektionsmatrix */
  glMatrixMode (GL_PROJECTION);
  /* Matrix zuruecksetzen - Einheitsmatrix laden */
  glLoadIdentity ();
    
  {
      /* perspektivische Projektion */
      gluPerspective (90.0,     /* Oeffnungswinkel */
                      aspect,   /* Seitenverhaeltnis */
                      0.01,      /* nahe ClipPIEng-Ebene */
                      1000.0 /* ferne ClipPIEng-Ebene */ );
  }
}

static void drawColoredQuad(double r, double g, double b) {
	glDisable(GL_CULL_FACE);
	glUseProgram(G_ShaderColor);
		GLfloat mp[16], mv[16];
		glGetFloatv(GL_PROJECTION_MATRIX, mp);
		glGetFloatv(GL_MODELVIEW_MATRIX, mv);
		glUniformMatrix4fv(glGetUniformLocation(G_ShaderColor, "projMatrix"),  1, GL_FALSE, &mp[0]);
		glUniformMatrix4fv(glGetUniformLocation(G_ShaderColor, "viewMatrix"),  1, GL_FALSE, &mv[0]);
		
		GLfloat color[] = {r, g, b};
		GLfloat cam[] = {getCameraPosition(0), getCameraPosition(1), getCameraPosition(2)};
		glUniform3fv(glGetUniformLocation(G_ShaderColor, "colorIn"), 1, color);
		glUniform3fv(glGetUniformLocation(G_ShaderColor, "cameraPos"), 1, cam);
		
		glBindBuffer (GL_ARRAY_BUFFER, G_ObjectsBuffer);
		glEnableVertexAttribArray(0);
		glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3*sizeof(float), 0);
		glDrawArrays(GL_TRIANGLES, 0, 6);
		
		glDisableVertexAttribArray(0);
		glBindBuffer (GL_ARRAY_BUFFER, 0);
	glUseProgram(0);
	glEnable(GL_CULL_FACE);
}

static void drawSimpleStuff(GLuint colorTex, int fromX, int fromY, int width, int height)   {
	glUseProgram(G_ShaderIDSimple);
		
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glViewport (fromX, fromY, width, height);		
	glMatrixMode (GL_PROJECTION);
	glLoadIdentity ();
	gluPerspective (90.0, 1, 5.1, 1000.0 );
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	gluLookAt (0,0,1,
		 0.0, 0.0, 0.0,
		 0.0, 1.0, 0.0);
	
	glEnable(GL_TEXTURE_2D);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, colorTex);
	
	GLfloat mp[16], mv[16];
	glGetFloatv(GL_PROJECTION_MATRIX, mp);
	glGetFloatv(GL_MODELVIEW_MATRIX, mv);
	glUniformMatrix4fv(glGetUniformLocation(G_ShaderIDSimple, "projMatrix"),  1, GL_FALSE, &mp[0]);
	glUniformMatrix4fv(glGetUniformLocation(G_ShaderIDSimple, "viewMatrix"),  1, GL_FALSE, &mv[0]);
	
	glUniform1i(glGetUniformLocation(G_ShaderIDSimple, "texsampler"), 0);
	
	glBindBuffer (GL_ARRAY_BUFFER, G_arrayBuffer);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), 0);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), 3*sizeof(float));
	
	glDrawArrays(GL_TRIANGLES, 0, 6);
	
	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);
	glBindBuffer (GL_ARRAY_BUFFER, 0);
	
	glUseProgram(0);	
}

static void drawSimpleStuffShader(GLuint shader, GLuint colorTex, int fromX, int fromY, int width, int height)   {
	glUseProgram(shader);
		
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glViewport (fromX, fromY, width, height);		
	glMatrixMode (GL_PROJECTION);
	glLoadIdentity ();
	gluPerspective (90.0, 1, 5.1, 1000.0 );
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	gluLookAt (0,0,1,
		 0.0, 0.0, 0.0,
		 0.0, 1.0, 0.0);
	
	glEnable(GL_TEXTURE_2D);
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, colorTex);
	
	GLfloat mp[16], mv[16];
	glGetFloatv(GL_PROJECTION_MATRIX, mp);
	glGetFloatv(GL_MODELVIEW_MATRIX, mv);
	glUniformMatrix4fv(glGetUniformLocation(G_ShaderIDSimple, "projMatrix"),  1, GL_FALSE, &mp[0]);
	glUniformMatrix4fv(glGetUniformLocation(G_ShaderIDSimple, "viewMatrix"),  1, GL_FALSE, &mv[0]);
	
	glUniform1i(glGetUniformLocation(G_ShaderIDSimple, "texsampler"), 0);
	
	glBindBuffer (GL_ARRAY_BUFFER, G_arrayBuffer);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5*sizeof(float), 0);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5*sizeof(float), 3*sizeof(float));
	
	glDrawArrays(GL_TRIANGLES, 0, 6);
	
	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);
	glBindBuffer (GL_ARRAY_BUFFER, 0);
	
	glUseProgram(0);	
}

void drawTerrainComplete(void) {
	glUseProgram(G_ShaderIDSimple);
	
	glActiveTexture(GL_TEXTURE0);
	glBindTexture(GL_TEXTURE_2D, G_TexImageGrass);
	glActiveTexture(GL_TEXTURE1);
	glBindTexture(GL_TEXTURE_2D, G_TexImageSand);
	glActiveTexture(GL_TEXTURE0+2);
	glBindTexture(GL_TEXTURE_2D, G_TexImageForest);
	glActiveTexture(GL_TEXTURE0+3);
	glBindTexture(GL_TEXTURE_2D, G_TexImageRocks);
	glActiveTexture(GL_TEXTURE0+4);
	glBindTexture(GL_TEXTURE_2D, G_TexImageSnow);
	glActiveTexture(GL_TEXTURE0+5);
	glBindTexture(GL_TEXTURE_2D, G_TexImageTundra);
		
	GLfloat mp[16], mv[16];
	glGetFloatv(GL_PROJECTION_MATRIX, mp);
	glGetFloatv(GL_MODELVIEW_MATRIX, mv);
	glUniformMatrix4fv(glGetUniformLocation(G_ShaderIDSimple, "projMatrix"),  1, GL_FALSE, &mp[0]);
	glUniformMatrix4fv(glGetUniformLocation(G_ShaderIDSimple, "viewMatrix"),  1, GL_FALSE, &mv[0]);
		 
	glUniform1i(glGetUniformLocation(G_ShaderIDSimple, "texSand") , 1);
	glUniform1i(glGetUniformLocation(G_ShaderIDSimple, "texGrass"), 0);
	glUniform1i(glGetUniformLocation(G_ShaderIDSimple, "texForest"), 2);
	glUniform1i(glGetUniformLocation(G_ShaderIDSimple, "texRocks"), 3);
	glUniform1i(glGetUniformLocation(G_ShaderIDSimple, "texSnow"), 4);
	glUniform1i(glGetUniformLocation(G_ShaderIDSimple, "texTundra"), 5);
	
	/* Wasser-Normalen für eigene Caustics-Berechnungen */
		glBindBuffer (GL_ARRAY_BUFFER, G_CausticsBuffer);
		glBufferData (GL_ARRAY_BUFFER, sizeof(*getTerrainCaustics())*TERRAIN_SIZE*TERRAIN_SIZE, getTerrainCaustics(), GL_STREAM_DRAW);
		glEnableVertexAttribArray(3);
		glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 5*sizeof(GLfloat));
		
	/* Offset in X und Z-Richtung eventuell hier in die Shader übergeben... */
	
	glBindBuffer (GL_ARRAY_BUFFER, G_TerrainBuffer);
	glEnableVertexAttribArray(0);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 0);
	glEnableVertexAttribArray(1);
	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 3*sizeof(GLfloat));
	glEnableVertexAttribArray(2);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 5*sizeof(GLfloat));
	
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, G_TerrainBufferIndex);
	glDrawElements(GL_TRIANGLES, TERRAIN_SIZE*TERRAIN_SIZE*2*3, GL_UNSIGNED_INT, 0);
	
	glDisableVertexAttribArray(0);
	glDisableVertexAttribArray(1);
	glDisableVertexAttribArray(2);
	glDisableVertexAttribArray(3);
	
	glUseProgram(0);
	
}

void drawSceneToTexture(GLuint tex, GLfloat ex, GLfloat ey, GLfloat ez, GLfloat cx, GLfloat cy, GLfloat cz) {
	glBindFramebuffer(GL_FRAMEBUFFER, tex);	
	glClearColor(0.0, 1.0, 1.0, 0.0);
	glClearDepth(1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	glViewport (0, 0, G_Width, G_Height);		
	setProjection (1);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt (	ex, ey, ez,
		 cx, cy, cz,
		 0.0, 1.0, 0.0);

	glDisable(GL_TEXTURE_2D);
	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
		printf ("Framebuffer ist nicht korrekt! 4\n");
	}

	/*drawSides();*/
	drawTerrainComplete();
	
}


void allocateMemoryStuff(GLuint * texID, GLuint * fbo) {
	
	glGenTextures(1, texID);
	glBindTexture(GL_TEXTURE_2D, *texID);
	
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	/*glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);*/
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	
	/*glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);	*/
	glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE, GL_INTENSITY);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_R_TO_TEXTURE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
	
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, G_Width, G_Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
	
	glGenFramebuffers(1, fbo);
	glBindFramebuffer(GL_FRAMEBUFFER, *fbo);	
	
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texID, 0);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void allocateMemoryStuffDepth(GLuint * texID, GLuint * texID2, GLuint * fbo) {
	
	glGenTextures(1, texID);
	glBindTexture(GL_TEXTURE_2D, *texID);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, G_Width, G_Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
	
	glGenTextures(1, texID2);
	glBindTexture(GL_TEXTURE_2D, *texID2);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);	
	glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, G_Width, G_Height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
	
	glGenFramebuffers(1, fbo);
	glBindFramebuffer(GL_FRAMEBUFFER, *fbo);	
	
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texID, 0);
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, *texID2, 0);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void loadCubeSide(GLuint * texID, GLenum side) {
	/*glBindTexture(GL_TEXTURE_CUBE_MAP, *texID);*/
	
	glTexImage2D(side, 0, GL_RGBA8, G_Width, G_Height, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);	
}

void appendTexToFB(GLuint * fbo, GLuint * texID, GLenum side) {
	glGenFramebuffers(1, fbo);
	glBindFramebuffer(GL_FRAMEBUFFER, *fbo);		
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, side, *texID, 0);
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void allocateMemoryStuffCube(GLuint * texID) {
	glActiveTexture (GL_TEXTURE0);
	glGenTextures(1, texID);
	
	
	glBindTexture(GL_TEXTURE_CUBE_MAP, *texID);
	
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0); 
	glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
	
	loadCubeSide(texID, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); /* front  */
	loadCubeSide(texID, GL_TEXTURE_CUBE_MAP_POSITIVE_Z); /* back   */
	loadCubeSide(texID, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y); /* bottom */
	loadCubeSide(texID, GL_TEXTURE_CUBE_MAP_POSITIVE_Y); /* top    */
	loadCubeSide(texID, GL_TEXTURE_CUBE_MAP_NEGATIVE_X); /* left   */
	loadCubeSide(texID, GL_TEXTURE_CUBE_MAP_POSITIVE_X); /* right  */
	
	appendTexToFB(&G_TexCubeFront, texID, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
	appendTexToFB(&G_TexCubeBack,  texID, GL_TEXTURE_CUBE_MAP_POSITIVE_Z);
	appendTexToFB(&G_TexCubeBottom,texID, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y);
	appendTexToFB(&G_TexCubeTop,   texID, GL_TEXTURE_CUBE_MAP_POSITIVE_Y);
	appendTexToFB(&G_TexCubeLeft,  texID, GL_TEXTURE_CUBE_MAP_NEGATIVE_X);
	appendTexToFB(&G_TexCubeRight, texID, GL_TEXTURE_CUBE_MAP_POSITIVE_X);
	
	
	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
		printf ("Framebuffer ist nicht korrekt 1!\n");
	}
	
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}

void renderFBToCubeTexture(GLuint * fbo, GLenum side, double vX, double vY, double vZ) {
	/*==================================================================*/
	/* Eine Seite für die Cube-Textur rendern */
	/*==================================================================*/
	glBindFramebuffer(GL_FRAMEBUFFER, *fbo);	
	glClearColor(0.0, 1.0, 1.0, 0.0);
	glClearDepth(1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glViewport (0, 0, G_Width, G_Height);		
	setProjection(1);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	
	gluLookAt (0, 0, 0,
		 vX, vY, vZ,
		 0.0, fabs(vY) > 0.8 ? 0.0 : 1.0, vY > 0.8 ? 1.0 : (vY < -0.8 ? -1.0 : 0.0));

	glDisable(GL_TEXTURE_2D);
	if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
		printf ("Framebuffer ist nicht korrekt! 2\n");

	}
	
	/*drawColoredQuad(1,1,1);*/
	/*drawSides();*/
	
	/* RAUS, WEIL EIGENTLICH NUR DIE ENTFERNTE UMGEBUNG HIER WAHRGENOMMEN WERDEN SOLL UND  NICHT DIE KONKRETEN, DYNAMISCHEN OBJEKTE DER SCENE!!!!!!! */
	/*drawTerrainComplete();*/
}



/**
 * Zeichen-Callback.
 * Loescht die Buffer, ruft das Zeichnen der Szene auf und tauscht den Front-
 * und Backbuffer.
 */
static void
cbDisplay (void)
{
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
	glClearColor(0.0, 1.0, 1.0, 0.0);
	glClearDepth(1.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	/*==================================================================*/
	/* Textur mit Kamera-Perspektive */
	/*==================================================================*/
	drawSceneToTexture(G_fboCam, getCameraPosition(0), getCameraPosition(1), getCameraPosition(2), 0.0, 0.0, 0.0);
	
	/*==================================================================*/
	/* Textur mit Reflection-Perspektive */
	/*==================================================================*/
	/*drawSceneToTexture(G_fboRefl, 0.0, 0.0, 0.0,
		 getCameraPosition(0)+(2*-getCameraPosition(0)), 
		 getCameraPosition(1)+(2*-getCameraPosition(1))+2*getCameraPosition(1), 
		 getCameraPosition(2)+(2*-getCameraPosition(2)));*/
	
	/*==================================================================*/
	/* Kamera-Textur rendern. */
	/*==================================================================*/
	if (0) {
		drawSimpleStuff(G_fboCam, 0, G_Height/2, G_Width/2, G_Height/2);
	}
	if (0) {
		drawSimpleStuffShader(G_ShaderIDSimpleD, G_TexCameraDepth, 0, 0, G_Width/2, G_Height/2);
	}
	
	/*==================================================================*/
	/* Reflection-Textur rendern */
	/*==================================================================*/
	if (0) {
		drawSimpleStuff(G_TexReflection, G_Width/2, G_Height/2, G_Width/2, G_Height/2);
	}

	/*==================================================================*/
	/* Spiegelfläche mit korrektem dynamischen Environment-Mapping (Reflection + Refraction) */
	/*==================================================================*/
	if (0) {			
		glUseProgram(G_ShaderID);
			glBindFramebuffer(GL_FRAMEBUFFER, 0);
			glViewport (0, 0, G_Width/2, G_Height/2);		
			setProjection (1);
			glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();
			gluLookAt (getCameraPosition(0), getCameraPosition(1), getCameraPosition(2),
				 0.0, 0.0, 0.0,
				 0.0, 1.0, 0.0);
			
			glEnable(GL_TEXTURE_CUBE_MAP);
			glEnable(GL_TEXTURE_2D);
			
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_CUBE_MAP, G_TexCube);
			
			GLfloat mp[16], mv[16];
			glGetFloatv(GL_PROJECTION_MATRIX, mp);
			glGetFloatv(GL_MODELVIEW_MATRIX, mv);
			glUniformMatrix4fv(glGetUniformLocation(G_ShaderID, "projMatrix"),  1, GL_FALSE, &mp[0]);
			glUniformMatrix4fv(glGetUniformLocation(G_ShaderID, "viewMatrix"),  1, GL_FALSE, &mv[0]);
			
			glUniform1i(G_sampler2dLoc, 0);
			
			GLfloat cam_pos[] = {getCameraPosition(0), getCameraPosition(1), getCameraPosition(2)};
			glUniform3fv(glGetUniformLocation(G_ShaderID, "cameraPos"), 1, cam_pos);
			
			glBindBuffer (GL_ARRAY_BUFFER, G_WaterBuffer);
			glBufferData (GL_ARRAY_BUFFER, sizeof(*getWaterList())*WORLD_SIZE*WORLD_SIZE, getWaterList(), GL_STATIC_DRAW);
			glEnableVertexAttribArray(0);
			glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat)+1*sizeof(GLint), 0);
			glEnableVertexAttribArray(1);
			glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat)+1*sizeof(GLint), 5*sizeof(GLfloat));
			
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, G_WaterBufferIndex);
			
			/* Wasser. */
			glDrawElements(GL_TRIANGLES, WORLD_SIZE*WORLD_SIZE*2*3, GL_UNSIGNED_INT, 0);
			
			glDisableVertexAttribArray(0);
			glDisableVertexAttribArray(1);
			glDisable(GL_TEXTURE_CUBE_MAP);
			glDisable(GL_TEXTURE_2D);
			
		glUseProgram(0);
		
		/*drawSides();*/
		drawTerrainComplete();
		
		
	}
	
	/*==================================================================*/
	/* Spiegelfläche mit Screenspace-Reflections */
	/*==================================================================*/
	if (1) {			
		int toX = G_fullScreen ? G_Width : G_Width/2, 
			toZ = G_fullScreen ? G_Height : G_Height/2;
		glUseProgram(G_ShaderID);
			glBindFramebuffer(GL_FRAMEBUFFER, 0);
			glViewport (0, 0, toX, toZ);
			setProjection (1);
			glMatrixMode(GL_MODELVIEW);
			glLoadIdentity();
			gluLookAt (getCameraPosition(0), getCameraPosition(1), getCameraPosition(2),
				 0.0, 0.0, 0.0,
				 0.0, 1.0, 0.0);
			
			glActiveTexture(GL_TEXTURE1);
			glBindTexture(GL_TEXTURE_2D, G_TexCamera);
			glActiveTexture(GL_TEXTURE0);
			glBindTexture(GL_TEXTURE_2D, G_TexCameraDepth);
			glActiveTexture(GL_TEXTURE2);
			glBindTexture(GL_TEXTURE_CUBE_MAP, G_TexCube);
			
			GLfloat mp[16], mv[16];
			glGetFloatv(GL_PROJECTION_MATRIX, mp);
			glGetFloatv(GL_MODELVIEW_MATRIX, mv);
			glUniformMatrix4fv(glGetUniformLocation(G_ShaderID, "projMatrix"),  1, GL_FALSE, &mp[0]);
			glUniformMatrix4fv(glGetUniformLocation(G_ShaderID, "viewMatrix"),  1, GL_FALSE, &mv[0]);
			
			glUniform1i(G_sampler2dLoc, 1);
			glUniform1i(G_samplerDepth2dLoc, 0);
			glUniform1i(G_samplerCubeLoc, 2);
			
			GLfloat cam_pos[] = {getCameraPosition(0), getCameraPosition(1), getCameraPosition(2)};
			glUniform3fv(glGetUniformLocation(G_ShaderID, "cameraPos"), 1, cam_pos);
			
			/*glBindBuffer (GL_ARRAY_BUFFER, G_TerrainBuffer);
			glEnableVertexAttribArray(2);
			glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), 0);*/
			
			glBindBuffer (GL_ARRAY_BUFFER, G_WaterBuffer);
			glBufferData (GL_ARRAY_BUFFER, sizeof(*getWaterList())*WORLD_SIZE*WORLD_SIZE, getWaterList(), GL_STATIC_DRAW);
			glEnableVertexAttribArray(0);
			glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat)+1*sizeof(GLint), 0);
			glEnableVertexAttribArray(1);
			glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat)+1*sizeof(GLint), 5*sizeof(GLfloat));
			
			glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, G_WaterBufferIndex);
			
			/* Wasser. */
			glDrawElements(GL_TRIANGLES, WORLD_SIZE*WORLD_SIZE*2*3, GL_UNSIGNED_INT, 0);
			
			glDisableVertexAttribArray(0);
			glDisableVertexAttribArray(1);
			
		glUseProgram(0);
		
		/*drawSides();*/
		drawTerrainComplete();
		drawFPS();
	}
	
	/*==================================================================*/
	/* Landschaft aus Perlin-Noise. */
	/*==================================================================*/
	if (!G_fullScreen) {
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
		glViewport (G_Width/2, G_Height/2, G_Width/2, G_Height/2);
		setProjection (1);
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();
		gluLookAt (getCameraPosition(0), getCameraPosition(1), getCameraPosition(2),
			 0.0, 0.0, 0.0,
			 0.0, 1.0, 0.0);
			 
		drawTerrainComplete();
	}

	/*==================================================================*/
	/* Die Normale Scene auf der rechten Seite rendern. Echte Polygone etc. */
	/*==================================================================*/
	if (0) {
		glUseProgram(0);
		glBindFramebuffer(GL_FRAMEBUFFER, 0);
		glViewport (0, G_Height/2, G_Width/2, G_Height/2);		
		setProjection (1);
		glMatrixMode(GL_MODELVIEW);
		glLoadIdentity();

		gluLookAt (getCameraPosition(0), getCameraPosition(1), getCameraPosition(2),
			 0.0, 0.0, 0.0,
			 0.0, 1.0, 0.0);		
			
		glDisable(GL_TEXTURE_2D);
		
		drawSides();
		drawWaterSurface();		
	}	
	
	/* Alles fertig. */
	glutSwapBuffers ();
}

/**
 * Callback fuer Tastendruck.
 * Ruft Ereignisbehandlung fuer Tastaturereignis auf.
 * @param key betroffene Taste (In).
 * @param x x-Position der Maus zur Zeit des Tastendrucks (In).
 * @param y y-Position der Maus zur Zeit des Tastendrucks (In).
 */
void cbKeyboard (unsigned char key, int x, int y)
{
	
	switch (key)
	{
		case 'q':
		case 'Q':
		case ESC:
			exit (0);
			break;
		case 'r':
        case 'R':
			/*initGame ();*/
			setRandomize();
			break;
		case 'h':
        case 'H':
            setHelpStatus(!getHelpStatus());
            break;
        case '+':
            incQuadCount();
            break;
        case '-':
            decQuadCount();
            break;
        case 'n':
		case 'N':
			pushSomeWaterDown();
            break;
        case 'w':
        case 'W':
			toggleWaterMovement();
			break;
        case 'm':
		case 'M':
			toggleSpheresMoving ();
            break;
		case 'p':
        case 'P':
            toggleParticleFreeze ();
            break;
		case 'f':
        case 'F':
            G_fullScreen = !G_fullScreen;
            break;
        case 's':
        case 'S':
            toggleShadows ();
            break;    
        case 'k':
        case 'K':
			printf ("k recognized.\n");
            startMovingBall ();
            break;   
        case 'v':
        case 'V':
            view = !view;
            break;  
            
	}	
}

/* Spezialtasten-Druck-Callback - wird ausgefuehrt, wenn Spezialtaste
* (F1 - F12, Links, Rechts, Oben, Unten, Bild-Auf, Bild-Ab, Pos1, Ende oder
* Einfuegen) gedrueckt wird */
void cbSpecial (int key, int x, int y)
{
	switch (key)
	{
        case GLUT_KEY_LEFT: 

			break;
		case GLUT_KEY_RIGHT:

			break;
		case GLUT_KEY_UP:
            setKey (1, 1);
			break;
		case GLUT_KEY_DOWN:
            setKey(0,1);
			break;
		case GLUT_KEY_F1:
            toggleWireframeMode();
			break;
        case GLUT_KEY_F2:
            setLightStatus(!getLightStatus());
            break;
		case GLUT_KEY_F3:
            setTextureStatus(!getTextureStatus());
			break;
        case GLUT_KEY_F4:

            break;
        case GLUT_KEY_F5:

            break;
        case GLUT_KEY_F6:

            break;
        case GLUT_KEY_F7:

            break;
        case GLUT_KEY_F8:

            break;
	}
}

/* Wird aufgerufen, wenn eine Spezialtaste wieder losgelassen wird1 */
void cbUpSpecial (int key, int x, int y)
{
	switch (key)
	{
		case GLUT_KEY_LEFT: 

			break;
		case GLUT_KEY_RIGHT:

			break;
		case GLUT_KEY_UP:
            setKey (1,0);
			break;
		case GLUT_KEY_DOWN:
            setKey (0,0);
			break;
	}
}

/**
 * Verarbeitung eines Mausereignisses.
 * Durch Bewegung der Maus bei gedrueckter Maustaste kann die aktuelle
 * Zeichenfarbe beeinflusst werden.
 * Falls Debugging aktiviert ist, wird jedes Mausereignis auf stdout
 * ausgegeben.
 * @param x x-Position des Mauszeigers zum Zeitpunkt der Ereignisausloesung.
 * @param y y-Position des Mauszeigers zum Zeitpunkt der Ereignisausloesung.
 * @param eventType Typ des Ereignisses.
 * @param button ausloesende Maustaste (nur bei Ereignissen vom Typ mouseButton).
 * @param buttonState Status der Maustaste (nur bei Ereignissen vom Typ mouseButton).
 */
static void
handleMouseEvent (int x, int y, CGMouseEventType eventType, int button, int buttonState)
{
    switch (eventType)
    {
        case mouseButton:
            switch (button)
            {
                case GLUT_LEFT_BUTTON:
                    setMouseEvent(MOVE,x,y);
                break;
                case GLUT_RIGHT_BUTTON:
                    setMouseEvent(ZOOM,x,y);
                break;
                default:
                  break;
            }
        break;
        default:
          break;
    }
    if (buttonState)
        setMouseEvent(NONE,x,y);

}

/**
 * Mouse-Button-Callback.
 * @param button Taste, die den Callback ausgeloest hat.
 * @param state Status der Taste, die den Callback ausgeloest hat.
 * @param x X-Position des Mauszeigers beim Ausloesen des Callbacks.
 * @param y Y-Position des Mauszeigers beim Ausloesen des Callbacks.
 */
static void
cbMouseButton (int button, int state, int x, int y)
{
	handleMouseEvent (x, y, mouseButton, button, state);
}

void mouseMovement(int x, int y) 
{
    
    if (getMouseEvent() == MOVE)
		setCameraMovement(x,y);
	
    if (getMouseEvent() == ZOOM)
        setCameraZoom(x,y);
}




/**
 * Callback fuer Aenderungen der Fenstergroesse.
 * Initiiert Anpassung der Projektionsmatrix an veraenderte Fenstergroesse.
 * @param w Fensterbreite (In).
 * @param h Fensterhoehe (In).
 */
static void
cbReshape (int w, int h)
{
  /* Das ganze Fenster ist GL-Anzeigebereich */
  glViewport (0, 0, (GLsizei) w, (GLsizei) h);

  /* Anpassen der Projektionsmatrix an das Seitenverhaeltnis des Fensters */
  setProjection ((GLdouble) w / (GLdouble) h);
}

/**
 * Registrierung der GLUT-Callback-Routinen.
 */
static void registerCallBacks (void)
{
    /* Mouse-Button-Callback (wird ausgefuehrt, wenn eine Maustaste
     *  gedrueckt oder losgelassen wird) */
    glutMouseFunc (cbMouseButton);
    
    glutMotionFunc(mouseMovement);
	
	/* Timer-Callback - wird einmalig nach msescs Millisekunden ausgefuehrt */
	glutTimerFunc (1000 / TIMER_CALLS_PS, /* msecs - bis Aufruf von func */
                 cbTimer,       /* func  - wird aufgerufen    */
                 glutGet (GLUT_ELAPSED_TIME));  /* value - Parameter, mit dem
                                                   func aufgerufen wird */

	/* Reshape-Callback - wird ausgefuehrt, wenn neu gezeichnet wird (z.B. nach
	* Erzeugen oder Groessenaenderungen des Fensters) */
	glutReshapeFunc (cbReshape);

	/* Display-Callback - wird an mehreren Stellen imlizit (z.B. im Anschluss an
	* Reshape-Callback) oder explizit (durch glutPostRedisplay) angestossen */
	glutDisplayFunc (cbDisplay);
	
	/* Tasten-Druck-Callback - wird ausgefuehrt, wenn eine Taste gedrueckt wird */
	glutKeyboardFunc (cbKeyboard);
	
	/* Spezialtasten-Druck-Callback - wird ausgefuehrt, wenn Spezialtaste
	* (F1 - F12, Links, Rechts, Oben, Unten, Bild-Auf, Bild-Ab, Pos1, Ende oder
	* Einfuegen) gedrueckt wird */
	glutSpecialFunc (cbSpecial);
	
    /* Wird aufgerufen, wenn eine Taste wieder losgelassen wird! */
	glutSpecialUpFunc(cbUpSpecial);
    
	/* Automat. Tastendruckwiederholung ignorieren */
	glutIgnoreKeyRepeat (1);
    
    /* Wenn die Fenstergröße verändert wird. */
    /*glutReshapeFunc(cgReshape);*/
}

int readFile (char * name, char ** buffer) {
	FILE *f = fopen(name, "rb");
	fseek(f, 0, SEEK_END);
	int pos = ftell(f);
	fseek(f, 0, SEEK_SET);

	(*buffer) = malloc(pos+1);
	fread(*buffer, pos-1, 1, f);
	(*buffer)[pos-1] = '\0';
	fclose(f);
}

GLuint loadShaders(char * vertexShader, char * fragmentShader){
 
    /* Create the shaders */
    GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
    GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
 
	/* Read Shader from File was here */
 
    GLint Result = GL_FALSE;
    int InfoLogLength;
 
    /* Compile Vertex Shader */
    printf("Compiling Vertex shader\n");
    char * VertexSourcePointer = NULL;
    readFile(vertexShader, &VertexSourcePointer);
    
    glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
    glCompileShader(VertexShaderID);
 
    /* Check Vertex Shader */
    glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    char * vertexShaderErrorMessage = calloc(InfoLogLength, sizeof(char));
    glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &(vertexShaderErrorMessage[0]));
    fprintf(stdout, "vertexShaderErrorMessage: %s\n", vertexShaderErrorMessage);
 
    /* Compile Fragment Shader */
    printf("Compiling Fragment shader\n");
    char * FragmentSourcePointer = NULL;
    readFile(fragmentShader, &FragmentSourcePointer);
    
    /*printf ("FragmentShader: \n\"%s\"\n", FragmentSourcePointer);*/
    
    glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
    glCompileShader(FragmentShaderID);
 
    /* Check Fragment Shader */
    glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
    glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    char * fragmentShaderErrorMessage = calloc(InfoLogLength, sizeof(char));
    glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &(fragmentShaderErrorMessage[0]));
    fprintf(stdout, "fragmentShaderErrorMessage: %s\n", fragmentShaderErrorMessage);
 
    /*  Link the program */
    GLuint ProgramID = glCreateProgram();
    
    glAttachShader(ProgramID, VertexShaderID);
    
    glAttachShader(ProgramID, FragmentShaderID);
    
    glLinkProgram(ProgramID);
    
    /* Check the program */
    glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result);
    glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength);
    char * programErrorMessage = calloc(InfoLogLength, sizeof(char));
    glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &(programErrorMessage[0]));
    fprintf(stdout, "programErrorMessage: %s\n", programErrorMessage);
 
    glDeleteShader(VertexShaderID);
    glDeleteShader(FragmentShaderID);
 
    return ProgramID;
}

int loadTextureImage(Image * image, char * name, GLuint * tex) {
	
	if (!imageLoad(name, image)) 
	{
		printf("Error reading image file");
		exit(1);
	}        
	
	glGenTextures(1, tex);
	glBindTexture(GL_TEXTURE_2D, *tex);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, image->sizeX, image->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, image->data);	
}

/**
 * Initialisiert das Programm (inkl. I/O und OpenGL) und startet die
 * Ereignisbehandlung.
 * @param title Beschriftung des Fensters
 * @param width Breite des Fensters
 * @param height Hoehe des Fensters
 * @return ID des erzeugten Fensters, 0 im Fehlerfall
 */
int initAndStartIO (char *title, int width, int height)
{
	int windowID = 0;
	
	/* Kommandozeile immitieren */
	int argc = 1;
	char *argv = "cmd";
	
	G_Width = width;
	G_Height = height;

	/* Glut initialisieren */
	glutInit (&argc, &argv);
	
	/* FensterInitialisierung */
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	/* FensterGröße */
	glutInitWindowSize (G_Width, G_Height);
	/* FensterPosition */
	glutInitWindowPosition (0, 0);
	
	windowID = glutCreateWindow (title);
	
	if (windowID)
	{
		/* Hintergrund und so werden initialisiert (Farben) */
		if (initScene ())
		{
			G_ShaderID = loadShaders("waterVertexShader.vert", "waterFragmentShader.frag");
			G_ShaderIDSimple = loadShaders("textureVertexShader.vert", "textureFragmentShader.frag");
			G_ShaderIDSimpleD = loadShaders("textureVertexShader.vert", "textureDepthFragmentShader.frag");
			G_ShaderColor = loadShaders("colorVertexShader.vert", "colorFragmentShader.frag");
           
			registerCallBacks ();
			
			allocateMemoryStuffDepth(&G_TexCamera, &G_TexCameraDepth, &G_fboCam);
			allocateMemoryStuff(&G_TexReflection, &G_fboRefl);
			allocateMemoryStuff(&G_TexRefraction, &G_fboRefr);
			
			allocateMemoryStuffCube(&G_TexCube);

			G_sampler2dLoc  		= glGetUniformLocation(G_ShaderID, "texsampler");
			G_samplerDepth2dLoc  	= glGetUniformLocation(G_ShaderID, "texsamplerDepth");
			G_samplerCubeLoc	  	= glGetUniformLocation(G_ShaderID, "texsamplerCube");
			
			Image * imageSand, * imageGrass, * imageCaustics, * imageRocks, * imageSnow, * imageForest, * imageTundra;
			imageSand  = malloc(sizeof(Image));
			imageGrass = malloc(sizeof(Image));
			imageCaustics = malloc(sizeof(Image));
			imageRocks = malloc(sizeof(Image));
			imageSnow = malloc(sizeof(Image));
			imageForest = malloc(sizeof(Image));
			imageTundra = malloc(sizeof(Image));
			
			loadTextureImage(imageSand,  "sand1.bmp", &G_TexImageSand );
			loadTextureImage(imageGrass, "gras2.bmp", &G_TexImageGrass);
			loadTextureImage(imageCaustics, "caustics.bmp", &G_TexImageCaustics);
			loadTextureImage(imageRocks, "rocks.bmp", &G_TexImageRocks);
			loadTextureImage(imageSnow, "snow.bmp", &G_TexImageSnow);
			loadTextureImage(imageForest, "forest.bmp", &G_TexImageForest);
			loadTextureImage(imageTundra, "tundra.bmp", &G_TexImageTundra);
			 
			glGenBuffers(1, &G_arrayBuffer);
			glBindBuffer(GL_ARRAY_BUFFER, G_arrayBuffer); 
			glBufferData(GL_ARRAY_BUFFER, sizeof(G_data), G_data, GL_STATIC_DRAW);
			glBindBuffer(GL_ARRAY_BUFFER, 0);

			glGenBuffers (1, &G_cubeBuffer);
			glBindBuffer (GL_ARRAY_BUFFER, G_cubeBuffer);
			glBufferData (GL_ARRAY_BUFFER, sizeof(G_points), &G_points, GL_STATIC_DRAW);
			glBindBuffer (GL_ARRAY_BUFFER, 0);
			
			glGenBuffers (1, &G_SurfaceBuffer);
			glBindBuffer (GL_ARRAY_BUFFER, G_SurfaceBuffer);
			glBufferData (GL_ARRAY_BUFFER, sizeof(G_Surface), &G_Surface, GL_STATIC_DRAW);
			glBindBuffer (GL_ARRAY_BUFFER, 0);
			
			/* Wasser */
			glGenBuffers (1, &G_WaterBuffer);
			glBindBuffer (GL_ARRAY_BUFFER, G_WaterBuffer);
			glBufferData (GL_ARRAY_BUFFER, sizeof(*getWaterList())*WORLD_SIZE*WORLD_SIZE, getWaterList(), GL_STREAM_DRAW);
			glBindBuffer (GL_ARRAY_BUFFER, 0);
			
			glGenBuffers (1, &G_WaterBufferIndex);
			glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, G_WaterBufferIndex);
			glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(*getWaterIndices())*WORLD_SIZE*WORLD_SIZE*3*2, getWaterIndices(), GL_STREAM_DRAW);
			glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
			
			/* Terrain */
			glGenBuffers (1, &G_TerrainBuffer);
			glBindBuffer (GL_ARRAY_BUFFER, G_TerrainBuffer);
			glBufferData (GL_ARRAY_BUFFER, sizeof(*getTerrainList())*TERRAIN_SIZE*TERRAIN_SIZE, getTerrainList(), GL_STATIC_DRAW);
			glBindBuffer (GL_ARRAY_BUFFER, 0);
			
			glGenBuffers (1, &G_TerrainBufferIndex);
			glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, G_TerrainBufferIndex);
			glBufferData (GL_ELEMENT_ARRAY_BUFFER, sizeof(*getTerrainIndices())*TERRAIN_SIZE*TERRAIN_SIZE*3*2, getTerrainIndices(), GL_STATIC_DRAW);
			glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
			
			/* Caustics --> Indices des Terrains nutzen! */
			glGenBuffers (1, &G_CausticsBuffer);
			glBindBuffer (GL_ARRAY_BUFFER, G_CausticsBuffer);
			glBufferData (GL_ARRAY_BUFFER, sizeof(*getTerrainCaustics())*TERRAIN_SIZE*TERRAIN_SIZE, getTerrainCaustics(), GL_STREAM_DRAW);
			glBindBuffer (GL_ARRAY_BUFFER, 0);
			
			glGenBuffers(1, &G_ObjectsBuffer);
			glBindBuffer(GL_ARRAY_BUFFER, G_ObjectsBuffer); 
			glBufferData(GL_ARRAY_BUFFER, sizeof(G_Objects), G_Objects, GL_STATIC_DRAW);
			glBindBuffer(GL_ARRAY_BUFFER, 0);
			
			glBindFramebuffer(GL_FRAMEBUFFER, 0);
			glClearColor(0.0, 1.0, 1.0, 0.0);
			glClearDepth(1.0f);
			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
			renderFBToCubeTexture(&G_TexCubeFront, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0,  0,    -1);
			renderFBToCubeTexture(&G_TexCubeBack,  GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0,  0,    1);
			renderFBToCubeTexture(&G_TexCubeBottom,GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0,  -1,   0);
			renderFBToCubeTexture(&G_TexCubeTop,   GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0,  1,    0);
			renderFBToCubeTexture(&G_TexCubeLeft,  GL_TEXTURE_CUBE_MAP_NEGATIVE_X, -1, 0,    0);
			renderFBToCubeTexture(&G_TexCubeRight, GL_TEXTURE_CUBE_MAP_POSITIVE_X, 1,  0,    0);
			
			/* Die Endlosschleife wird angestoßen */
			glutMainLoop ();  
			windowID = 0;
			
			glDeleteFramebuffers(1, &G_fboCam);
			glDeleteTextures(1, &G_TexCamera);
            
		} 
		else
		{
			glutDestroyWindow (windowID);
			windowID = 0;
		}
	}
	return windowID;
}


================================================
FILE: src/io.h
================================================
#ifndef __IO_H__
#define __IO_H__
#define __DEBUG_GL_H__
/**
 * @file
 * CallBack-Funktionsköpfe
 *
 * @author Maurice Tollmien
 */

/* ---- System Header einbinden ---- */
#ifdef WIN32
#include <windows.h>
#endif

#ifdef MACOSX
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

#ifdef MACOSX
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif

#include <stdio.h>
#include <stdarg.h>

int initAndStartIO (char *title, int width, int height);

#endif


================================================
FILE: src/logic.c
================================================

/**
 * @file
 * Hier ist die Datenhaltung und Programmlogik
 *
 * @author Tilman Nedele, Maurice Tollmien
 */

/* ---- System Header einbinden ---- */
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <math.h>
#include <stringOutput.h>
#include <assert.h>

#ifdef MACOSX
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

/* ---- Eigene Header einbinden ---- */
#include "logic.h"
#include "vector.h"
#include "scene.h"
#include "types.h"
#include "water.h"
#include "terrain.h"

/* Globale Variablen */
/** Licht an/aus */
InitType G_Light = ON;
/** Hilfe an/aus */
InitType G_Help  = OFF;
/** Textur an/aus */
InitType G_Texture = ON;
/** Mausbewegung zoom/move/none */
MouseInterpretType G_Mouse;
/** Kameraposition */
CGVector3D G_CameraPosition = {CAMERA_X,CAMERA_Y,CAMERA_Z};
/** Position der Maus */
Movement G_MouseMove = {0.0,0.0,0.0};
/** Startpunkt der Mausbewegung */
CGVector3D G_LastMouseCenter = {0.0,0.0,0.0};
/** Anzahl der Quadrate für den Boden */
int G_QuadCount = 0;
/** Welche Textur soll angezeigt werden */
int G_TextureCount = 5;
/** Liste aller Kugeln */
Spheres * G_Spheres;

int G_BallMoving = 0;

Quads * G_Quads;
/** Sollen sich die Kugeln bewegen? */
int G_SpheresMoving = 0;
/** Ob die Partikel neu berechnet werden */
int G_ParticleFreeze = 0;
/** Wie sollen die Partikel gezeichnet werden? */
ParticleType G_ParticleType = line;
/** Schatten zeichnen? */
int G_DrawShadows = 0;
/** Partikel hinzufügen? */
int G_UpDownKeys[2] = {0,0};
/** Kamer auf einem Partikel? */
int G_ParticleCamera = 0;
/** Position des Partikel in der Liste mit der Kamera */
int G_CameraParticlePos = 0;
/** Verfolgermodus? */
int G_PersecutorParticle = 0;
/** UP-Vektor anzeigen? */
int G_ShowUpVector = 0;
/** FPS */
int G_FPS = 0;
/** FPS counter */
double G_Counter = 0.0-EPS;

/* ------- GETTER / SETTER ------- */

int getFPS(void)
{
	return G_FPS;
}

/**
 * Setzt die Ansicht des Up-Vektors
 */
void toggleShowUpVector (void)
{
	G_ShowUpVector = !G_ShowUpVector;
}

/**
 * Getter für Ansicht des Up-Vektors
 * @return 0 / 1
 */
int getShowUpVector (void)
{
	return G_ShowUpVector;
}

/**
 * Getter für die Position des Partikel mit der Kamera
 */
int getCameraParticlePos() {
    return G_CameraParticlePos;
}

/**
 * Ändert den Verfolger-Modus
 */
void togglePersecutorParticle (void)
{
    G_PersecutorParticle = !G_PersecutorParticle;
}

/**
 * Ändert den Kameramodus.
 */
void toggleParticleCamera (void)
{
    G_ParticleCamera = !G_ParticleCamera;
}

/**
 * Ob der Verfolgermodus gesetzt ist
 */
int getParticleCamera (void)
{
    return G_ParticleCamera;
}

void startMovingBall(void)
{
	G_BallMoving = G_BallMoving == 0 ? 1 : 0;
}

/**
 * Setzt, ob ein Up/Down-Key gedrückt ist.
 * key == 0 = down
 * key == 1 = up
 * value = gesetzt/nicht gesetzt.
 */
void setKey (int key, int value)
{
    if (key < 2)
        G_UpDownKeys[key] = value;
}

/**
 * Ob Schatten gezeichnet werden sollen, oder nicht.
 */
void toggleShadows(void)
{
	G_DrawShadows = !G_DrawShadows;
}

/**
 * Ob Schatten gezeichnet werden sollen, oder nicht.
 */
int getDrawShadows(void)
{
	return G_DrawShadows;
}

/**
 * Ändert den Typ der Partikel
 */
void toggleParticleType (void)
{
	if (G_ParticleType + 1 > sphere)
		G_ParticleType = 0;
	else 
		G_ParticleType++;
}

/**
 * Welcher Typ die Partikel sind
 */
ParticleType getParticleType (void)
{
	return G_ParticleType;
}

/**
 * Ob die Partikel sich bewegen oder nicht.
 */
void toggleParticleFreeze (void)
{
	G_ParticleFreeze = !G_ParticleFreeze;
	if (G_SpheresMoving)
		G_SpheresMoving = 0;
}

/**
 * Gibt eine Sphere zurück.
 */
Spheres * getSphereList (void) 
{
	return G_Spheres;
}

/**
 * Gibt eine Sphere zurück.
 */
Quads * getQuadList (void) 
{
	return G_Quads;
}

/**
 * Ändert den Wert des Boolean, ob sich die Kugeln bewegen dürfen.
 */
void toggleSpheresMoving (void)
{
	G_SpheresMoving = !G_SpheresMoving;
}

/**
 * Get-Function für den Status des Lichts
 * @return Status des Lichts
 */
InitType getLightStatus() {
    return G_Light;
}

/**
 * Set-Function für den Status des Lichts
 * @param Status des Lichts
 */
void setLightStatus(InitType state) {
    G_Light = state;
}

void toggleLight (void)
{
	G_Light = !G_Light;
}

/**
 * Get-Function für den Status der Hilfe
 * @return Status der Hilfe
 */
InitType getHelpStatus() {
    return G_Help;
}

/**
 * Set-Function für den Status der Hilfe
 * @param Status der Hilfe
 */
void setHelpStatus(InitType state) {
    G_Help = state;
}

/**
 * Get-Function für den Status der Texturen
 * @return Status der Texturen
 */
InitType getTextureStatus() {
    return G_Texture;
}

/**
 * Set-Function für den Status der Textur
 * @param Status der Textur
 */
void setTextureStatus(InitType state) {
    G_Texture = state;
}

/**
 * Set-Function für den Status der Maus
 * @param Status der Maus
 */
void setMouseEvent(MouseInterpretType state,int x, int y) {
    G_MouseMove[0] = 0.0;
    G_MouseMove[2] = 0.0;
    G_LastMouseCenter[0] = x;
    G_LastMouseCenter[2] = y;
    
    
    G_Mouse = state;
}

/**
 * Get-Function für den Status der Maus
 * @return Status der Maus
 */
MouseInterpretType getMouseEvent() {
    return G_Mouse;
}

/**
 * Gibt die Kamerakoordinate zurück.
 */
double getCameraPosition (int axis)
{
    if (axis >= 0 && axis < 3)
        return G_CameraPosition[axis];
        
    return 0.0;
}



/**
 * Erhöht die Größe der Unterteilungen um den Faktor 2
 */
void incQuadCount() {
    if (G_QuadCount < 9)
        ++G_QuadCount;
}

/**
 * Verkleinert die Größe der Unterteilungen um den Divisor 2
 */
void decQuadCount() {
    if (G_QuadCount > 0)
        --G_QuadCount;
}

/**
 * Rekursionstiefe für die Bodenfläche
 */
int getQuadCount() {
    return G_QuadCount;
}

/**
 * Bewegt die Kamera auf einem Kugelradius um den Szenenmittelpunkt.
 */
void setCameraMovement(int x,int y)
{
	CGVector3D tmp;
	double factor, radius = vectorLength3D(G_CameraPosition);
	
	tmp[0] = G_CameraPosition[0];
	tmp[1] = G_CameraPosition[1];
	tmp[2] = G_CameraPosition[2];
	
	G_MouseMove[0] = x-G_LastMouseCenter[0];
	G_MouseMove[2] = y-G_LastMouseCenter[2];
	
	G_LastMouseCenter[0] = x;
	G_LastMouseCenter[2] = y;
	
	/* Bewegung um Y-Achse: */
	G_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];
	G_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];
	
	/* Bewegung oben/unten */
	G_CameraPosition[1] += G_MouseMove[2]/(CAMERA_MOVEMENT_SPEED/2)*(vectorLength3D(G_CameraPosition)/100.0);
	factor = 1.0 / (vectorLength3D(G_CameraPosition) / radius);
	multiplyVectorScalar (G_CameraPosition, factor, &G_CameraPosition);
		
}

/**
 * Verlängert/verkürzt den Vektor zur Kamera.
 */
void setCameraZoom(int x,int y)
{
	double factor = 1.0 + (CAMERA_ZOOM_SPEED / 1000.0) * ((G_MouseMove[2] < 0.0) ? -1.0 : 1.0);
	
	G_MouseMove[0] = x-G_LastMouseCenter[0];
	G_MouseMove[2] = y-G_LastMouseCenter[2];
	
	G_LastMouseCenter[0] = x;
	G_LastMouseCenter[2] = y;
	
	G_CameraPosition[0] *= factor;
	G_CameraPosition[1] *= factor;
	G_CameraPosition[2] *= factor;
}

/* ------- BERECHNUNGEN ------- */

/**
 * Berechnet die Bewegung der Kugeln
 * @param interval - Zeit
 */
void moveSpheres (double interval)
{
	int i;
	
	for (i=0;i<SPHERE_CNT && G_BallMoving;i++)
	{
		Spheres s = getSphereList()[i];
	
		s->pos[0] += SPHERE_MOVE_SPEED*interval;
		s->pos[1] += 0.0;
		s->pos[2] += 0.0;
		
	}
}

/**
 * Berechnet alle Funktionen, die vom interval abhängig sind
 * @param interval - Zeit
 */
void calcTimeRelatedStuff (double interval)
{
    moveSpheres(interval);
	
	if (!G_ParticleFreeze)
    {
        calcWaterAttributes(interval);
    }
    
    /* Keine Partikel hinzufügen oder löschen! */
    /*
    if (G_UpDownKeys[0])
    {
		for (i=0;i<100;i++) {
			deleteParticle ();
		}
    } else if (G_UpDownKeys[1]) {
		for (i=0;i<100;i++) {
			addParticle ();
		}
    }
    */
    
    G_Counter += interval;
    
    if (G_Counter >= 1.0)
		G_Counter = 0.0 -EPS;
    
    if (G_Counter <= 0.0)
		G_FPS = (int) 1.0/interval;
}

/**
 * Berechnet anhand der Rekursionstiefe die Anzahl der Quadrate auf dem Boden
 * @param p1,p2,p3,p4 - Die Ecken des Quadrats
 * @param rek - Rekursionstiefe
 * @param color - die Farbe der Quadrate
 * 
 */
void drawRecursiveQuad(CGPoint3f p1, CGPoint3f p2, CGPoint3f p3, CGPoint3f p4, int rek, int color)
{
    CGPoint3f middle0 = {0.0,0.0,0.0},
              middle1 = {0.0,0.0,0.0},
              middle2 = {0.0,0.0,0.0},
              middle3 = {0.0,0.0,0.0},
              center = {0.0,0.0,0.0};

    center[0] = (p1[0] + p3[0]) / 2;
    center[2] = (p1[2] + p3[2]) / 2;

    middle0[0] = (p1[0] + p2[0]) / 2;
    middle0[2] = (p1[2] + p2[2]) / 2;

    middle1[0] = (p2[0] + p3[0]) / 2;
    middle1[2] = (p2[2] + p3[2]) / 2;

    middle2[0] = (p3[0] + p4[0]) / 2;
    middle2[2] = (p3[2] + p4[2]) / 2;


    middle3[0] = (p4[0] + p1[0]) / 2;
    middle3[2] = (p4[2] + p1[2]) / 2;

    if (rek > 0)
    {
      drawRecursiveQuad(center,middle0,p2,middle1, rek-1, color);
      drawRecursiveQuad(center,middle1,p3,middle2, rek-1, !color);
      drawRecursiveQuad(center,middle2,p4,middle3, rek-1, color);
      drawRecursiveQuad(center,middle3,p1,middle0, rek-1, !color);


    } else {
        drawVertex(p4,p3,p2,p1, color);
    }
}

/* ------- INIT ------- */

/**
 * Initialisiert die Kamera.
 */
void initCameraPosition ()
{
    G_CameraPosition[0] = CAMERA_X;
    G_CameraPosition[1] = CAMERA_Y;
    G_CameraPosition[2] = CAMERA_Z;
}

/**
 * Initialisiert die Kugeln.
 */
void initSpheres(void)
{
	int i;
	G_Spheres = malloc (sizeof(*G_Spheres) * SPHERE_CNT);
	
	for (i=0;i<SPHERE_CNT;i++) 
	{
		
		Spheres sphere = malloc (sizeof(**G_Spheres));
		
        sphere->interpolatedPoints = NULL;
        sphere->interpolatedPointsAll = NULL;
        sphere->controlPoints = NULL;
        sphere->t = 0.0;
        
		sphere->pos[0] = rand() % (int)WORLD_SIZE/2 - rand() % (int)WORLD_SIZE/2+150;
		sphere->pos[1] = GROUND_HEIGHT-WORLD_SIZE/2.0+0.1 + SPHERE_R + 10;
		sphere->pos[2] = rand() % (int)WORLD_SIZE/2 - rand() % (int)WORLD_SIZE/2;
		
		sphere->newPos[0] = 0.0;
		sphere->newPos[1] = 0.0;
		sphere->newPos[2] = 0.0;
		
		sphere->color[0] = rand()%255;
		sphere->color[1] = rand()%255;
		sphere->color[2] = rand()%255;
		
		G_Spheres[i] = sphere;
	}
}

/**
 * Initialisiert die Quads.
 */
void initQuads(void)
{
	int i;
	G_Quads = malloc (sizeof(*G_Quads) * QUAD_CNT);
	
	for (i=0;i<QUAD_CNT;i++) 
	{
		
		Quads quads = malloc (sizeof(**G_Quads));
		
		quads->pos[0] = -40;
		quads->pos[1] = GROUND_HEIGHT-WORLD_SIZE/2.0+0.1+QUAD_SIDE/2 ;
		quads->pos[2] = -40;
		
		G_Quads[i] = quads;
	}
}

/**
 * Hier findet die komplette Initialisierung des kompletten SPIEeles statt.
 * Inklusive der Datenhaltung und des SPIEelfeldes.
 */
void initGame ()
{   
    initCameraPosition();
    initTerrain();
    initWater();
    calcFixWaterPoints(getTerrainList());
    /*setRandomize();*/
}



================================================
FILE: src/logic.h
================================================
#ifndef __LOGIC_H__
#define __LOGIC_H__
#define __DEBUG_GL_H__
/**
 * @file
 * Programmlogik und Datenhaltung
 *
 * @author Maurice Tollmien
 */

/* ---- System Header einbinden ---- */
#ifdef WIN32
#include <windows.h>
#endif

#ifdef MACOSX
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif

#include <stdio.h>
#include <stdarg.h>
#include "types.h"

/* eig. Funktionen */

/* ------- GETTER / SETTER ------- */
InitType getLightStatus(void);
void setLightStatus(InitType state);
InitType getHelpStatus(void);
void setHelpStatus(InitType state);
InitType getTextureStatus(void);
void setTextureStatus(InitType state);
void setMouseEvent(MouseInterpretType state,int x, int y);
MouseInterpretType getMouseEvent(void);
double getCameraPosition (int axis);
int getTextureSize(void);
void setCameraMovement(int x,int y);
void setCameraZoom(int x,int y);
void toggleLight (void);
Spheres * getSphereList (void);
void incQuadCount();
void decQuadCount();
int getQuadCount();
void toggleSpheresMoving (void);
int getTextureCount();
void nextTexture();
Particle * getParticleList (void);
int getParticleCnt (void);
void toggleParticleFreeze (void);
void toggleParticleType (void);
ParticleType getParticleType (void);
void toggleShadows(void);
int getDrawShadows(void);
void setKey (int key, int value);
void toggleParticleCamera (void);
void togglePersecutorParticle (void);
int getParticleCamera (void);
void nextCameraParticle();
int getCameraParticlePos();
Particle getCameraParticle (void);
int getShowUpVector (void);
void toggleShowUpVector (void);
int getFPS(void);
void startMovingBall(void);

Quads * getQuadList (void);

/* ------- BERECHNUNGEN ------- */
void moveCamera(int x, int y);
void zoomCamera(int x, int y);
void calcTimeRelatedStuff (double interval);
void drawRecursiveQuad(CGPoint3f p1, CGPoint3f p2, CGPoint3f p3, CGPoint3f p4, int rek, int color);
/* ------- INIT ------- */

void initGame ();



#endif


================================================
FILE: src/main.c
================================================
/**
 * @file
 * ein erster Versuch, eine eigene Datei zu erstellen...
 * @author Maurice Tollmien.
 */

/* ---- System Header einbinden ---- */
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdarg.h>
#include <time.h>

#ifdef MACOSX
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

#ifdef WIN32
#include <windows.h>
#endif

/* ---- Eigene Header einbinden ---- */
#include "io.h"
#include "scene.h" 
#include "types.h"



/**
 * Hauptprogramm.
 * Initialisiert Fenster, Anwendung und Callbacks, startet glutMainLoop.
 * @param argc Anzahl der Kommandozeilenparameter (In).
 * @param argv Kommandozeilenparameter (In).
 * @return Rueckgabewert im Fehlerfall ungleich Null.
 */
int
main (int argc, char **argv)
{
	srand (time (0));
	if (!initAndStartIO ("nen Programm", 1080, 1080))
	{
		fprintf (stderr, "Initialisierung fehlgeschlagen!\n");
		return 1;
	} 
	return 0;
}


================================================
FILE: src/particle.c
================================================


/**
 * @file
 * Hier ist die Datenhaltung und Programmlogik
 *
 * @author Tilman Nedele, Maurice Tollmien
 */

/* ---- System Header einbinden ---- */
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>

#ifdef MACOSX
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

/* ---- Eigene Header einbinden ---- */
#include "particle.h"
#include "logic.h"
#include "vector.h"
#include "types.h"

/** Globale Variablen */

/** Liste mit Partikeln */
Particle * G_Particles;
/** Anzahl der Partikel */
int G_ParticleCnt = PARTICLE_CNT;

/** Init-Wert der Länge der Feder ohne Dehnung */
double G_StructureSpringLengthInit;
double G_SheerSpringLengthInit;
double G_BendingSpringLengthInit;


/**
 * Gibt die Liste mit Partikeln zurück
 */
Particle * getParticleList (void)
{
	return G_Particles;
}

/**
 * Getter für ein Partikel an der Position i
 * @return das Partikel
 */
Particle getParticleAt(int i)
{
	return G_Particles[i];
}

/**
 * Gibt die Anzahl der Partikel zurück.
 */
int getParticleCnt (void)
{
	return G_ParticleCnt;
}

/**
 * Setzt die Partikelanzahl
 */
void setParticleCnt (int i)
{
    G_ParticleCnt = i;
}

void calcSpringForce (Particle p1, Particle p2, double initLength, double k, CGVector3D * res)
{
	CGVector3D tmp = {0.0,0.0,0.0};
	double len = 0.0;
	
	/* Tatsächlicher Abstand beider Punkte */
	subtractVectorVector (p1->s, p2->s, &tmp);
	/* Länge des Abstandes */
	len  = vectorLength3D (tmp);
	/* Bildung des Einheitsvektors in die Richtung der Kraft */
	divideVectorScalar (tmp, len, &tmp);
	/* Abweichung der Initialen Länge berechnen */
	len  = len - initLength;
	
	if (abs(len) < EPS_LEN) 
		len = 0.0;
	
	/* Abweichung mit Federkonstante multiplizieren */
	multiplyVectorScalar (tmp, len * -k, &tmp);
	
	if (vectorLength3D(tmp) <= EPS_F) 
		multiplyVectorScalar (tmp, 0, &tmp);
		
	/* NEU! */
	if (vectorLength3D(tmp) > MAX_F) {
		multiplyVectorScalar (tmp, 0.0001, &tmp);
	}
	
		
	multiplyVectorScalar (tmp, -1, &tmp);
		
	(*res)[0] = tmp[0];
	(*res)[1] = tmp[1];
	(*res)[2] = tmp[2];
	
}

void correctConcreteParticleSymmetric (Particle p, Particle p2, double initValue)
{
	CGVector3D tmp = {0.0,0.0,0.0};
	double len, tooMuch;
	double moveLen;
	
	subtractVectorVector (p->s, p2->s, &tmp);	
	len = vectorLength3D (tmp);
	
	tooMuch = 1.0 - (len / initValue);

	/* Grenze überschritten! Feder zu lang oder kurz! */
	if ((double)(abs(tooMuch * 1000.0)/1000.0) > SPRING_EXPANSION_MAX) {
		if (len > initValue) {
			moveLen = initValue * SPRING_EXPANSION_MAX + initValue;
		} else {
			moveLen = -initValue * SPRING_EXPANSION_MAX + initValue;
		}

		/* Wenn der Vektor verkürzt werden soll, ist das Ergebnis positiv! */
		moveLen = (len - moveLen) / 2.0;
			
		/* normierter Richtungsvektor in Richtung des Partikels p */
		divideVectorScalar (tmp, len, &tmp);
		
		/* Vektor zeigt Richtung Partikel p, wenn er verkürzt werden soll! */
		multiplyVectorScalar (tmp, moveLen, &tmp);
		
		addVectorVector (p2->s, tmp, &(p2->s));
		multiplyVectorScalar (tmp, -1, &tmp);
		addVectorVector (p->s, tmp, &p->s);		
	}
	
}
 
void correctConcreteParticleP2 (Particle p, Particle p2, double initValue)
{
	CGVector3D tmp = {0.0,0.0,0.0};
	double len, tooMuch;
	double moveLen;
	
	subtractVectorVector (p->s, p2->s, &tmp);	
	len = vectorLength3D (tmp);
	
	tooMuch = 1.0 - (len / initValue);
	/* Grenze überschritten! Feder zu lang oder kurz! */
	if ((double)(abs(tooMuch * 1000.0)/1000.0) > SPRING_EXPANSION_MAX) {
		if (len > initValue) {
			moveLen = initValue * SPRING_EXPANSION_MAX + initValue;
		} else {
			moveLen = -initValue * SPRING_EXPANSION_MAX + initValue;
		}
		
		/* Wenn der Vektor verkürzt werden soll, ist das Ergebnis positiv! */
		moveLen = len - moveLen;
			
		/* normierter Richtungsvektor in Richtung des Partikels p */
		divideVectorScalar (tmp, len, &tmp);
		
		/* Vektor zeigt Richtung Partikel p, wenn er verkürzt werden soll! */
		multiplyVectorScalar (tmp, moveLen, &tmp);
		
		addVectorVector (p2->s, tmp, &(p2->s));
	}
	
}
 
void correctSpringLengthPosition(Particle p, int i, int j)
{
	int sqrtLen = (int)(sqrt(G_ParticleCnt)+0.5);
	
	/** ================== STRUKTURFEDERN ===================== */
	if (1) {
		/* Untere Feder */
		if (i > 0) {				
			/*Particle p2 = G_Particles[(i-1)*sqrtLen+j];
			correctConcreteParticleSymmetric (p, p2, G_StructureSpringLengthInit);*/
		}
		
		/* Obere Feder */
		if (i < sqrtLen-1) {		
			Particle p2 = G_Particles[(i+1)*sqrtLen+j];		
			
			if ((i == sqrtLen-2 && j == sqrtLen-1) || (i == sqrtLen-2 && j == 0)) {
				correctConcreteParticleP2(p2, p, G_StructureSpringLengthInit);
			} else {
				correctConcreteParticleSymmetric (p, p2, G_StructureSpringLengthInit);
			}
		}
		
		/* Rechte Feder */
		if (j < sqrtLen-1) {
			Particle p2 = G_Particles[i*sqrtLen+(j+1)];		
			correctConcreteParticleSymmetric (p, p2, G_StructureSpringLengthInit);
			/*if (i == sqrtLen-1 && j == sqrtLen-2) {
				correctConcreteParticleP2(p2, p, G_StructureSpringLengthInit);
			} else {
				correctConcreteParticleSymmetric (p, p2, G_StructureSpringLengthInit);
			}*/
		}
		
		/* Linke Feder */
		if (j > 0) {
			Particle p2 = G_Particles[i*sqrtLen+(j-1)];		
			correctConcreteParticleSymmetric (p, p2, G_StructureSpringLengthInit);
			/*if (i == sqrtLen-1 && j == 1) {
				correctConcreteParticleP2(p2, p, G_StructureSpringLengthInit);
			} else {
				correctConcreteParticleSymmetric (p, p2, G_StructureSpringLengthInit);
			}*/
		}
	}
	
	/** ==================== SCHERFEDERN ====================== */	
	
	if (1) {
		
		/* Links oben */
		if (i < sqrtLen-1 && j > 0) {					
			Particle p2 = G_Particles[(i+1)*sqrtLen+(j-1)];
			
			if (i == sqrtLen-2 && j == 1) {
				correctConcreteParticleP2(p2, p, G_SheerSpringLengthInit);	
			} else {
				correctConcreteParticleSymmetric (p, p2, G_SheerSpringLengthInit);
			}
		}
		
		/* Rechts oben */
		if (i < sqrtLen-1 && j < sqrtLen-1) {					
			Particle p2 = G_Particles[(i+1)*sqrtLen+(j+1)];
			
			if (i == sqrtLen-2 && j == sqrtLen-2) {
				correctConcreteParticleP2(p2, p, G_SheerSpringLengthInit);
			} else {
				correctConcreteParticleSymmetric (p, p2, G_SheerSpringLengthInit);
			}
		}
		
		if (i > 0 && j > 0) {					
			Particle p2 = G_Particles[(i-1)*sqrtLen+(j-1)];
			correctConcreteParticleSymmetric (p, p2, G_SheerSpringLengthInit);
		}
		
		if (i > 0 && j < sqrtLen-1) {					
			Particle p2 = G_Particles[(i-1)*sqrtLen+(j+1)];
			correctConcreteParticleSymmetric (p, p2, G_SheerSpringLengthInit);
		}
		
		
	}

}

double calcWindForce (CGVector3D va, CGVector3D vb, CGVector3D vc, CGVector3D wind) {
	CGVector3D a = {0.0,0.0,0.0};
	CGVector3D b = {0.0,0.0,0.0};
	CGVector3D c = {0.0,0.0,0.0};
	CGVector3D norm = {0.0,0.0,0.0};
	double la, lb, lc, s, f;
	
	subtractVectorVector (vb, va, &a);
	subtractVectorVector (vc, vb, &b);
	subtractVectorVector (va, vc, &c);
	
	la = vectorLength3D (a);
	lb = vectorLength3D (b);
	lc = vectorLength3D (c);
	
	s = (la + lb + lc ) / 2.0;
	
	f = sqrt (s * (s-la) * (s-lb) * (s-lc));
	
	crossProduct3D (norm, a, b);
	
	return scalarProduct (norm, wind) * f * WIND_FORCE;
	
}

/**
 * Berechnet mitHilfe von Euler die neuen Attribute der Partikel
 * 
 * @param spheres - Liste aller Kugeln
 * @param sphereCnt - Anzahl aller Kugeln
 * @param interval - Zeit
 * @param persecutorParticleMode - Verfolgermodus
 */
void calcParticleAttributesEuler (Spheres * spheres, int sphereCnt, double interval,int persecutorParticleMode, int cameraParticlePos)
{
	int i,j,k;
	int sqrtLen = (int)(sqrt(G_ParticleCnt)+0.5);
		
	for (i=0;i<sqrtLen;i++) {
		
		for (j=0;j<sqrtLen;j++) {
		
			Particle p = G_Particles[i*sqrtLen +j];
			CGVector3D tmp = {0.0,0.0,0.0};
			CGVector3D fComplete = {0.0,0.0,0.0};
			CGVector3D fInt = {0.0,0.0,0.0};
			CGVector3D fIntNeighbours = {0.0,0.0,0.0};
			CGVector3D fWindForce = {0.0,0.0,0.0};
			CGVector3D fExt = {0.0,G,0.0};
			double factor = 1.0;
			CGVector3D wind = WIND_DIR;
			CGVector3D tmp2 = {0.0,0.0,0.0};
		
		
			/* Tuch an zwei Ecken aufhängen. */
			if (!(i >= sqrtLen-2 /*   || (i == sqrtLen-1 && j == sqrtLen-1) || (i == sqrtLen-1 && j == 0)  */  )) {
				
				
				
				/** ================== STRUKTURFEDERN ===================== */
				
				/* Linke Feder */
				if (i > 0) {					
					calcSpringForce (G_Particles[(i-1)*sqrtLen+j], p, G_StructureSpringLengthInit, K_STRUCTURE, &tmp);	
					addVectorVector (fInt, tmp, &fInt);
					
					divideVectorScalar (G_Particles[(i-1)*sqrtLen+j]->f, 5, &tmp);
					addVectorVector (fIntNeighbours, tmp, &fIntNeighbours);
				}
				
				/* Rechte Feder */
				if (i < sqrtLen-1) {
					calcSpringForce (G_Particles[(i+1)*sqrtLen+j], p, G_StructureSpringLengthInit, K_STRUCTURE, &tmp);
					addVectorVector (fInt, tmp, &fInt);
					
					divideVectorScalar (G_Particles[(i+1)*sqrtLen+j]->f, 5, &tmp);
					addVectorVector (fIntNeighbours, tmp, &fIntNeighbours);
				}
				
				/* Untere Feder */
				if (j > 0) {
					calcSpringForce (G_Particles[i*sqrtLen+(j-1)], p, G_StructureSpringLengthInit, K_STRUCTURE, &tmp);
					addVectorVector (fInt, tmp, &fInt);
					
					divideVectorScalar (G_Particles[i*sqrtLen+(j-1)]->f, 5, &tmp);
					addVectorVector (fIntNeighbours, tmp, &fIntNeighbours);
				}
				
				/* Obere Feder */
				if (j < sqrtLen-1) {
					calcSpringForce (G_Particles[i*sqrtLen+(j+1)], p, G_StructureSpringLengthInit, K_STRUCTURE, &tmp);
					addVectorVector (fInt, tmp, &fInt);
					
					divideVectorScalar (G_Particles[i*sqrtLen+(j+1)]->f, 5, &tmp);
					addVectorVector (fIntNeighbours, tmp, &fIntNeighbours);
				}
				
				/** ==================== SCHERFEDERN ====================== */
				
				/* Links unten */
				if (i > 0 && j > 0) {					
					calcSpringForce (G_Particles[(i-1)*sqrtLen+(j-1)], p, G_SheerSpringLengthInit, K_SHEER, &tmp);		
					addVectorVector (fInt, tmp, &fInt);
				}
				
				if (i > 0 && j < sqrtLen-1) {					
					calcSpringForce (G_Particles[(i-1)*sqrtLen+(j+1)], p, G_SheerSpringLengthInit, K_SHEER, &tmp);		
					addVectorVector (fInt, tmp, &fInt);
				}
				
				if (i < sqrtLen-1 && j > 0) {					
					calcSpringForce (G_Particles[(i+1)*sqrtLen+(j-1)], p, G_SheerSpringLengthInit, K_SHEER, &tmp);
					addVectorVector (fInt, tmp, &fInt);
				}
				
				if (i < sqrtLen-1 && j < sqrtLen-1) {					
					calcSpringForce (G_Particles[(i+1)*sqrtLen+(j+1)], p, G_SheerSpringLengthInit, K_SHEER, &tmp);	
					addVectorVector (fInt, tmp, &fInt);
				}
				
				/** ================== BEUGUNGSFEDERN ===================== */
				
				if (i > 1) {					
					calcSpringForce (G_Particles[(i-2)*sqrtLen+j], p, G_BendingSpringLengthInit, K_BEND, &tmp);	
					addVectorVector (fInt, tmp, &fInt);
				}
				
				if (i < sqrtLen-2) {
					calcSpringForce (G_Particles[(i+2)*sqrtLen+j], p, G_BendingSpringLengthInit, K_BEND, &tmp);
					addVectorVector (fInt, tmp, &fInt);
				}
				
				if (j > 1) {
					calcSpringForce (G_Particles[i*sqrtLen+(j-2)], p, G_BendingSpringLengthInit, K_BEND, &tmp);
					addVectorVector (fInt, tmp, &fInt);
				}
				
				if (j < sqrtLen-2) {
					calcSpringForce (G_Particles[i*sqrtLen+(j+2)], p, G_BendingSpringLengthInit, K_BEND, &tmp);
					addVectorVector (fInt, tmp, &fInt);
				}
				
				/*divideVectorScalar (fInt, 5, &fInt);
				addVectorVector (fInt, fIntNeighbours, &fInt);*/
				
				if (vectorLength3D(fInt) <= F_MIN) {
					multiplyVectorScalar (fInt, 0, &fInt);
				}
				
				p->f[0] = fInt[0];
				p->f[1] = fInt[1];
				p->f[2] = fInt[2];
				
				/* Kollision mit Wind :-) */						
				if (i == 0 || i == sqrtLen-1) {
					factor *= WIND_EDGE_FACTOR;
				}
				
				if (j == 0 || j == sqrtLen-1) {
					factor *= WIND_EDGE_FACTOR;
				}
					
				if (i > 0) {
					if (j > 0) {
						/* 8 */
						multiplyVectorScalar (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);
						addVectorVector (fWindForce, tmp2, &fWindForce);
						/* 1 */
						multiplyVectorScalar (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);
						addVectorVector (fWindForce, tmp2, &fWindForce);
					}
					if (j < sqrtLen-1) {
						/* 2 */
						multiplyVectorScalar (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);
						addVectorVector (fWindForce, tmp2, &fWindForce);
						/* 3 */
						multiplyVectorScalar (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);
						addVectorVector (fWindForce, tmp2, &fWindForce);
					}
				}
				
				if (i < sqrtLen-1) {
					if (j < sqrtLen-1) {
						/* 4 */
						multiplyVectorScalar (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);
						addVectorVector (fWindForce, tmp2, &fWindForce);
						/* 5 */
						multiplyVectorScalar (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);
						addVectorVector (fWindForce, tmp2, &fWindForce);
					}
					if (j > 0) {
						/* 6 */
						multiplyVectorScalar (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);
						addVectorVector (fWindForce, tmp2, &fWindForce);
						/* 7 */
						multiplyVectorScalar (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);
						addVectorVector (fWindForce, tmp2, &fWindForce);
					}
				}
				
				multiplyVectorScalar (fWindForce, factor, &fWindForce);
				
				/* Kräfte */
				addVectorVector (fInt, fExt, &fComplete);
				addVectorVector (fComplete, fWindForce, &fComplete);
				
				/* Beschleunigung */
				p->a[0] = (-LAMDA * p->v[0] + fComplete[0]) / p->m;
				p->a[1] = (-LAMDA * p->v[1] + fComplete[1]) / p->m;
				p->a[2] = (-LAMDA * p->v[2] + fComplete[2]) / p->m;
				
				/* Geschwindigkeit */
				multiplyVectorScalar (p->a, interval, &tmp);
				addVectorVector (p->v, tmp, &p->v);
				
				if (vectorLength3D(p->v) > MAX_V) {
					/*printf ("V = %f\n", vectorLength3D(p->v));*/
					divideVectorScalar (p->v, vectorLength3D(p->v), &(p->v));
					multiplyVectorScalar(p->v, MAX_V, &(p->v));
				}
				
				/* Ort */
				multiplyVectorScalar (p->v, interval, &tmp);
				addVectorVector (p->s, tmp, &p->s);
				
				/* Up */
				crossProduct3D (tmp, p->v, p->a);
				crossProduct3D (tmp, tmp, p->v);
				
				if (vectorLength3D(tmp) > 0.1)
				{
					p->up[0] = tmp[0];
					p->up[1] = tmp[1];
					p->up[2] = tmp[2];
				}
				
				/* Eventuelle Anpassung der Entfernung zwischen Partikeln, wenn die Feder zu lang oder zu klein wird! */
			
				correctSpringLengthPosition(p, i, j);
				
				/* Kollision mit Boden */
				if (p->s[1] <= -WORLD_SIZE/2.0 + 0.5) {
					p->s[1] = -WORLD_SIZE/2.0 + 0.5;
					multiplyVectorScalar(p->v, 0, &(p->v));
				}
				
				/* Kollision mit Kugel(n) */
				for (k=0;k<SPHERE_CNT;k++) {
					Spheres s = getSphereList()[k];
					double dist = 0.0;
					
					subtractVectorVector(p->s, s->pos, &tmp);
					dist = vectorLength3D(tmp);
					
					if (dist < SPHERE_R+4.5) {
						divideVectorScalar(tmp, dist, &tmp);
						
						multiplyVectorScalar(tmp, SPHERE_R-dist+4.5, &tmp);
						
						addVectorVector(p->s, tmp, &(p->s));
						p->v[0] = 0;
						p->v[1] = 0;
						p->v[2] = 0;
						
					}
					
				}
				
				/* Kollision mit Quad(s) */
				for (k=0;k<QUAD_CNT;k++) {
					Quads s = getQuadList()[k];
					
					if (	p->s[1] <= s->pos[1]+QUAD_SIDE/2+2.5
						&&	p->s[0] <= s->pos[0]+QUAD_SIDE/2+2.5
						&& 	p->s[0] >= s->pos[0]-QUAD_SIDE/2-2.5
						&& 	p->s[2] <= s->pos[2]+QUAD_SIDE/2+2.5
						&& 	p->s[2] >= s->pos[2]-QUAD_SIDE/2-2.5
						) {
							
						p->s[1] = s->pos[1]+QUAD_SIDE/2+2.5;
						multiplyVectorScalar(p->v, 0, &(p->v));
					}	
				}
				
			} else {
				Particle p2 = G_Particles[(i-1)*sqrtLen+j];		
						
				correctConcreteParticleP2(p, p2, G_StructureSpringLengthInit);
				
			}
			
		}
        
	}
	
}


/**
 * Fügt ein Partikel der Liste hinzu.
 */
void addParticle (void)
{
    Particle p = malloc (sizeof(**G_Particles));
    
    G_Particles = realloc (G_Particles, sizeof(*G_Particles) * ++G_ParticleCnt);
    
    p->s[0] = rand()%(int)(5*WORLD_SIZE)/20.0 - rand()%(int)(5*WORLD_SIZE)/20.0;
    p->s[1] = rand()%(int)(5*WORLD_SIZE)/20.0 - rand()%(int)(5*WORLD_SIZE)/20.0;
    p->s[2] = rand()%(int)(5*WORLD_SIZE)/20.0 - rand()%(int)(5*WORLD_SIZE)/20.0;
    
    p->v[0] = 0.1;
    p->v[1] = 0.0;
    p->v[2] = 0.0;
    
    p->a[0] = 0.0;
    p->a[1] = 0.0;
    p->a[2] = 0.0;
    
    p->up[0] = 0.0;
    p->up[1] = 0.0;
    p->up[2] = 0.0;
    
    G_Particles[G_ParticleCnt-1] = p;
}

/**
 * Löscht das letzte Partikel
 */
 void deleteParticle (void)
 {
    if (G_ParticleCnt >= 1) 
    {
        free(G_Particles[G_ParticleCnt-1]);
        G_Particles = realloc (G_Particles, sizeof(*G_Particles) * --G_ParticleCnt);
    }
 }

/**
 * Initialisiert die Partikel.
 */
void initParticles(void)
{
	int i,j;
	G_Particles = malloc (sizeof(*G_Particles) * G_ParticleCnt * G_ParticleCnt);
	
	for (i=0;i<(int)(sqrt(G_ParticleCnt)+0.5);i++) {
		for (j=0;j<(int)(sqrt(G_ParticleCnt)+0.5);j++) {
			
			Particle p = malloc (sizeof(**G_Particles));
			
			p->s[0] = PARTICLE_HEIGHT_INIT ;
			p->s[1] = i/((sqrt(G_ParticleCnt)))*WORLD_SIZE - WORLD_SIZE/2+0;
			p->s[2] = j/((sqrt(G_ParticleCnt)))*WORLD_SIZE - WORLD_SIZE/2;
			
			/*p->s[0] = i/((sqrt(G_ParticleCnt)))*WORLD_SIZE - WORLD_SIZE/2;
			p->s[1] = PARTICLE_HEIGHT_INIT;
			p->s[2] = j/((sqrt(G_ParticleCnt)))*WORLD_SIZE - WORLD_SIZE/2;*/
			
			p->v[0] = 0.0;
			p->v[1] = 0.0;
			p->v[2] = 0.0;
			
			p->a[0] = 0.0;
			p->a[1] = 0.0;
			p->a[2] = 0.0;
			
			p->up[0] = 0.0;
			p->up[1] = 0.0;
			p->up[2] = 0.0;
			
			p->m = PARTICLE_M;
			p->f[0] = 0.0;
			p->f[1] = 0.0;
			p->f[2] = 0.0;
			
			G_Particles[i*(int)(sqrt(G_ParticleCnt)+0.5) +j] = p;
		}
	}
	
	G_StructureSpringLengthInit = abs((i+1)/((sqrt(G_ParticleCnt)))*WORLD_SIZE - i/((sqrt(G_ParticleCnt)))*WORLD_SIZE);
	G_SheerSpringLengthInit = sqrt(pow(G_StructureSpringLengthInit, 2) + pow(G_StructureSpringLengthInit, 2));
	G_BendingSpringLengthInit = 2 * G_StructureSpringLengthInit;
	
	printf ("Strukturfeder-Länge: %f, Scherfeder-Länge: %f, Beugungsfeder-Länge: %f\n", G_StructureSpringLengthInit, G_SheerSpringLengthInit, G_BendingSpringLengthInit);
}






















================================================
FILE: src/particle.h
================================================
#ifndef __PARTICLE_H__
#define __PARTICLE_H__
#define __DEBUG_GL_H__
/**
 * @file
 * Programmlogik und Datenhaltung
 *
 * @author Maurice Tollmien
 */

/* ---- System Header einbinden ---- */
#ifdef WIN32
#include <windows.h>
#endif

#ifdef MACOSX
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif

#include <stdio.h>
#include <stdarg.h>

#include "types.h"

#define PARTICLE_HEIGHT_INIT	40	
#define PARTICLE_CNT	0
#define PARTICLE_LEN	1.0
#define PARTICLE_M		1.0
#define K_WEAK			1.0
#define K_WEAK_INTERPOL	0.05
#define K_V				1.5
#define GAUSS			10000.0
#define CAMERA_PARTICLE_MULT 2.5

Particle * getParticleList (void);
int getParticleCnt (void);
void initParticles(void);
void calcParticleAttributesEuler (Spheres * spheres, int sphereCnt, double interval,int persecutorParticleMode, int cameraParticlePos);
void addParticle (void); 
void deleteParticle (void);
Particle getParticleAt(int i);

#endif


================================================
FILE: src/scene.c
================================================

/**
 * @file
 * Hier wird vll gezeichnet...
 *
 * @author Maurice Tollmien, Tilman Nedele
 */

/* ---- System Header einbinden ---- */
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
#include <string.h>
#include <stringOutput.h>

#ifdef MACOSX
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

#include <GL/glu.h>

/* ---- Eigene Header einbinden ---- */
#include "scene.h"
#include "logic.h"
#include "types.h"
#include "water.h"
#include "terrain.h"
#include "vector.h"


/* ---- Globale Variablen für die Farben der Wände ------ */
float G_R;
float G_G;
float G_B;
float G_Alpha;
float G_Shininess;
int G_Emission;


/* ---- Funktionen ---- */

/**
 * Wird aufgerufen, wenn "h" gedrückt worden ist.
 * Gibt einen Text auf einem schwarzen Hintergrund auf dem Bildschirm aus
 */
void printHelp (void)
{
    /* Textfarbe */
    GLfloat textColor[3] = { 1.0f, 0.5f, 0.5f };

    drawString (0.2f, 0.1f, textColor, HELP_OUTPUT_1);
    drawString (0.2f, 0.125f, textColor, HELP_OUTPUT_2);
    drawString (0.2f, 0.148f, textColor, HELP_OUTPUT_3);
    drawString (0.2f, 0.171f, textColor, HELP_OUTPUT_4);
    drawString (0.2f, 0.194f, textColor, HELP_OUTPUT_5);
    drawString (0.2f, 0.217f, textColor, HELP_OUTPUT_6);
    drawString (0.2f, 0.240f, textColor, HELP_OUTPUT_7);
    drawString (0.2f, 0.263f, textColor, HELP_OUTPUT_8);
    drawString (0.2f, 0.286f, textColor, HELP_OUTPUT_9);
    drawString (0.2f, 0.311f, textColor, HELP_OUTPUT_10);
    drawString (0.2f, 0.336f, textColor, HELP_OUTPUT_11);
    drawString (0.2f, 0.361f, textColor, HELP_OUTPUT_12);
    drawString (0.2f, 0.386f, textColor, HELP_OUTPUT_13);
    drawString (0.2f, 0.411f, textColor, HELP_OUTPUT_14);
    drawString (0.2f, 0.436f, textColor, HELP_OUTPUT_15);
    drawString (0.2f, 0.461f, textColor, HELP_OUTPUT_16);
    drawString (0.2f, 0.486f, textColor, HELP_OUTPUT_17);
    drawString (0.2f, 0.505f, textColor, HELP_OUTPUT_18);
    drawString (0.2f, 0.530f, textColor, HELP_OUTPUT_19);
    drawString (0.2f, 0.555f, textColor, HELP_OUTPUT_20);
    drawString (0.2f, 0.580f, textColor, HELP_OUTPUT_21);
    drawString (0.2f, 0.605f, textColor, HELP_OUTPUT_22);
    drawString (0.2f, 0.630f, textColor, HELP_OUTPUT_23);

}



/**
 * Setzt global eine Farbe!
 * @param color1,color2,color3 - RGB
 * @param alpha
 * @param shininess
 * @param emission
 */
void setColor (float color1, float color2, float color3, float alpha, float shininess, int emission)
{
    float tmp[] = {0.0, 0.0, 0.0};
    tmp[0] = color1;
    tmp[1] = color2;
    tmp[2] = color3;
        
    {
        /* Material */
        float matAmbient[] = {0.0, 0.0, 0.0, 0.0};
        float matBlack[]= {0.0, 0.0, 0.0, 0.0};
        float matDiffuse[] = {0.0, 0.0, 0.0, 0.0};
        float matSpecular[] = {0.0, 0.0, 0.0, 0.0};
        float matShininess[] = { 0.0 };
        
        matShininess[0] = shininess;
        
        matAmbient[0] = tmp[0];
        matAmbient[1] = tmp[1];
        matAmbient[2] = tmp[2];
        matAmbient[3] = alpha;
        
        matSpecular[0] = tmp[0];
        matSpecular[1] = tmp[1];
        matSpecular[2] = tmp[2];
        matSpecular[3] = alpha;
        
        matDiffuse[0] = tmp[0] - 0.7;
        matDiffuse[1] = tmp[1] - 0.7;
        matDiffuse[2] = tmp[2] - 0.7;
        matDiffuse[3] = alpha;

        /* Setzen der Material-Parameter */
        glMaterialfv (GL_FRONT, GL_AMBIENT, matAmbient);
        glMaterialfv (GL_FRONT, GL_DIFFUSE, matDiffuse);
        glMaterialfv (GL_FRONT, GL_SPECULAR, matSpecular);
        glMaterialfv (GL_FRONT, GL_SHININESS, matShininess);
        if (emission)
            glMaterialfv (GL_FRONT, GL_EMISSION, matSpecular);
        else
            glMaterialfv (GL_FRONT, GL_EMISSION, matBlack);
    }
}

/**
 * Zeichnet Kugel mit mehr Parametern.
 * @param sliceCount - Anzahl der Unterteilungen
 * @param r - Radius
 */
void drawSphere (int sliceCount, double r)
{
	GLUquadricObj * body;
    
    body = gluNewQuadric ();
    if (body == NULL)
        exit (1);

    /* Normalen fuer Quadrics berechnen lassen */
    gluQuadricNormals (body, GLU_SMOOTH);
    
    gluSphere (body, r, sliceCount, sliceCount);

    gluDeleteQuadric (body);
}

/**
 * Zeichnet ein Quadrat mit der Kantenlaenge 1, das aus mehreren kleineren
 * Quadraten zusammen gesetzt ist.
 * @param subDivs Anzahl der Unterteilungsschritte der Kanten.
 */
static void
drawSquare (GLint subDivs)
{
  int x, y;

  for (y = 0; y < subDivs + 1; y++)
    {
		glNormal3f (0.0f, 0.0f, 1.0f);
		glBegin (GL_QUAD_STRIP);
		
		for (x = 0; x <= subDivs + 1; x++)
		{
		/* Texturkoordinate,
		gilt nicht, wenn Texturkoordinaten automatisch generiert werden. */
		/*glTexCoord2f (x / (subDivs + 1.0f), y / (subDivs + 1.0f));*/
		glVertex3f (-0.5f + x / (subDivs + 1.0f),
				   0.5f - y / (subDivs + 1.0f),
				   0.0f);

		/* Texturkoordinate,
		gilt nicht, wenn Texturkoordinaten automatisch generiert werden. */
		/*glTexCoord2f (x / (subDivs + 1.0f), (y + 1) / (subDivs + 1.0f));*/
		glVertex3f (-0.5f +    x    / (subDivs + 1.0f),
				   0.5f - (y + 1) / (subDivs + 1.0f),
				   0.0f);
		}
      glEnd ();
    }

}

/**
 * Zeichnet einen Wuerfel mit Kantenlaenge 1.
 * @param subDivs Anzahl der Unterteilungsschritte der Kanten.
 */
static void
drawCube (unsigned int subDivs, GLfloat radius)
{
  /* Frontflaeche */
  glPushMatrix ();
  {
    glTranslatef (0.0f, 0.0f, radius);
    drawSquare (subDivs);
  }
  glPopMatrix ();

  /* rechte Seitenflaeche */
  glPushMatrix ();
  {
    glRotatef (90.0f, 0.0f, 1.0f, 0.0f);
    glTranslatef (0.0f, 0.0f, radius);
    drawSquare (subDivs);
 }
  glPopMatrix ();

  /* Rueckseitenflaeche */
  glPushMatrix ();
  {
    glRotatef (180.0f, 0.0f, 1.0f, 0.0f);
    glTranslatef (0.0f, 0.0f, radius);
    drawSquare (subDivs);
  }
  glPopMatrix ();


  /* linke Seitenflaeche */
  glPushMatrix ();
  {
    glRotatef (270.0f, 0.0f, 1.0f, 0.0f);
    glTranslatef (0.0f, 0.0f, radius);
    drawSquare (subDivs);
  }
  glPopMatrix ();

  /* Deckelflaeche */
  glPushMatrix ();
  {
    glRotatef (-90.0f, 1.0f, 0.0f, 0.0f);
    glTranslatef (0.0f, 0.0f, radius);
    drawSquare (subDivs);
  }
  glPopMatrix ();

  /* Bodenflaeche */
  /*glPushMatrix ();
  {
    glRotatef (90.0f, 1.0f, 0.0f, 0.0f);
    glTranslatef (0.0f, 0.0f, radius);
    drawSquare (subDivs);
  }
  glPopMatrix ();*/
}

/**
 * Zeichnet ein Quadrat mit den Ecken p1,p2,p3,p4 in der Farbe color=1/0
 * @param p1,p2,p3,p4 - Die Ecken
 * @param color - schwarz = 0 / weiß = 1
 */
void drawVertex(CGPoint3f p1, CGPoint3f p2, CGPoint3f p3, CGPoint3f p4, int color)
{
     if (color)
        setColor(1.0,1.0,1.0,G_Alpha,G_Shininess,G_Emission);
    else
        setColor(G_R,G_G,G_B,G_Alpha,G_Shininess,G_Emission);
      glBegin (GL_QUADS);
      {
        glVertex3f(p1[0],p1[1],p1[2]);
        glVertex3f(p2[0],p2[1],p2[2]);
        glVertex3f(p3[0],p3[1],p3[2]);
        glVertex3f(p4[0],p4[1],p4[2]);
      }
      glEnd();
}

/**
 * Zeichnet den Boden
 */
void drawBottom(void)
{
    CGPoint3f p1 = {0.0,GROUND_HEIGHT,0.0},
          p2 = {WORLD_SIZE,GROUND_HEIGHT,0.0},
          p3 = {WORLD_SIZE,GROUND_HEIGHT,WORLD_SIZE},
          p4 = {0.0,GROUND_HEIGHT,WORLD_SIZE};

	
	/*glDisable (GL_DEPTH_TEST);*/
    /*glDisable(GL_CULL_FACE);*/
    
    glPushMatrix ();
    {
        glTranslatef(-(WORLD_SIZE/2), -WORLD_SIZE/2.0+0.1,-(WORLD_SIZE/2));
		/*setColor (0.0, 0.0, 0.0, 1.0, 40, 1);*/
        drawRecursiveQuad(p1,p2,p3,p4,getQuadCount(),0);
    }
    glPopMatrix ();
    
    /*glEnable(GL_CULL_FACE);*/
    /*glEnable (GL_DEPTH_TEST);*/
}

/**
 * Zeichnet die Wände
 */
void drawSides(void) 
{	
	glPushMatrix();
	{
		G_R = 1.0;
		G_G = 0.0;
		G_B = 0.0;
		G_Alpha = 1.0;
		G_Shininess = 40;
		G_Emission = 1;
		glRotatef(90,1,0,0);
		drawBottom();
	}
	glPopMatrix();
	glPushMatrix();
	{
		G_R = 0.0;
		G_G = 1.0;
		G_B = 0.0;
		G_Alpha = 1.0;
		G_Shininess = 40;
		G_Emission = 1;
		glRotatef(90,1,0,0);
		glRotatef(180,0,0,1);
		drawBottom();
	}
	glPopMatrix();
	glPushMatrix();
	{
		G_R = 0.0;
		G_G = 0.0;
		G_B = 1.0;
		G_Alpha = 1.0;
		G_Shininess = 40;
		G_Emission = 1;
		glRotatef(90,1,0,0);
		glRotatef(90,0,0,1);
		drawBottom();
	}
	glPopMatrix();
	glPushMatrix();
	{
		G_R = 0.5;
		G_G = 0.5;
		G_B = 0.5;
		G_Alpha = 1.0;
		G_Shininess = 40;
		G_Emission = 1;
		glRotatef(90,1,0,0);
		glRotatef(90,0,0,-1);
		drawBottom();
	}
	glPopMatrix();
	
	/* Oben! */
	glPushMatrix();
	{
		G_R = 1.0;
		G_G = 1.0;
		G_B = 0.0;
		G_Alpha = 1.0;
		G_Shininess = 40;
		G_Emission = 1;
		glRotatef(180,1,0,0);
		drawBottom();
	}
	glPopMatrix();
	
	/* Unten! */
	glPushMatrix();
	{
		G_R = 0.0;
		G_G = 0.0;
		G_B = 0.0;
		G_Alpha = 1.0;
		G_Shininess = 40;
		G_Emission = 1;
		glRotatef(360,1,0,0);
		drawBottom();
	}
	glPopMatrix();
	
}


/**
 * Zeichnet die Welt
 */
void drawWorld() {


    glDisable(GL_CULL_FACE);
    glPushMatrix();
    {
		setColor (WHITE, 1.0, 30.0, 0);
        /*glTranslatef(0,(30.0f)/2,0);*/
        glScalef(WORLD_SIZE,WORLD_SIZE,WORLD_SIZE);
        drawCube(20,0.5f);
    }
    glPopMatrix();
  glEnable(GL_CULL_FACE);
}

/**
 * Zeichnet die beiden Referenzkugeln
 */
void drawSpheres(void)
{
	int i;
	glEnable(GL_BLEND);
	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	
		for (i=0;i<SPHERE_CNT;i++)
		{
			glPushMatrix();
			{
				Spheres s = getSphereList()[i];
				glTranslatef(s->pos[0],s->pos[1],s->pos[2]);
			
				setColor (s->color[0],s->color[1],s->color[2], SPHERE_TRANSPARENCY, 0.0, 1);
				glCullFace (GL_FRONT);
				drawSphere (SLICE_CNT, SPHERE_R);
				glCullFace (GL_BACK);
				drawSphere (SLICE_CNT, SPHERE_R);
			}
			glPopMatrix();
		}
	
	glDisable (GL_BLEND);
	
}

void drawQuads(void) 
{
	
	int i;
	
	for (i=0;i<QUAD_CNT;i++)
	{
		glPushMatrix();
		{
			Quads s = getQuadList()[i];
			glTranslatef(s->pos[0],s->pos[1],s->pos[2]);
			glScalef(QUAD_SIDE, QUAD_SIDE, QUAD_SIDE);
			
			drawCube (1, 0.5);
			
		}
		glPopMatrix();
	}

}

/**
 * Malt ein übergebenes Partikel in den Ursprung
 */
void drawOneParticle(Particle p, int suspensionPoint)
{  
	if (getParticleType() == sphere) {  
		if (suspensionPoint) 
			setColor (GREEN, 1.0, 0, 1);
		else
			setColor (RED, 1.0, 0, 1);
		
		glPushMatrix();
		{
			glTranslatef(p->s[0],p->s[1],p->s[2]);
			drawSphere (4, 0.8);
		}
		glPopMatrix();
				
		setColor (WHITE, 1.0, 0, 1);
	}
			
}

/**
 * Malt die Normale --> Up-Vektor des Partikels
 */
void drawParticleNormal (Particle p)
{
    
    glBegin (GL_LINES);
    {
        CGVector3D up;
        /*printf ("scene: up: %f, %f, %f\n", p->up[0],p->up[1],p->up[2]);*/
        up[0]=p->up[0];
        up[1]=p->up[1];
        up[2]=p->up[2];
        normVector3D(up);
        glVertex3f(p->s[0],p->s[1],p->s[2]);
        glVertex3f(up[0]+p->s[0],up[1]+p->s[1],up[2]+p->s[2]);
    }
    glEnd ();
}

void drawFPS (void)
{
	GLfloat textColor[3] = { 1.0f, 1.0f, 1.0f };
	char * string = calloc ((strlen ("FPS = ") + 4), sizeof(char));
	sprintf(string, "FPS = %d", getFPS());
	
	drawString (0.6, 0.1, textColor, string);
	
	free (string);
}

void drawWaterSurface(void) 
{
	Water * water = getWaterList();
	int i,j;
	
	/* Punkte anzeigen. */
	glPointSize(1.0);
	for (i=0;i<WORLD_SIZE*WORLD_SIZE;i++) {
		glBegin (GL_POINTS);
			glVertex3f(water[i].x, water[i].y, water[i].z);
		glEnd();
	}
	
	
	
}

void drawTerrainSurface(void)
{
	Terrain * terrain = getTerrainList();
	GLuint * indices = getTerrainIndices();
	int i,j;
	
	/* Punkte anzeigen. */
	if (0) {
		glPointSize(4.0);
		for (i=0;i<TERRAIN_SIZE*TERRAIN_SIZE;i++) {
			glBegin (GL_POINTS);
				glVertex3f(terrain[i].x, terrain[i].y, terrain[i].z);
			glEnd();
		}
	}
	/* Linestrip. */
	if (1) {
		
		for (i=0;i<TERRAIN_SIZE*TERRAIN_SIZE*3*2;i+=3) {
			glBegin(GL_TRIANGLES);
				glVertex3f(terrain[indices[i]].x, terrain[indices[i]].y, terrain[indices[i]].z);
				glVertex3f(terrain[indices[i+1]].x, terrain[indices[i+1]].y, terrain[indices[i+1]].z);
				glVertex3f(terrain[indices[i+2]].x, terrain[indices[i+2]].y, terrain[indices[i+2]].z);
			glEnd();
		}
		
	}
}
	

/**
 * Zeichen-Funktion.
 * Stellt die Szenerie rund um die Rennstrecke dar.
 */
void drawScene (void)
{
    CGPoint4f 	lightPos2 = { 0.0f, 20.0f, 0.0f, 1.0f };
       
    CGPoint4f 	lightPos1 = { 0.0f, 5.0f, 10.0f, 1.0f };
    CGPoint3f 	lightDir1  = { 0.0, -5.0, -10.0 };
    

    glLightfv (GL_LIGHT2, GL_POSITION, lightPos2);

    glLightfv (GL_LIGHT1, GL_POSITION, lightPos1);
    glLightfv (GL_LIGHT1, GL_SPOT_DIRECTION, lightDir1);
	
    setColor (BLACK, 1.0, 0.0, 0);
	
    if (!getHelpStatus()) 
    {
        if (getLightStatus()){
			/*glEnable (GL_LIGHT1);*/
            glEnable (GL_LIGHT2);
        } else {
			glDisable (GL_LIGHT1);
			glDisable (GL_LIGHT2);
        }

        /* Zeichnet den Boden*/
        G_R = 0.0;
		G_G = 0.0;
		G_B = 0.0;
		G_Alpha = 1.0;
		G_Shininess = 40;
		G_Emission = 1;
        drawBottom();
        
        drawSides();
        
        /* Zeichnet die beiden Kugeln */
        drawSpheres();
        
        drawQuads();
                
        /* Zeichnet die Partikel */
        /*drawParticles();
        
        drawParticleCloth();*/
        
        drawWaterSurface();
            
        drawFPS ();
        
                
    } else {
        printHelp();
    }
    
}

/**
 * Initialisierung der Lichtquellen.
 * Setzt Eigenschaften der Lichtquellen (Farbe, Oeffnungswinkel, ...)
 */
static void initLight (void)
{

    /* Farbe der zweiten Lichtquelle */
	CGPoint4f lightColor1[3] =
	{ {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f,
														   1.0f}
	};
    
    /* Farbe der ersten Lichtquelle */
    CGPoint4f lightColor2[3] =
    { {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {1.0f, 1.0f, 1.0f,
                                                           1.0f}
    };
    
	/* Oeffnungswinkel der zweiten Lichtquelle */
	GLdouble lightCutoff1 = 90.0f;
	/* Lichtverteilung im Lichtkegel der zweiten Lichtquelle */
	GLdouble lightExponent1 = 20.0f;
    
    float globalAmbientLight[] = {0.3, 0.3, 0.3, 1.0};
    
    glLightModelfv(GL_LIGHT_MODEL_AMBIENT, globalAmbientLight);
    
    /* Farbe der zweiten Lichtquelle setzen */
	glLightfv (GL_LIGHT1, GL_AMBIENT, lightColor1[0]);
	glLightfv (GL_LIGHT1, GL_DIFFUSE, lightColor1[1]);
	glLightfv (GL_LIGHT1, GL_SPECULAR, lightColor1[2]);
    
    /* Spotlight-Eigenschaften der zweiten Lichtquelle setzen */
	glLightf (GL_LIGHT1, GL_SPOT_CUTOFF, lightCutoff1);
	glLightf (GL_LIGHT1, GL_SPOT_EXPONENT, lightExponent1);
    
    /* Farbe der zweiten Lichtquelle setzen */
	glLightfv (GL_LIGHT2, GL_AMBIENT, lightColor2[0]);
	glLightfv (GL_LIGHT2, GL_DIFFUSE, lightColor2[1]);
	glLightfv (GL_LIGHT2, GL_SPECULAR, lightColor2[2]);
	
	/* Spotlight-Eigenschaften der zweiten Lichtquelle setzen */
	glLightf (GL_LIGHT2, GL_SPOT_CUTOFF, lightCutoff1);
	glLightf (GL_LIGHT2, GL_SPOT_EXPONENT, lightExponent1);
}

/**
 * Bei SPIEelbegin wird das SPIEelfeld komplett initialisiert
 * mit einem Hintergrund, einer Zeichenfarbe, Linienbreite.
 * Außerdem wird die Datenhaltung initialisiert (siehe initField (), initStones ()).
 * @return Ob ein Fehler aufgetreten ist.
 */
int initScene (void)
{
	glEnable (GL_DEPTH_TEST);
	glCullFace (GL_BACK);
	glEnable (GL_CULL_FACE);
	glEnable (GL_NORMALIZE);
	glEnable (GL_LIGHTING);
	initLight ();
	initGame ();

	return 1;
}



/**
 * (De-)aktiviert den Wireframe-Modus.
 */
void
toggleWireframeMode (void)
{
    /* Flag: Wireframe: ja/nein */
    static GLboolean wireframe = GL_FALSE;

    /* Modus wechseln */
    wireframe = !wireframe;

    if (wireframe)
        glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
    else
        glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
}



================================================
FILE: src/scene.h
================================================
#ifndef __SCENE_H__
#define __SCENE_H__

#define __DEBUG_GL_H__
/**
 * @file
 * hier kann gezeichnet werden (Hoffentlich^^)
 *
 * @author Maurice Tollmien
 */

/* ---- System Header einbinden ---- */
#ifdef WIN32
#include <windows.h>
#endif

#ifdef MACOSX
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif

#include <stdio.h>
#include <stdarg.h>
#include "types.h"

void drawVertex(CGPoint3f p1, CGPoint3f p2, CGPoint3f p3, CGPoint3f p4, int color);
void drawScene (void);
void drawWaterSurface(void);
void drawFPS (void);
void drawSides(void);
int initScene (void);
void toggleWireframeMode (void);

#endif


================================================
FILE: src/stringOutput.c
================================================
/**
 * @file
 * Einfache Funktion zum Zeichnen von Text fuer GLUT-Programme.
 */

/* ---- System Header einbinden ---- */
#include <string.h>
#include <stdio.h>
#include <stdarg.h>

#ifdef MACOSX
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

/* ---- Eigene Header einbinden ---- */
#include "stringOutput.h"

/**
 * Zeichnen einer Zeichfolge in den Vordergrund. Gezeichnet wird mit Hilfe von
 * <code>glutBitmapCharacter(...)</code>. Kann wie <code>printf genutzt werden.</code>
 * @param x x-Position des ersten Zeichens 0 bis 1 (In).
 * @param y y-Position des ersten Zeichens 0 bis 1 (In).
 * @param color Textfarbe (In).
 * @param format Formatstring fuer die weiteren Parameter (In).
 */
void
drawString (GLfloat x, GLfloat y, GLfloat * color, char *format, ...)
{

  GLint matrixMode;             /* Zwischenspeicher akt. Matrixmode */
  va_list args;                 /* variabler Teil der Argumente */
  char buffer[255];             /* der formatierte String */
  char *s;                      /* Zeiger/Laufvariable */
  va_start (args, format);
  vsprintf (buffer, format, args);
  va_end (args);

  /* aktuelle Zeichenfarbe (u.a. Werte) sichern */
  glPushAttrib (GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT);

  /* aktuellen Matrixmode speichern */
  glGetIntegerv (GL_MATRIX_MODE, &matrixMode);
  glMatrixMode (GL_PROJECTION);

  /* aktuelle Projektionsmatrix sichern */
  glPushMatrix ();

  /* neue orthogonale 2D-Projektionsmatrix erzeugen */
  glLoadIdentity ();
  gluOrtho2D (0.0, 1.0, 1.0, 0.0);

  glMatrixMode (GL_MODELVIEW);

  /* aktuelle ModelView-Matrix sichern */
  glPushMatrix ();

  /* neue ModelView-Matrix zuruecksetzen */
  glLoadIdentity ();

  /* Tiefentest ausschalten */
  glDisable (GL_DEPTH_TEST);

  /* Licht ausschalten */
  glDisable (GL_LIGHTING);

  /* Nebel ausschalten */
  glDisable (GL_FOG);

  /* Blending ausschalten */
  glDisable (GL_BLEND);

  /* Texturierung ausschalten */
  glDisable (GL_TEXTURE_1D);
  glDisable (GL_TEXTURE_2D);
  /* glDisable (GL_TEXTURE_3D); */

  /* neue Zeichenfarbe einstellen */
  glColor4fv (color);

  /* an uebergebenene Stelle springen */
  glRasterPos2f (x, y);

  /* Zeichenfolge zeichenweise zeichnen */
  for (s = buffer; *s; s++)

    {
      glutBitmapCharacter (GLUT_BITMAP_HELVETICA_18, *s);
    }

  /* alte ModelView-Matrix laden */
  glPopMatrix ();
  glMatrixMode (GL_PROJECTION);

  /* alte Projektionsmatrix laden */
  glPopMatrix ();

  /* alten Matrixmode laden */
  glMatrixMode (matrixMode);

  /* alte Zeichenfarbe und Co. laden */
  glPopAttrib ();
}


================================================
FILE: src/stringOutput.h
================================================
#ifndef _STRING_OUTPUT_H
#define _STRING_OUTPUT_H
/**
 * @file
 * Einfache Funktion zum Zeichnen von Text fuer GLUT-Programme.
 */

/* ---- System Header einbinden ---- */
#ifdef MACOSX
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif

/* ---- Funktionsprototypen ---- */

/**
 * Zeichnen einer Zeichfolge in den Vordergrund. Gezeichnet wird mit Hilfe von
 * <code>glutBitmapCharacter(...)</code>. Kann wie <code>printf genutzt werden.</code>
 * @param x x-Position des ersten Zeichens 0 bis 1 (In).
 * @param y y-Position des ersten Zeichens 0 bis 1 (In).
 * @param color Textfarbe (In).
 * @param format Formatstring fuer die weiteren Parameter (In).
 */
void drawString (GLfloat x, GLfloat y, GLfloat * color, char *format, ...);

#endif


================================================
FILE: src/terrain.c
================================================

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <math.h>
/* ---- Eigene Header einbinden ---- */
#include "terrain.h"
#include "logic.h"
#include "vector.h"
#include "types.h"

Terrain * G_TerrainList;
GLuint * G_TerrainIndices;

Terrain * G_TerrainCaustics;

Terrain * getTerrainList(void){
	return G_TerrainList;
}

Terrain * getTerrainCaustics(void) {
	return G_TerrainCaustics;
}

GLuint * getTerrainIndices (void) 
{
	return G_TerrainIndices;
}

void initTerrainIndices(void) {
	
	int i,j;
	int index = 0;
	for (i=0;i<TERRAIN_SIZE*TERRAIN_SIZE;i++) {		
		int atI = i % TERRAIN_SIZE;
		int atJ = i / TERRAIN_SIZE;
		
		if (atI == TERRAIN_SIZE-1 || atJ == TERRAIN_SIZE-1) {
			continue;
		}
		
		G_TerrainIndices[index]   = i;
		G_TerrainIndices[index+1] = i+1;
		G_TerrainIndices[index+2] = i+TERRAIN_SIZE+1;
		
		G_TerrainIndices[index+3] = i;
		G_TerrainIndices[index+4] = i+TERRAIN_SIZE+1;
		G_TerrainIndices[index+5] = i+TERRAIN_SIZE;
		
		index += 6;
	}
	
}

void calcTerrainNormals(void) {
	int i;
	for (i=0;i<TERRAIN_SIZE*TERRAIN_SIZE;i++) {
		int atI = i % TERRAIN_SIZE;
		int atJ = i / TERRAIN_SIZE;
		
		if (atI < 1 || atI >= TERRAIN_SIZE-1 || atJ < 1 || atJ >= TERRAIN_SIZE-1) {
			continue;
		}
		
		CGVector3D 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};
		CGVector3D 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};
		CGVector3D res1;
		crossProduct3D(res1, v1, v2);
		
		CGVector3D 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};
		CGVector3D 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};
		CGVector3D res2;
		crossProduct3D(res2, v3, v4);
		
		if (res1[1] < 0) {
			multiplyVectorScalar(res1, -1, &res1);
		}
		if (res2[1] < 0) {
			multiplyVectorScalar(res2, -1, &res2);
		}
		CGVector3D normal;
		addVectorVector(res1, res2, &normal);
		
		G_TerrainList[i].nx = normal[0];
		G_TerrainList[i].ny = normal[1];
		G_TerrainList[i].nz = normal[2];
		
		G_TerrainCaustics[i].nx = G_TerrainList[i].nx;
		G_TerrainCaustics[i].ny = G_TerrainList[i].ny;
		G_TerrainCaustics[i].nz = G_TerrainList[i].nz;
		
	}
	
}

/**
 * Kubische Interpolation.
 */
double interpolateCube(double v0, double v1, double v2, double v3, double x) {
	double p = (v3 - v2) - (v0 - v1);
	double q = (v0 - v1) - p;
	double r = v2 - v0;
	double s = v1;
	return p*pow(x, 3) + q*pow(x, 2) + r*x + s;
}

/**
 * Kosinus-Interpolation.
 */
double interpolateCos(double a, double b, double x) {
	double ft = x * 3.1415927;
	double f  = (1 - cos(ft)) * 0.5;
	return a*(1-f) + b*f;
}

/**
 * Erzeugt random-Noise-Wert zwischen 0..1
 */
double noise(int x, int y) {
	long n = x + y * 57;
	n = (n<<13) ^ n;
	return (1.0 - ((n * (n*n*15731 + 789221) + 1376312589) & 0x7fffffff) / 1073741824.0);
}


/**
 * Erzeugt Noise... Etwas angepasst und smoothed.
 */
double smoothedNoise(float x, float y) {
	double corners 	= ( noise(x-1, y-1) + noise(x+1, y-1) + noise(x-1, y+1) + noise(x+1, y+1) ) / 16.0;
	double sides	= ( noise(x-1, y  ) + noise(x+1, y  ) + noise(x  , y-1) + noise(x  , y+1) ) / 8;
	double center	= noise(x,y) / 4;
	return corners + sides + center;
}

/**
 * Interpoliert das errechneten Noise, um perfekte fließende Übergänge zu erreichen (je nach Interpolationsart).
 */
double interpolatedNoise(float x, float y) {
	
	int intX 			= (int)x;
	double fractionalX 	= x - intX;
	int intY			= (int)y;
	double fractionalY 	= y - intY;
	
	double v1 = smoothedNoise (intX		, intY 		);
	double v2 = smoothedNoise (intX + 1	, intY 		);
	double v3 = smoothedNoise (intX		, intY + 1	);
	double v4 = smoothedNoise (intX + 1	, intY + 1	);
	
	double i1 = interpolateCos(v1, v2, fractionalX);
	double i2 = interpolateCos(v3, v4, fractionalX);
	
	return interpolateCos(i1, i2, fractionalY);
}

/**
 * Berechnet einen Perlin-Noise-Wert für eine beliebige Position auf dem Feld!
 */
double perlinNoise2D(float x, float y) {
	double 	total  	= 0.0;
	double 	p 		= PERSISTENCE;
	int 	n		= OCTAVES_COUNT;
	int i;
	
	for (i = 0;i<n;i++) {
		
		double frequency = pow(2, i);
		double amplitude = pow(p, i);
		
		total += interpolatedNoise (x * frequency, y * frequency) * amplitude;
		
	}
	
	return total;
}

double gauss(float x, float y, float offset) {
	float a = 3.0;
	float e = 2.71828182846;
	float spread = 25.0;
	
	x = x + offset;
	y = y + offset;
	
	float term = -(pow(x,2)/(2*spread) + pow(y,2)/(2*spread));
	return -a * pow(e, term);
}

void initTerrain(void) {
	
	int i,j;
	
	double min, max;
	
	G_TerrainList = calloc(TERRAIN_SIZE*TERRAIN_SIZE, sizeof(*G_TerrainList));
	G_TerrainCaustics = calloc(TERRAIN_SIZE*TERRAIN_SIZE, sizeof(*G_TerrainList));
	G_TerrainIndices = calloc(TERRAIN_SIZE*TERRAIN_SIZE*2*3, sizeof(*G_TerrainIndices));

	for (i=0;i<(TERRAIN_SIZE)*(TERRAIN_SIZE);i++) {
		int xCoord = i / TERRAIN_SIZE;
		int zCoord = i % TERRAIN_SIZE;
		
		G_TerrainList[i].x = (xCoord - TERRAIN_SIZE/2) * TERRAIN_DISTANCE;
		
		float noiseAtX = (float)xCoord/10.0;
		float noiseAtZ = (float)zCoord/10.0;
		
		G_TerrainList[i].y = 	(perlinNoise2D(noiseAtX, noiseAtZ)*TERRAIN_DIMENSION
								/* Die 0.8 ist ein manueller Versatz, damit die Wasserkante nicht sichtbar ist. */
								+ gauss(noiseAtX, noiseAtZ, -TERRAIN_SIZE*TERRAIN_DISTANCE*0.5*0.1*0.9) * GAUSS_DIMENSION
								- 2.0 * gauss(noiseAtX, noiseAtZ, 0.0) * GAUSS_DIMENSION) 
								+ 14.0;
		G_TerrainList[i].z = (zCoord - TERRAIN_SIZE/2) * TERRAIN_DISTANCE;
		
		G_TerrainList[i].s = (float)xCoord / (float)TERRAIN_SIZE;
		G_TerrainList[i].t = (float)zCoord / (float)TERRAIN_SIZE;
		
		G_TerrainList[i].nx = 0.0;
		G_TerrainList[i].ny = 1.0;
		G_TerrainList[i].nz = 0.0;
		
		min = G_TerrainList[i].y < min ? G_TerrainList[i].y : min;
		max = G_TerrainList[i].y > max ? G_TerrainList[i].y : max;
		
		G_TerrainCaustics[i].x = G_TerrainList[i].x;
		G_TerrainCaustics[i].y = G_TerrainList[i].y;
		G_TerrainCaustics[i].z = G_TerrainList[i].z;
		G_TerrainCaustics[i].nx = G_TerrainList[i].nx;
		G_TerrainCaustics[i].ny = G_TerrainList[i].ny;
		G_TerrainCaustics[i].nz = G_TerrainList[i].nz;
		G_TerrainCaustics[i].s = G_TerrainList[i].s;
		G_TerrainCaustics[i].t = G_TerrainList[i].t;		
		
	}
	
	printf ("Terrain-Height min: %f, max: %f\n", min, max);
	
	initTerrainIndices();
	calcTerrainNormals();
	
}


================================================
FILE: src/terrain.h
================================================
#ifndef __TERRAIN_H__
#define __TERRAIN_H__
#define __DEBUG_GL_H__
/**
 * @file
 * Programmlogik und Datenhaltung
 *
 * @author Maurice Tollmien
 */

/* ---- System Header einbinden ---- */
#ifdef WIN32
#include <windows.h>
#endif

#ifdef MACOSX
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif

#include <stdio.h>
#include <stdarg.h>

#include "types.h"

/* Maximale Ausdehnung (Mittig!) */
#define TERRAIN_SIZE	200
/* Wie groß das Noise abgebildet werden soll */
#define TERRAIN_DIMENSION	18.0
#define GAUSS_DIMENSION		10.0

#define TERRAIN_DISTANCE	1.0

#define PERSISTENCE		0.25
#define OCTAVES_COUNT	32

Terrain * getTerrainList(void);
void initTerrain(void);
Terrain * getTerrainCaustics(void);
GLuint * getTerrainIndices (void);

#endif



================================================
FILE: src/textureDepthFragmentShader.frag
================================================
#version 330 

in vec2 texcoords; 
uniform sampler2D texsampler; 
out vec4 Color; 

float linearizeDepth (float depth) {
	float nearPlane = 0.1, farPlane = 1000.0;
	return (2*nearPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane));
}

float linearizeDepthExtreme (float depth) {
	float nearPlane = 0.1, farPlane = 1000.0;
	float res = (2*nearPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane));
	res = (res+0.3)*(res+0.3) - 0.5;
	return res;
}

void main(){
	Color = vec4(linearizeDepthExtreme(texture(texsampler, texcoords).x)); 
}


================================================
FILE: src/textureFragmentShader.frag
================================================
#version 330 

in vec2 texcoords; 
in vec3 normal;
in float height;
in vec3 causticNormal;
uniform sampler2D texSand; 
uniform sampler2D texGrass; 
uniform sampler2D texRocks; 
uniform sampler2D texSnow; 
uniform sampler2D texForest; 
uniform sampler2D texTundra; 
out vec4 Color; 

float getLightValue(vec3 normalAt, vec3 sun, vec3 sun2, float lightUp) {
	float light  = max(0,dot(normalAt, sun));
	float light1 = max(0,dot(normalAt, sun2));
	return mix(min(1,light + lightUp), min(1,light1 + lightUp), 0.5);
}

vec4 calcTexChange (float height, float min, float max, vec4 tex1, vec4 tex2) {
	float aspect = (height-min) / (max-min);
	return mix(tex1, tex2, aspect);
}

void main(){ 	
	float 	sandGrassFrom 	= -3.0, sandGrassTo 		= 3.0,
			grassForestFrom = 4.0,  grassForestTo 	= 7.0,
			forestTundraFrom = 16.0, forestTundraTo = 25.0,
			tundraRocksFrom = 25.0, tundraRocksTo	= 30.0,
			rocksSnowFrom 	= 40.0, rocksSnowTo		= 60.0;
	
	vec3 sun  = vec3(1,1,1);
	vec3 sun2 = vec3(-1,1,1);
	vec4 sand  = texture(texSand , texcoords); 
	vec4 grass = texture(texGrass, texcoords*3.0); 
	vec4 forest = texture(texForest, texcoords*3.0);
	vec4 rocks = texture(texRocks, texcoords);
	vec4 tundra = texture(texTundra, texcoords*5.0);
	vec4 snow = texture(texSnow, texcoords*5.0);
	vec4 color;
	
	if (height < sandGrassFrom) {
		color = sand;
	} else if (height < sandGrassTo) {
		color = calcTexChange(height, sandGrassFrom, sandGrassTo, sand, grass);
	} else if (height < grassForestFrom) {
		color = grass;
	} else if (height < grassForestTo) {
		color = calcTexChange(height, grassForestFrom, grassForestTo, grass, forest);
	} else if (height < forestTundraFrom) {
		color = forest;
	} else if (height < forestTundraTo) {
		color = calcTexChange(height, forestTundraFrom, forestTundraTo, forest, tundra);
	} else if (height < tundraRocksFrom) {
		color = tundra;
	} else if (height < tundraRocksTo) {
		color = calcTexChange(height, tundraRocksFrom, tundraRocksTo, tundra, rocks);
	} else if (height < rocksSnowFrom) {
		color = rocks;
	} else if (height < rocksSnowTo) {
		color = calcTexChange(height, rocksSnowFrom, rocksSnowTo, rocks, snow);
	} else {
		color = snow;
	}
		
	color = color * getLightValue(normal, sun, sun2, 0.3);
	
	// Caustics
	//color = color * getLightValue(causticNormal, sun, sun2, 0.5);
	//float amount = dot(causticNormal, sun);
	//vec4 white = vec4(1,1,1,1);
	//vec4 caustics = mix(color, white, amount);
	
	Color = color;
}


================================================
FILE: src/textureVertexShader.vert
================================================
#version 330 
		
layout (location = 0) in vec3 vertPos; 
layout (location = 1) in vec2 tex; 
layout (location = 2) in vec3 normalIn; 
layout (location = 3) in vec3 causticNormal;
uniform mat4 viewMatrix, projMatrix; 
out vec2 texcoords; 
out vec3 normal;
out float height;
out vec3 caustic;

void main(){ 
	gl_Position =  projMatrix * viewMatrix * vec4(vertPos, 1.0); 
	texcoords = tex; 
	normal = normalize(normalIn);
	height = vertPos.y;
	caustic = normalize(causticNormal);
}


================================================
FILE: src/types.h
================================================
#ifndef __TYPES_H__
#define __TYPES_H__

/**
 * @file
 * Typenschnittstelle.
 * Das Modul kapselt die Typdefinitionen und globalen Konstanten des Programms.
 *
 * @author Maurice Tollmien
 */

/* ---- System Header einbinden ---- */
#ifdef WIN32
#include <windows.h>
#endif

#ifdef MACOSX
#include <OpenGL/gl.h>
#else
#include <GL/gl.h>
#endif

/* ---- Eigene Konstanten */

#define REFRACTION		30

#define GROUND_HEIGHT	0.3

#define CAMERA_X        -50.1
#define CAMERA_Y        50.0
#define CAMERA_Z        75.0
#define CAMERA_SPEED    15.0

#define CAMERA_MOVEMENT_SPEED	4.0
#define CAMERA_ZOOM_SPEED 10.0

#define COUNTOWNTEX 2
#define WORLD_SIZE 150

#define SLICE_CNT	50

#define E			2.71828183
#define PI             3.14159265  
#define EPS		0.0001

/** Anzahl der Aufrufe der Timer-Funktion pro Sekunde */
#define TIMER_CALLS_PS      120

/** Reihen des Images */
#define IMAGE_ROWS  128
#define IMAGE_COLS  128

#define SPHERE_MOVE_SPEED	-35
#define SPHERE_R	80.0
#define SPHERE_TRANSPARENCY		0.8
#define SPHERE_CNT	0

#define QUAD_CNT	0
#define QUAD_SIDE	60

#define RED                     0.7, 0.0, 0.0
#define BLUE                    0.0, 0.0, 0.7
#define GREEN                   0.0, 0.7, 0.0
#define BLACK                   0.0, 0.0, 0.0
#define WHITE                   1.0, 1.0, 1.0
#define GREY                    0.4, 0.4, 0.4 
#define YELLOW                  0.7, 0.7, 0.0

/* Text */
/** Textausgabe, wenn das SPIEel zu ende ist, weil kein Stein mehr verfuegbar ist */
#define HELP_OUTPUT_1       "====== U'r blinded by pure AWESOMENESS!!!!! ======"
#define HELP_OUTPUT_2       "|________________________________________________|"
#define HELP_OUTPUT_3       "q/Q    beendet das Spiel."
#define HELP_OUTPUT_4       "r        beginnt ein neues Spiel im Ausgangszustand."
#define HELP_OUTPUT_5       "h/H     oeffnet/schliesst den Hilfemodus."
#define HELP_OUTPUT_6       "+/-     Aendert die Anzahl der Quadrate auf dem Boden"
#define HELP_OUTPUT_7       "n/N     Kamera zum naechsten Partikel wechseln."
#define HELP_OUTPUT_8       "m/M   Kugeln in Bewegung setzten."
#define HELP_OUTPUT_9       "t/T    Textur wechseln."
#define HELP_OUTPUT_10       "p/P   Partikel einfrieren."
#define HELP_OUTPUT_11       "f/F    Ansicht der Partikel wechseln."
#define HELP_OUTPUT_12       "b      Kugeln bewegen sich nach Bezier."
#define HELP_OUTPUT_13       "B      Bezier-Kurven der Kugeln werden angezeigt."
#define HELP_OUTPUT_14       "s/S   Schatten zeichnen an/aus."
#define HELP_OUTPUT_15      "k/K    Kamera-Modus wechseln."
#define HELP_OUTPUT_16       "v/V   Verfolger-Modus an/aus."
#define HELP_OUTPUT_17       "x/X   Abstand fuer Bezier-Kontrollpunkte erhoehen."
#define HELP_OUTPUT_18       "y/Y   Abstand fuer Bezier-Kontrollpunkte verkleinern."
#define HELP_OUTPUT_19       "f1    Wireframe an/aus."
#define HELP_OUTPUT_20       "f2    Licht an/aus."
#define HELP_OUTPUT_21       "f3    Texturen an/aus."
#define HELP_OUTPUT_22       "Maus + rechte Maustaste    Abstand zum Mittelpunkt."
#define HELP_OUTPUT_23       "Maus + linke Maustaste    Bewegung im Raum."


/* Tastatur */
/** Keyboardtaste ESC definieren */
#define ESC     27
/** Keyboardtaste SPACE definieren */
#define SPACE   32

/** Datentyp fuer  den aktuellen SPIEelmodus */
enum e_gameIntiType { OFF, ON };
typedef enum e_gameIntiType InitType;

/** Mausereignisse. */
enum e_MouseEventType
{ mouseButton, mouseMotion, mousePassiveMotion };
/** Datentyp fuer Mausereignisse. */
typedef enum e_MouseEventType CGMouseEventType;

/** Mausereignisse. */
enum e_MouseInterpretType
{ NONE, MOVE, ZOOM};
/** Datentyp fuer Mausereignisse. */
typedef enum e_MouseInterpretType MouseInterpretType;

/** Datentyp fuer die Texturart */
enum e_textureType
{ NORMALTEXTURE, CHECKER, DIAGONAL };
/** Datentyp die Texturart */
typedef enum e_textureType textureType;

/** Datentyp fuer  den aktuellen SPIEelmodus */
enum e_gameModi { normal, help };
typedef enum e_gameModi GameMode;

/** Datentyp fuer die Verlaengerung/Verkuerzung des Kameravektors */
enum e_cameraVector { closer, further };
typedef enum e_cameraVector CameraVector;

/** Datentyp fuer die Richtungsaenderungen */
enum e_gameDirection {left, right, up, down};
typedef enum e_gameDirection Directions;

/** Punkt im 3D-Raum (homogene Koordinaten) */
typedef GLfloat CGPoint4f[4];
typedef GLfloat CGPoint3f[3];
typedef CGPoint3f CGColor;

/** Datentyp fuer einen Vektor */
typedef double Vector4D[4];
typedef Vector4D Punkt4D;

/** Vektor im 3D-Raum */
typedef GLfloat CGVector3D[3];

typedef double Vertex[6];

typedef int Movement[3];

typedef double VertexTexture[2];

enum e_particleType {line, sphere};
typedef enum e_particleType ParticleType;

typedef struct {
	GLfloat x,y,z;
	GLfloat s,t;
	GLfloat nx, ny, nz;
	GLint fix;
} Water;

typedef struct {
	GLfloat x,y,z;
	GLfloat s,t;
	GLfloat nx, ny, nz;
} Terrain;

/** Kugeln */
typedef struct X * Spheres;
struct X
{
	/* Position im Raum */
    CGPoint3f pos;
    /* Richtungsvektor, Geschwindigkeit in eine Richtung */
    CGVector3D newPos;   
    /* Farbe */
   CGVector3D color; 
    /* Bezier */
    Vertex * interpolatedPoints;
    /* Bezier */
    Vertex * interpolatedPointsAll;

    Vertex * controlPoints;
    /* Bezier t */
    double t;
};

/** Kugeln */
typedef struct Z * Quads;
struct Z
{
	/* Position im Raum */
    CGPoint3f pos;
};


/** Partikel */
typedef struct Y * Particle;
struct Y
{
	/* Position im Raum */
    CGPoint3f s;
    /* Geschwindigkeitsvektor */
    CGVector3D v;   
    /* Beschleunigungsvektor */
	CGVector3D a;
	/* Kraft - intern */
	CGVector3D f;
	/* Masse */
	double m;
	/* Noch was? */
	/* Upvektor */ 
	CGVector3D up;
};

#endif


================================================
FILE: src/vector.c
================================================
/**
 * @file
 * Hier ist die Datenhaltung und Programmlogik
 *
 * @author Tilman Nedele, Maurice Tollmien
 */

/* ---- System Header einbinden ---- */
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <math.h>
#include <stringOutput.h>
#include <assert.h>

#ifdef MACOSX
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

/* ---- Eigene Header einbinden ---- */
#include "types.h"


/**
 * Printet einen Vector aus.
 */
void printVector (CGVector3D a)
{
	int i;
	printf("\nprintVector:\n");
	for (i=0;i<3;i++)
		printf("%.1f\n", a[i]);
	printf("\n");
}

/**
 * Konvertierungsfunktion,
 * wandelt drei Koordinaten in den dazugehörigen Vektor um
 * @param x
 * @param y
 * @param z
 */
void toVector3D(CGVector3D vector, GLfloat x, GLfloat y, GLfloat z)
{
  vector[0] = x;
  vector[1] = y;
  vector[2] = z;
}

/**
 * Berechnet die Länge es Vektors
 * @param v
 *@return float
 */
float vectorLength3D(CGVector3D vector)
{
  return sqrt((vector[0]*vector[0])+
              (vector[1]*vector[1])+
              (vector[2]*vector[2]));
}

/**
 * Normiert eine Vektor
 * @param v der zu normierende Vektor
 * @return der normierte Vektor
 */
void normVector3D(CGVector3D vector)
{
  float l = vectorLength3D(vector);
  if (l != .0f)
    toVector3D(vector, vector[0]/l, vector[1]/l, vector[2]/l);
}

/**
 * Berechnet das Kreuzprodukt zweier Vektoren
 * @param
 * @param
 * @return
 */
void crossProduct3D(CGVector3D product, CGVector3D a, CGVector3D b)
{
  toVector3D(product, (a[1]*b[2] - a[2]*b[1]),
                      (a[2]*b[0] - a[0]*b[2]),
                      (a[0]*b[1] - a[1]*b[0]));
}

/**
 * Multipliziert zwei Vektoren miteinander (Skalarprodukt)
 */
double multiplyVectorVector (CGVector3D a, CGVector3D b)
{
	int i;
	double res = 0.0;
	for (i=0;i<3;i++)
		res += a[i]*b[i];
	return res;
}

/**
 * Multipliziert einen Vektor mit einem Skalar.
 */
void multiplyVectorScalar (CGVector3D a, double s, CGVector3D * res)
{
	int i;
	for (i=0;i<3;i++)
		(*res)[i] = a[i]*s;
}

double scalarProduct (CGVector3D a, CGVector3D b)
{
	return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];	
}

/**
 * Zieht b von a ab, also: a-b
 */
void subtractVectorVector (CGVector3D a, CGVector3D b, CGVector3D * res)
{
	int i;
	for (i=0;i<3;i++)
		(*res)[i] = a[i] - b[i];
}

/**
 * Teilt den Vector a durch s.
 */
void divideVectorScalar (CGVector3D a, double s, CGVector3D * res)
{
	int i;
	for (i=0;i<3;i++)
		(*res)[i] = a[i] / s;
}

/**
 * Addiert a und b und schreibt das Ergebnis in res.
 */
void addVectorVector (CGVector3D a, CGVector3D b, CGVector3D * res)
{
	int i;
	for (i=0;i<3;i++)
		(*res)[i] = a[i] + b[i];
}

/**
 * Wandelt eine Zahl (Grad) in Radiant.
 * deg muss im Wertebereich 0..359 liegen!
 */
double degToRad (double deg)
{
	return deg*PI/180.0;
}

/**
 * Wandelt eine Zahl (Radiant) in Grad um.
 * deg muss im Wertebereich 0..PI liegen!
 */
double radToDeg (double rad)
{
	return rad*180.0/PI;
}

/**
 * Berechnet den Winkel zwischen zwei Vektoren und gibt das Ergebnis in 
 * ° zurück (nicht radiant!).
 */
double angleVectorVector (CGVector3D a, CGVector3D b)
{
	return radToDeg (acos (multiplyVectorVector (a, b) / (vectorLength3D(a)*vectorLength3D(b))));
}


















================================================
FILE: src/vector.h
================================================
#ifndef __VECTOR_H__
#define __VECTOR_H__
#define __DEBUG_GL_H__
/**
 * @file
 * Programmlogik und Datenhaltung
 *
 * @author Maurice Tollmien
 */

/* ---- System Header einbinden ---- */
#ifdef WIN32
#include <windows.h>
#endif

#ifdef MACOSX
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif

#include <stdio.h>
#include <stdarg.h>

#include "types.h"

/* eig. Funktionen */

/**
 * Konvertierungsfunktion,
 * wandelt drei Koordinaten in den dazugehörigen Vektor um
 * @param x
 * @param y
 * @param z
 */
void toVector3D(CGVector3D vector, GLfloat x, GLfloat y, GLfloat z);
/**
 * Berechnet die Länge es Vektors
 * @param v
 *@return float
 */
float vectorLength3D(CGVector3D vector);

/**
 * Normiert eine Vektor
 * @param v der zu normierende Vektor
 * @return der normierte Vektor
 */
void normVector3D(CGVector3D vector);

/**
 * Berechnet das Kreuzprodukt zweier Vektoren
 * @param
 * @param
 * @return
 */
void crossProduct3D(CGVector3D product, CGVector3D a, CGVector3D b);

double multiplyVectorVector (CGVector3D a, CGVector3D b);
void multiplyVectorScalar (CGVector3D a, double s, CGVector3D * res);
void subtractVectorVector (CGVector3D a, CGVector3D b, CGVector3D * res);
void divideVectorScalar (CGVector3D a, double s, CGVector3D * res);
void addVectorVector (CGVector3D a, CGVector3D b, CGVector3D * res);
void printVector (CGVector3D a);
double angleVectorVector (CGVector3D a, CGVector3D b);
double radToDeg (double rad);
double degToRad (double deg);
double scalarProduct (CGVector3D a, CGVector3D b);

#endif


================================================
FILE: src/water.c
================================================

#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <math.h>
/* ---- Eigene Header einbinden ---- */
#include "water.h"
#include "particle.h"
#include "logic.h"
#include "vector.h"
#include "types.h"
#include "terrain.h"

Water * G_WaterList;
Water * G_TmpWaterList;
float ** G_V;

GLuint * G_WaterIndices;

int normalList = 1;
int G_IsMoving = 1;
int G_randomize = 0;

Water * getWaterList(void){
	return G_WaterList;
}

void calcWaterAttributes (double interval) {
	
	int i,j;
	double f;
	
	if (G_IsMoving) {
		
		for (i=0;i<WORLD_SIZE*WORLD_SIZE;i++) {		
			int atI = i % WORLD_SIZE;
			int atJ = i / WORLD_SIZE;
			
			if (0 && G_WaterList[i].fix && fabs(G_WaterList[i].y - WATER_HEIGHT_INIT) > 0.1) {
				printf ("Wasser: fix=%d, Y now=%f, Y init=%f\n", G_WaterList[i].fix, G_WaterList[i].y, (double)WATER_HEIGHT_INIT);
			}
			
			if (atI == 0 || atI == WORLD_SIZE-1 || atJ == 0 || atJ == WORLD_SIZE-1
				) {
				continue;
			}
			
			f = WATER_SPEED * WATER_SPEED * (	G_WaterList[i - WORLD_SIZE].y + 
												G_WaterList[i + WORLD_SIZE].y + 
												G_WaterList[i + 1].y + 
												G_WaterList[i - 1].y - 4 *
												G_WaterList[i].y
											) / WATER_WIDTH;
			
			G_V[atI][atJ] += f * interval;
			
			if (!G_WaterList[i].fix)
				G_TmpWaterList[i].y = G_WaterList[i].y + G_V[atI][atJ] * interval;
			else
				G_TmpWaterList[i].y = WATER_HEIGHT_INIT;
				
			if (G_randomize) {
				G_TmpWaterList[i].y = WATER_HEIGHT_INIT + WATER_DISTORTION - WATER_DISTORTION;
				G_WaterList[i].y = WATER_HEIGHT_INIT + WATER_DISTORTION - WATER_DISTORTION;
			}
			
			
			CGVector3D 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};
			CGVector3D 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};
			CGVector3D res1;
			crossProduct3D(res1, v1, v2);
			
			CGVector3D 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};
			CGVector3D 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};
			CGVector3D res2;
			crossProduct3D(res2, v3, v4);
			
			if (res1[1] < 0) {
				multiplyVectorScalar(res1, -1, &res1);
			}
			if (res2[1] < 0) {
				multiplyVectorScalar(res2, -1, &res2);
			}
			CGVector3D normal;
			addVectorVector(res1, res2, &normal);
			
			G_TmpWaterList[i].nx = normal[0];
			G_TmpWaterList[i].ny = normal[1];
			G_TmpWaterList[i].nz = normal[2];
			
			/* Caustics durch die Normalen des Wasser auf der Bodenfläche. */
			int waterTerrainOffset = (TERRAIN_SIZE - WORLD_SIZE)/2;
			Terrain * terrainCaustics = getTerrainCaustics();
			/*terrainCaustics[(atI + waterTerrainOffset) * TERRAIN_SIZE + (atJ + waterTerrainOffset)].nx = normal[0]; 
			terrainCaustics[(atI + waterTerrainOffset) * TERRAIN_SIZE + (atJ + waterTerrainOffset)].ny = normal[1]; 
			terrainCaustics[(atI + waterTerrainOffset) * TERRAIN_SIZE + (atJ + waterTerrainOffset)].nz = normal[2]; */
			
		}
		
		Water * tmp;
		tmp = G_TmpWaterList;
		G_TmpWaterList = G_WaterList;
		G_WaterList = tmp;
	}
	
	G_randomize = 0;
	
}

/**
 * Guckt, wo/ob Wasserpunkte einen Mindestabstand zu Landpunkten unterschreiten
 * und setzt diese auf fix, sodass quasi ein Wasserrand entsteht.
 */
void calcFixWaterPoints(Terrain * terrain) 
{
	int w,t;
	double eps = 1.0;
	
	for (t = 0; t < TERRAIN_SIZE*TERRAIN_SIZE; t++) {
		for (w = 0; w < WORLD_SIZE*WORLD_SIZE; w++) {
			
			if (fabs(terrain[t].x - G_WaterList[w].x) < eps && 
				fabs(terrain[t].y - G_WaterList[w].y) < eps && 
				fabs(terrain[t].z - G_WaterList[w].z) < eps
				) {
				G_WaterList[w].fix	= 1;
				G_WaterList[w].y 	= WATER_HEIGHT_INIT;
			}
		}
	}
}

void setRandomize(void) {
	G_randomize = 1;
}

void pushSomeWaterDown(void)
{
	
	int i,j;
	
	for (i=WORLD_SIZE/2-4;i<WORLD_SIZE/2+5;i++) {
		for (j=WORLD_SIZE/2-4;j<WORLD_SIZE/2+5;j++) {
			if (!G_WaterList[i*WORLD_SIZE+j].fix)
				G_WaterList[i*WORLD_SIZE+j].y -= 5.0;			
		}
	}
	
}

void toggleWaterMovement(void) 
{
	G_IsMoving = !G_IsMoving;
}

GLuint * getWaterIndices (void) 
{
	return G_WaterIndices;
}

void initWaterIndices(void) {
	
	int i,j;
	int index = 0;
	for (i=0;i<WORLD_SIZE*WORLD_SIZE;i++) {		
		int atI = i % WORLD_SIZE;
		int atJ = i / WORLD_SIZE;
		
		if (atI == WORLD_SIZE-1 || atJ == WORLD_SIZE-1) {
			continue;
		}
		
		G_WaterIndices[index]   = i;
		G_WaterIndices[index+1] = i+1;
		G_WaterIndices[index+2] = i+WORLD_SIZE+1;
		
		G_WaterIndices[index+3] = i;
		G_WaterIndices[index+4] = i+WORLD_SIZE+1;
		G_WaterIndices[index+5] = i+WORLD_SIZE;
		
		index += 6;			
	}
	
}

void initWater(void) {
	
	int i,j;
	
	G_V = calloc(WORLD_SIZE, sizeof(*G_V));
	G_WaterList = calloc(WORLD_SIZE*WORLD_SIZE, sizeof(*G_WaterList));
	G_TmpWaterList = calloc(WORLD_SIZE*WORLD_SIZE, sizeof(*G_TmpWaterList));
	G_WaterIndices = calloc(WORLD_SIZE*WORLD_SIZE*2*3, sizeof(*G_WaterIndices));
	
	for (i=0;i<WORLD_SIZE;i++) {
		G_V[i] = calloc(WORLD_SIZE, sizeof(**G_V));
	}
	
	for (i=0;i<WORLD_SIZE*WORLD_SIZE;i++) {
		int xCoord = i / WORLD_SIZE;
		int zCoord = i % WORLD_SIZE;
		
		G_WaterList[i].x = xCoord - WORLD_SIZE/2;
		G_WaterList[i].y = WATER_HEIGHT_INIT /*+ WATER_DISTORTION - WATER_DISTORTION*/;
		G_WaterList[i].z = zCoord - WORLD_SIZE/2;
		
		G_WaterList[i].s = (float)xCoord / (float)WORLD_SIZE;
		G_WaterList[i].t = (float)zCoord / (float)WORLD_SIZE;
		
		G_WaterList[i].nx = 0.0;
		G_WaterList[i].ny = 1.0;
		G_WaterList[i].nz = 0.0;
		
		G_WaterList[i].fix = 0;
		
		G_TmpWaterList[i].x = G_WaterList[i].x;
		G_TmpWaterList[i].y = G_WaterList[i].y;
		G_TmpWaterList[i].z = G_WaterList[i].z;
		
		G_TmpWaterList[i].s = G_WaterList[i].s;
		G_TmpWaterList[i].t = G_WaterList[i].t;		
		
		G_TmpWaterList[i].nx = G_WaterList[i].nx;		
		G_TmpWaterList[i].ny = G_WaterList[i].ny;		
		G_TmpWaterList[i].nz = G_WaterList[i].nz;	
		
		G_TmpWaterList[i].fix = 0;	
		
		G_V[xCoord][zCoord] = 0.0;
		
		
	}
	
	initWaterIndices();	
}


================================================
FILE: src/water.h
================================================
#ifndef __WATER_H__
#define __WATER_H__
#define __DEBUG_GL_H__
/**
 * @file
 * Programmlogik und Datenhaltung
 *
 * @author Maurice Tollmien
 */

/* ---- System Header einbinden ---- */
#ifdef WIN32
#include <windows.h>
#endif

#ifdef MACOSX
#include <OpenGL/glu.h>
#else
#include <GL/glu.h>
#endif

#include <stdio.h>
#include <stdarg.h>

#include "types.h"
#include "terrain.h"

#define WATER_HEIGHT_INIT	0
#define WATER_SPEED 		3
#define WATER_WIDTH			1
#define WATER_DISTORTION	(rand()%1000) / 4000.0

Water * getWaterList(void);
void initWater(void);
void calcWaterAttributes (double interval);
void pushSomeWaterDown(void);
void toggleWaterMovement(void);
GLuint * getWaterIndices (void);
void calcFixWaterPoints(Terrain * terrain);
void setRandomize(void);

#endif



================================================
FILE: src/waterFragmentShader.frag
================================================
#version 330 
		

in vec3 pos_vec; 
in vec3 normal; 
in vec3 pos_cam;
in vec3 backgroundColor;
in float height;
uniform sampler2D texsampler; 
uniform sampler2D texsamplerDepth; 
uniform samplerCube texsamplerCube; 
uniform mat4 viewMatrix, projMatrix; 
out vec4 Color; 

float linearizeDepth2 (float depth) {
	float nearPlane = 0.1, farPlane = 1000.0;
	return (2*nearPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane));
}

float linearizeDepth (float depth) {
	float nearPlane = 0.1, farPlane = 1000.0;
	float res = (2*nearPlane) / (farPlane + nearPlane - depth * (farPlane - nearPlane));
	res = (res+0.3)*(res+0.3) - 0.5;
	return res;
}

// Umwandlung einer Weltkoordinate in Screenkoordinate!
vec3 getScreenPos (vec3 worldPos) {
	vec4 screenPos 	= projMatrix * viewMatrix * vec4(worldPos, 1.0);
	vec3 screenPos3	= screenPos.xyz / screenPos.w;
	return (screenPos3 + vec3(1.0)) / 2.0;
}

vec3 cubeMapRefl (vec3 reflectionWorld) {
	return texture(texsamplerCube, reflectionWorld).rgb;
}

vec3 cubeMapRefr (vec3 refractionWorld) {
	return texture(texsamplerCube, refractionWorld).rgb;
}

// Tiefe des Wassers an dem Fragment:
vec3 calcWaterDependentDarkness(vec3 color, float maxDepth) {
	// zwischen 0 und 1.
	vec3 screenPos		= getScreenPos(pos_vec);
	vec2 screenTexPos 	= screenPos.xy;
	
	float texDepth = texture(texsamplerDepth, screenTexPos).x;
	float worldDepth = screenPos.z;
	
	float depth = worldDepth - texDepth;
	vec3 black = vec3(0.0);
	
	/*if (depth <= 1.0 && depth >= 0.0) {
		return vec3(1,0,0);
	} else
		return vec3(1.0);*/
	return vec3(texDepth);
	
	return mix(black, color, 1.0-depth);
}

vec3 raytrace(in vec3 reflectionWorld, in int maxCount, in float stepSize) {
	vec3 color = vec3(1.0); 	
	vec3 testVec = pos_vec;
	
	vec3 reflectionVector = reflectionWorld * stepSize;
	
	vec3 screenPos		= getScreenPos(testVec);
	vec2 screenTexPos 	= screenPos.xy;
	
	
	float texDepth = texture(texsamplerDepth, screenTexPos).x;
	float worldDepth = screenPos.z;
	
	bool run = true;
	int count = 0;

	while (run) {
		
		texDepth = texture(texsamplerDepth, screenTexPos).x;
		worldDepth = screenPos.z;
		
		if (texDepth <= worldDepth) {
			color = texture(texsampler, screenTexPos).rgb;
			break;
		}
		
		testVec 		= testVec + reflectionVector;
		screenPos		= getScreenPos(testVec);
		screenTexPos 	= screenPos.xy;
		
		count = count+1;
		run = 	screenTexPos.x < 1.0 && screenTexPos.x >= 0.0 &&
				screenTexPos.y < 1.0 && screenTexPos.y >= 0.0 && count < maxCount;
	}
	
	if (!run) {
		color = cubeMapRefl(testVec);
		// Cheating
		//color = vec3(0,1,1);
	}
	
	return color;
} 

float getFresnelFactor (void) {
	float fresnelPower = 3; 
	float fresnelScale = 5.0; 
	float fresnelBias  = 0.05373; 
	return fresnelBias + fresnelScale * pow(1 + dot(normalize(pos_vec - pos_cam), normal), fresnelPower);
}

float calcStepSize(float stepSize, float max, vec3 n, vec3 cam) {
	float scalarProduct = dot(n, cam);
	float res = 0.0;
	
	res = (1.0 - scalarProduct) * (max-stepSize);
	
	return res + stepSize;
}

void main(){ 
	const int maxCount = 250;
	const float ratio = 1.0 / 1.3333; 
	float stepSize = 20.0;
	float maxStepSize = 400.0;
	float maxDepth = 0.9;
	vec4 black = vec4(0,0,0,0);
	
	vec3 eyePosition = normalize(pos_vec - pos_cam);
	
	vec3 reflectionWorld = normalize (reflect(eyePosition, normal));
	vec3 refractionWorld = normalize (refract(eyePosition, normal, ratio));
	
	// Nicht physikalisch korrekte Anpassung, dass mehr Geometrie gespiegelt wird!
	reflectionWorld = reflectionWorld + vec3(0, -0.15, 0);
	
	// Stepsize anpassen an das Verhältnis der Normalen zum Blickvektor
	stepSize = calcStepSize(stepSize, maxStepSize, -normal, eyePosition);
	
	vec3 reflectedColor = raytrace(reflectionWorld, maxCount, stepSize); 
	vec3 refractedColor = raytrace(refractionWorld, maxCount, stepSize);
	
	//refractedColor = calcWaterDependentDarkness(refractedColor, maxDepth);
	
	vec4 screenSpaceReflection = vec4(reflectedColor, 1.0);
	vec4 screenSpaceRefraction = vec4(refractedColor, 1.0);
	
	screenSpaceRefraction = mix(black, screenSpaceRefraction, 0.5);
	
	vec4 tmpColor = mix (screenSpaceRefraction, screenSpaceReflection, getFresnelFactor());
	tmpColor = mix (black, tmpColor, 0.8);
	
	// Wenn das Wasser tief wird.
	if (height < 0.0) {
		float aspect = (height+8.0) / 8.0;
		tmpColor = mix(black, tmpColor, aspect);
		tmpColor = vec4(0.0);
	}
	
	Color = tmpColor;
	//Color = screenSpaceReflection;
	//Color = screenSpaceRefraction;
}


================================================
FILE: src/waterVertexShader.vert
================================================
#version 330 
		
layout (location = 0) in vec3 vertPos; 
layout (location = 1) in vec3 normal_in; 
layout (location = 2) in vec3 terrain;
uniform mat4 viewMatrix, projMatrix; 
uniform vec3 cameraPos; 
out vec3 pos_vec; 
out vec3 normal; 
out vec3 pos_cam; 
out float height;

void main(){ 
	vec3 newPos = vec3(vertPos - pos_cam); 
	gl_Position =  projMatrix * viewMatrix * vec4(vertPos, 1.0); 
	pos_vec = vertPos; 
	normal   = normalize(normal_in); 
	pos_cam = cameraPos; 
	height = terrain.y;
}
Download .txt
gitextract_532xa9lh/

├── LICENSE
├── README.md
└── src/
    ├── Makefile
    ├── Makefile.common
    ├── Makefile.depend
    ├── colorFragmentShader.frag
    ├── colorVertexShader.vert
    ├── imageLoader.c
    ├── imageLoader.h
    ├── io.c
    ├── io.h
    ├── logic.c
    ├── logic.h
    ├── main.c
    ├── particle.c
    ├── particle.h
    ├── scene.c
    ├── scene.h
    ├── stringOutput.c
    ├── stringOutput.h
    ├── terrain.c
    ├── terrain.h
    ├── textureDepthFragmentShader.frag
    ├── textureFragmentShader.frag
    ├── textureVertexShader.vert
    ├── types.h
    ├── vector.c
    ├── vector.h
    ├── water
    ├── water.c
    ├── water.h
    ├── waterFragmentShader.frag
    └── waterVertexShader.vert
Download .txt
SYMBOL INDEX (168 symbols across 12 files)

FILE: src/imageLoader.c
  function error (line 9) | int error(FILE * f, char * name, char * errorMessage) {
  function imageLoad (line 16) | int imageLoad(char *filename, Image *image) {

FILE: src/imageLoader.h
  type Image (line 25) | typedef struct {

FILE: src/io.c
  function cbTimer (line 132) | static void
  function setProjection (line 159) | static void
  function drawColoredQuad (line 176) | static void drawColoredQuad(double r, double g, double b) {
  function drawSimpleStuff (line 201) | static void drawSimpleStuff(GLuint colorTex, int fromX, int fromY, int w...
  function drawSimpleStuffShader (line 243) | static void drawSimpleStuffShader(GLuint shader, GLuint colorTex, int fr...
  function drawTerrainComplete (line 285) | void drawTerrainComplete(void) {
  function drawSceneToTexture (line 342) | void drawSceneToTexture(GLuint tex, GLfloat ex, GLfloat ey, GLfloat ez, ...
  function allocateMemoryStuff (line 367) | void allocateMemoryStuff(GLuint * texID, GLuint * fbo) {
  function allocateMemoryStuffDepth (line 393) | void allocateMemoryStuffDepth(GLuint * texID, GLuint * texID2, GLuint * ...
  function loadCubeSide (line 419) | void loadCubeSide(GLuint * texID, GLenum side) {
  function appendTexToFB (line 425) | void appendTexToFB(GLuint * fbo, GLuint * texID, GLenum side) {
  function allocateMemoryStuffCube (line 432) | void allocateMemoryStuffCube(GLuint * texID) {
  function renderFBToCubeTexture (line 469) | void renderFBToCubeTexture(GLuint * fbo, GLenum side, double vX, double ...
  function cbDisplay (line 506) | static void
  function cbKeyboard (line 710) | void cbKeyboard (unsigned char key, int x, int y)
  function cbSpecial (line 775) | void cbSpecial (int key, int x, int y)
  function cbUpSpecial (line 819) | void cbUpSpecial (int key, int x, int y)
  function handleMouseEvent (line 850) | static void
  function cbMouseButton (line 883) | static void
  function mouseMovement (line 889) | void mouseMovement(int x, int y)
  function cbReshape (line 908) | static void
  function registerCallBacks (line 921) | static void registerCallBacks (void)
  function readFile (line 961) | int readFile (char * name, char ** buffer) {
  function GLuint (line 973) | GLuint loadShaders(char * vertexShader, char * fragmentShader){
  function loadTextureImage (line 1038) | int loadTextureImage(Image * image, char * name, GLuint * tex) {
  function initAndStartIO (line 1064) | int initAndStartIO (char *title, int width, int height)

FILE: src/logic.c
  function getFPS (line 81) | int getFPS(void)
  function toggleShowUpVector (line 89) | void toggleShowUpVector (void)
  function getShowUpVector (line 98) | int getShowUpVector (void)
  function getCameraParticlePos (line 106) | int getCameraParticlePos() {
  function togglePersecutorParticle (line 113) | void togglePersecutorParticle (void)
  function toggleParticleCamera (line 121) | void toggleParticleCamera (void)
  function getParticleCamera (line 129) | int getParticleCamera (void)
  function startMovingBall (line 134) | void startMovingBall(void)
  function setKey (line 145) | void setKey (int key, int value)
  function toggleShadows (line 154) | void toggleShadows(void)
  function getDrawShadows (line 162) | int getDrawShadows(void)
  function toggleParticleType (line 170) | void toggleParticleType (void)
  function ParticleType (line 181) | ParticleType getParticleType (void)
  function toggleParticleFreeze (line 189) | void toggleParticleFreeze (void)
  function Spheres (line 199) | Spheres * getSphereList (void)
  function Quads (line 207) | Quads * getQuadList (void)
  function toggleSpheresMoving (line 215) | void toggleSpheresMoving (void)
  function InitType (line 224) | InitType getLightStatus() {
  function setLightStatus (line 232) | void setLightStatus(InitType state) {
  function toggleLight (line 236) | void toggleLight (void)
  function InitType (line 245) | InitType getHelpStatus() {
  function setHelpStatus (line 253) | void setHelpStatus(InitType state) {
  function InitType (line 261) | InitType getTextureStatus() {
  function setTextureStatus (line 269) | void setTextureStatus(InitType state) {
  function setMouseEvent (line 277) | void setMouseEvent(MouseInterpretType state,int x, int y) {
  function MouseInterpretType (line 291) | MouseInterpretType getMouseEvent() {
  function getCameraPosition (line 298) | double getCameraPosition (int axis)
  function incQuadCount (line 311) | void incQuadCount() {
  function decQuadCount (line 319) | void decQuadCount() {
  function getQuadCount (line 327) | int getQuadCount() {
  function setCameraMovement (line 334) | void setCameraMovement(int x,int y)
  function setCameraZoom (line 363) | void setCameraZoom(int x,int y)
  function moveSpheres (line 384) | void moveSpheres (double interval)
  function calcTimeRelatedStuff (line 403) | void calcTimeRelatedStuff (double interval)
  function drawRecursiveQuad (line 442) | void drawRecursiveQuad(CGPoint3f p1, CGPoint3f p2, CGPoint3f p3, CGPoint...
  function initCameraPosition (line 484) | void initCameraPosition ()
  function initSpheres (line 494) | void initSpheres(void)
  function initQuads (line 528) | void initQuads(void)
  function initGame (line 550) | void initGame ()

FILE: src/main.c
  function main (line 38) | int

FILE: src/particle.c
  function Particle (line 45) | Particle * getParticleList (void)
  function Particle (line 54) | Particle getParticleAt(int i)
  function getParticleCnt (line 62) | int getParticleCnt (void)
  function setParticleCnt (line 70) | void setParticleCnt (int i)
  function calcSpringForce (line 75) | void calcSpringForce (Particle p1, Particle p2, double initLength, doubl...
  function correctConcreteParticleSymmetric (line 112) | void correctConcreteParticleSymmetric (Particle p, Particle p2, double i...
  function correctConcreteParticleP2 (line 147) | void correctConcreteParticleP2 (Particle p, Particle p2, double initValue)
  function correctSpringLengthPosition (line 179) | void correctSpringLengthPosition(Particle p, int i, int j)
  function calcWindForce (line 266) | double calcWindForce (CGVector3D va, CGVector3D vb, CGVector3D vc, CGVec...
  function calcParticleAttributesEuler (line 299) | void calcParticleAttributesEuler (Spheres * spheres, int sphereCnt, doub...
  function addParticle (line 567) | void addParticle (void)
  function deleteParticle (line 595) | void deleteParticle (void)
  function initParticles (line 607) | void initParticles(void)

FILE: src/scene.c
  function printHelp (line 50) | void printHelp (void)
  function setColor (line 90) | void setColor (float color1, float color2, float color3, float alpha, fl...
  function drawSphere (line 139) | void drawSphere (int sliceCount, double r)
  function drawSquare (line 160) | static void
  function drawCube (line 195) | static void
  function drawVertex (line 258) | void drawVertex(CGPoint3f p1, CGPoint3f p2, CGPoint3f p3, CGPoint3f p4, ...
  function drawBottom (line 277) | void drawBottom(void)
  function drawSides (line 303) | void drawSides(void)
  function drawWorld (line 391) | void drawWorld() {
  function drawSpheres (line 409) | void drawSpheres(void)
  function drawQuads (line 435) | void drawQuads(void)
  function drawOneParticle (line 459) | void drawOneParticle(Particle p, int suspensionPoint)
  function drawParticleNormal (line 482) | void drawParticleNormal (Particle p)
  function drawFPS (line 499) | void drawFPS (void)
  function drawWaterSurface (line 510) | void drawWaterSurface(void)
  function drawTerrainSurface (line 527) | void drawTerrainSurface(void)
  function drawScene (line 561) | void drawScene (void)
  function initLight (line 622) | static void initLight (void)
  function initScene (line 671) | int initScene (void)
  function toggleWireframeMode (line 689) | void

FILE: src/stringOutput.c
  function drawString (line 28) | void

FILE: src/terrain.c
  function Terrain (line 17) | Terrain * getTerrainList(void){
  function Terrain (line 21) | Terrain * getTerrainCaustics(void) {
  function GLuint (line 25) | GLuint * getTerrainIndices (void)
  function initTerrainIndices (line 30) | void initTerrainIndices(void) {
  function calcTerrainNormals (line 55) | void calcTerrainNormals(void) {
  function interpolateCube (line 99) | double interpolateCube(double v0, double v1, double v2, double v3, doubl...
  function interpolateCos (line 110) | double interpolateCos(double a, double b, double x) {
  function noise (line 119) | double noise(int x, int y) {
  function smoothedNoise (line 129) | double smoothedNoise(float x, float y) {
  function interpolatedNoise (line 139) | double interpolatedNoise(float x, float y) {
  function perlinNoise2D (line 160) | double perlinNoise2D(float x, float y) {
  function gauss (line 178) | double gauss(float x, float y, float offset) {
  function initTerrain (line 190) | void initTerrain(void) {

FILE: src/types.h
  type e_gameIntiType (line 103) | enum e_gameIntiType { OFF, ON }
  type InitType (line 104) | typedef enum e_gameIntiType InitType;
  type e_MouseEventType (line 107) | enum e_MouseEventType
  type CGMouseEventType (line 110) | typedef enum e_MouseEventType CGMouseEventType;
  type e_MouseInterpretType (line 113) | enum e_MouseInterpretType
  type MouseInterpretType (line 116) | typedef enum e_MouseInterpretType MouseInterpretType;
  type e_textureType (line 119) | enum e_textureType
  type textureType (line 122) | typedef enum e_textureType textureType;
  type e_gameModi (line 125) | enum e_gameModi { normal, help }
  type GameMode (line 126) | typedef enum e_gameModi GameMode;
  type e_cameraVector (line 129) | enum e_cameraVector { closer, further }
  type CameraVector (line 130) | typedef enum e_cameraVector CameraVector;
  type e_gameDirection (line 133) | enum e_gameDirection {left, right, up, down}
  type Directions (line 134) | typedef enum e_gameDirection Directions;
  type GLfloat (line 137) | typedef GLfloat CGPoint4f[4];
  type GLfloat (line 138) | typedef GLfloat CGPoint3f[3];
  type CGPoint3f (line 139) | typedef CGPoint3f CGColor;
  type Vector4D (line 143) | typedef Vector4D Punkt4D;
  type GLfloat (line 146) | typedef GLfloat CGVector3D[3];
  type e_particleType (line 154) | enum e_particleType {line, sphere}
  type ParticleType (line 155) | typedef enum e_particleType ParticleType;
  type Water (line 157) | typedef struct {
  type Terrain (line 164) | typedef struct {
  type X (line 171) | struct X
  type X (line 172) | struct X
  type Z (line 191) | struct Z
  type Z (line 192) | struct Z
  type Y (line 200) | struct Y
  type Y (line 201) | struct Y

FILE: src/vector.c
  function printVector (line 29) | void printVector (CGVector3D a)
  function toVector3D (line 45) | void toVector3D(CGVector3D vector, GLfloat x, GLfloat y, GLfloat z)
  function vectorLength3D (line 57) | float vectorLength3D(CGVector3D vector)
  function normVector3D (line 69) | void normVector3D(CGVector3D vector)
  function crossProduct3D (line 82) | void crossProduct3D(CGVector3D product, CGVector3D a, CGVector3D b)
  function multiplyVectorVector (line 92) | double multiplyVectorVector (CGVector3D a, CGVector3D b)
  function multiplyVectorScalar (line 104) | void multiplyVectorScalar (CGVector3D a, double s, CGVector3D * res)
  function scalarProduct (line 111) | double scalarProduct (CGVector3D a, CGVector3D b)
  function subtractVectorVector (line 119) | void subtractVectorVector (CGVector3D a, CGVector3D b, CGVector3D * res)
  function divideVectorScalar (line 129) | void divideVectorScalar (CGVector3D a, double s, CGVector3D * res)
  function addVectorVector (line 139) | void addVectorVector (CGVector3D a, CGVector3D b, CGVector3D * res)
  function degToRad (line 150) | double degToRad (double deg)
  function radToDeg (line 159) | double radToDeg (double rad)
  function angleVectorVector (line 168) | double angleVectorVector (CGVector3D a, CGVector3D b)

FILE: src/water.c
  function Water (line 24) | Water * getWaterList(void){
  function calcWaterAttributes (line 28) | void calcWaterAttributes (double interval) {
  function calcFixWaterPoints (line 114) | void calcFixWaterPoints(Terrain * terrain)
  function setRandomize (line 133) | void setRandomize(void) {
  function pushSomeWaterDown (line 137) | void pushSomeWaterDown(void)
  function toggleWaterMovement (line 151) | void toggleWaterMovement(void)
  function GLuint (line 156) | GLuint * getWaterIndices (void)
  function initWaterIndices (line 161) | void initWaterIndices(void) {
  function initWater (line 186) | void initWater(void) {
Condensed preview — 33 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (152K chars).
[
  {
    "path": "LICENSE",
    "chars": 769,
    "preview": "Copyright (c) 2015, 2016 Maurice Tollmien <maurice.tollmien@gmail.com>\n\nPermission to use, copy, modify, and/or distribu"
  },
  {
    "path": "README.md",
    "chars": 5614,
    "preview": "# Water-Simulation with Realtime Reflections/Refractions from the Surface\nThis project consists of several smaller proje"
  },
  {
    "path": "src/Makefile",
    "chars": 1141,
    "preview": "# Quelldateien\nSRCS             = imageLoader.c vector.c main.c scene.c io.c water.c terrain.c logic.c stringOutput.c \n\n"
  },
  {
    "path": "src/Makefile.common",
    "chars": 2151,
    "preview": "# Objektdateien\nOBJS             = $(SRCS:.c=.o)\n\n# Compiler\nCC               = gcc\n\n# Precompiler flags\nCPPFLAGS_LINUX "
  },
  {
    "path": "src/Makefile.depend",
    "chars": 550,
    "preview": "imageLoader.o: imageLoader.c imageLoader.h\nvector.o: vector.c stringOutput.h types.h\nmain.o: main.c io.h scene.h types.h"
  },
  {
    "path": "src/colorFragmentShader.frag",
    "chars": 118,
    "preview": "#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",
    "chars": 173,
    "preview": "#version 330 \n\nlayout (location = 0) in vec3 vertPos; \nuniform mat4 viewMatrix, projMatrix; \n\nvoid main(){ \n\tgl_Position"
  },
  {
    "path": "src/imageLoader.c",
    "chars": 2522,
    "preview": "\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <math.h>\n/* ---- Eigene Header einbinden ---- */\n#i"
  },
  {
    "path": "src/imageLoader.h",
    "chars": 477,
    "preview": "#ifndef __IMAGE_H__\n#define __IMAGE_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * Programmlogik und Datenhaltung\n *\n * @aut"
  },
  {
    "path": "src/io.c",
    "chars": 39878,
    "preview": "\n\n/**\n * @file\n * Hier sind alle CallBack-Funktionen\n *\n * @author Maurice Tollmien, Tilman Nedele\n */\n\n/* ---- System H"
  },
  {
    "path": "src/io.h",
    "chars": 464,
    "preview": "#ifndef __IO_H__\n#define __IO_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * CallBack-Funktionsköpfe\n *\n * @author Maurice T"
  },
  {
    "path": "src/logic.c",
    "chars": 11033,
    "preview": "\n/**\n * @file\n * Hier ist die Datenhaltung und Programmlogik\n *\n * @author Tilman Nedele, Maurice Tollmien\n */\n\n/* ---- "
  },
  {
    "path": "src/logic.h",
    "chars": 1930,
    "preview": "#ifndef __LOGIC_H__\n#define __LOGIC_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * Programmlogik und Datenhaltung\n *\n * @aut"
  },
  {
    "path": "src/main.c",
    "chars": 902,
    "preview": "/**\n * @file\n * ein erster Versuch, eine eigene Datei zu erstellen...\n * @author Maurice Tollmien.\n */\n\n/* ---- System H"
  },
  {
    "path": "src/particle.c",
    "chars": 18609,
    "preview": "\n\n/**\n * @file\n * Hier ist die Datenhaltung und Programmlogik\n *\n * @author Tilman Nedele, Maurice Tollmien\n */\n\n/* ----"
  },
  {
    "path": "src/particle.h",
    "chars": 915,
    "preview": "#ifndef __PARTICLE_H__\n#define __PARTICLE_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * Programmlogik und Datenhaltung\n *\n "
  },
  {
    "path": "src/scene.c",
    "chars": 15695,
    "preview": "\n/**\n * @file\n * Hier wird vll gezeichnet...\n *\n * @author Maurice Tollmien, Tilman Nedele\n */\n\n/* ---- System Header ei"
  },
  {
    "path": "src/scene.h",
    "chars": 615,
    "preview": "#ifndef __SCENE_H__\n#define __SCENE_H__\n\n#define __DEBUG_GL_H__\n/**\n * @file\n * hier kann gezeichnet werden (Hoffentlich"
  },
  {
    "path": "src/stringOutput.c",
    "chars": 2575,
    "preview": "/**\n * @file\n * Einfache Funktion zum Zeichnen von Text fuer GLUT-Programme.\n */\n\n/* ---- System Header einbinden ---- *"
  },
  {
    "path": "src/stringOutput.h",
    "chars": 747,
    "preview": "#ifndef _STRING_OUTPUT_H\n#define _STRING_OUTPUT_H\n/**\n * @file\n * Einfache Funktion zum Zeichnen von Text fuer GLUT-Prog"
  },
  {
    "path": "src/terrain.c",
    "chars": 6589,
    "preview": "\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <math.h>\n/* ---- Eigene Header einbinden ---- */\n#i"
  },
  {
    "path": "src/terrain.h",
    "chars": 753,
    "preview": "#ifndef __TERRAIN_H__\n#define __TERRAIN_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * Programmlogik und Datenhaltung\n *\n * "
  },
  {
    "path": "src/textureDepthFragmentShader.frag",
    "chars": 559,
    "preview": "#version 330 \n\nin vec2 texcoords; \nuniform sampler2D texsampler; \nout vec4 Color; \n\nfloat linearizeDepth (float depth) {"
  },
  {
    "path": "src/textureFragmentShader.frag",
    "chars": 2450,
    "preview": "#version 330 \n\nin vec2 texcoords; \nin vec3 normal;\nin float height;\nin vec3 causticNormal;\nuniform sampler2D texSand; \nu"
  },
  {
    "path": "src/textureVertexShader.vert",
    "chars": 479,
    "preview": "#version 330 \n\t\t\nlayout (location = 0) in vec3 vertPos; \nlayout (location = 1) in vec2 tex; \nlayout (location = 2) in ve"
  },
  {
    "path": "src/types.h",
    "chars": 5676,
    "preview": "#ifndef __TYPES_H__\n#define __TYPES_H__\n\n/**\n * @file\n * Typenschnittstelle.\n * Das Modul kapselt die Typdefinitionen un"
  },
  {
    "path": "src/vector.c",
    "chars": 3202,
    "preview": "/**\n * @file\n * Hier ist die Datenhaltung und Programmlogik\n *\n * @author Tilman Nedele, Maurice Tollmien\n */\n\n/* ---- S"
  },
  {
    "path": "src/vector.h",
    "chars": 1538,
    "preview": "#ifndef __VECTOR_H__\n#define __VECTOR_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * Programmlogik und Datenhaltung\n *\n * @a"
  },
  {
    "path": "src/water.c",
    "chars": 6107,
    "preview": "\n#include <stdio.h>\n#include <stddef.h>\n#include <stdlib.h>\n#include <math.h>\n/* ---- Eigene Header einbinden ---- */\n#i"
  },
  {
    "path": "src/water.h",
    "chars": 773,
    "preview": "#ifndef __WATER_H__\n#define __WATER_H__\n#define __DEBUG_GL_H__\n/**\n * @file\n * Programmlogik und Datenhaltung\n *\n * @aut"
  },
  {
    "path": "src/waterFragmentShader.frag",
    "chars": 4458,
    "preview": "#version 330 \n\t\t\n\nin vec3 pos_vec; \nin vec3 normal; \nin vec3 pos_cam;\nin vec3 backgroundColor;\nin float height;\nuniform "
  },
  {
    "path": "src/waterVertexShader.vert",
    "chars": 496,
    "preview": "#version 330 \n\t\t\nlayout (location = 0) in vec3 vertPos; \nlayout (location = 1) in vec3 normal_in; \nlayout (location = 2)"
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the MauriceGit/Water_Simulation GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 33 files (136.7 KB), approximately 45.3k tokens, and a symbol index with 168 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!