#include <main.h>
#include <Fenster.h>
#include <Bildschirm.h>
#include <RenderThread.h>
#include <Welt3D.h>
#include <Cube.h>
#include <Kam3D.h>
#include <Bild.h>
#include <Rahmen.h>
#include <Textur.h>
#include <Model3D.h>
#include <Model3DList.h>
#include <DXBuffer.h>
#include <DateiSystem.h>
#include <M3Datei.h>
#include <GraphicsApi.h>
#include <Mat4.h>
#include <M3Datei.h>

#define ambient  0.4f
#define diffus   0.3f
#define specular 0.3f

using namespace Framework;


void makeQuader( Vertex3D *vertecies, int startIndex, Vec3< float > ltf, Vec3< float > rtf, Vec3< float > lbf, Vec3< float > rbf, Vec3< float > ltb, Vec3< float > rtb, Vec3< float > lbb, Vec3< float > rbb, Model3DData *zModel )
{
    vertecies[ startIndex ].pos = ltf;
    vertecies[ startIndex ].tPos = Vec2< float >( 0.f, 0.f );
    vertecies[ startIndex + 1 ].pos = rtf;
    vertecies[ startIndex + 1 ].tPos = Vec2< float >( 1.f, 0.f );
    vertecies[ startIndex + 2 ].pos = lbf;
    vertecies[ startIndex + 2 ].tPos = Vec2< float >( 0.f, 1.f );
    vertecies[ startIndex + 3 ].pos = rbf;
    vertecies[ startIndex + 3 ].tPos = Vec2< float >( 1.f, 1.f );
    vertecies[ startIndex + 4 ].pos = ltb;
    vertecies[ startIndex + 4 ].tPos = Vec2< float >( 0.0f, 0.0f );
    vertecies[ startIndex + 5 ].pos = rtb;
    vertecies[ startIndex + 5 ].tPos = Vec2< float >( 1.0f, 0.0f );
    vertecies[ startIndex + 6 ].pos = lbb;
    vertecies[ startIndex + 6 ].tPos = Vec2< float >( 0.0f, 1.0f );
    vertecies[ startIndex + 7 ].pos = rbb;
    vertecies[ startIndex + 7 ].tPos = Vec2< float >( 1.0f, 1.0f );

    vertecies[ startIndex + 8 ].pos = ltf;
    vertecies[ startIndex + 8 ].tPos = Vec2< float >( 1.f, 0.f );
    vertecies[ startIndex + 9 ].pos = rtf;
    vertecies[ startIndex + 9 ].tPos = Vec2< float >( 0.f, 0.f );
    vertecies[ startIndex + 10 ].pos = lbf;
    vertecies[ startIndex + 10 ].tPos = Vec2< float >( 1.f, 1.f );
    vertecies[ startIndex + 11 ].pos = rbf;
    vertecies[ startIndex + 11 ].tPos = Vec2< float >( 0.f, 1.f );
    vertecies[ startIndex + 12 ].pos = ltb;
    vertecies[ startIndex + 12 ].tPos = Vec2< float >( 0.0f, 0.0f );
    vertecies[ startIndex + 13 ].pos = rtb;
    vertecies[ startIndex + 13 ].tPos = Vec2< float >( 1.0f, 0.0f );
    vertecies[ startIndex + 14 ].pos = lbb;
    vertecies[ startIndex + 14 ].tPos = Vec2< float >( 0.0f, 1.0f );
    vertecies[ startIndex + 15 ].pos = rbb;
    vertecies[ startIndex + 15 ].tPos = Vec2< float >( 1.0f, 1.0f );

    vertecies[ startIndex + 16 ].pos = ltf;
    vertecies[ startIndex + 16 ].tPos = Vec2< float >( 0.f, 1.f );
    vertecies[ startIndex + 17 ].pos = rtf;
    vertecies[ startIndex + 17 ].tPos = Vec2< float >( 1.f, 1.f );
    vertecies[ startIndex + 18 ].pos = lbf;
    vertecies[ startIndex + 18 ].tPos = Vec2< float >( 0.f, 0.f );
    vertecies[ startIndex + 19 ].pos = rbf;
    vertecies[ startIndex + 19 ].tPos = Vec2< float >( 1.f, 0.f );
    vertecies[ startIndex + 20 ].pos = ltb;
    vertecies[ startIndex + 20 ].tPos = Vec2< float >( 0.0f, 0.0f );
    vertecies[ startIndex + 21 ].pos = rtb;
    vertecies[ startIndex + 21 ].tPos = Vec2< float >( 1.0f, 0.0f );
    vertecies[ startIndex + 22 ].pos = lbb;
    vertecies[ startIndex + 22 ].tPos = Vec2< float >( 0.0f, 1.0f );
    vertecies[ startIndex + 23 ].pos = rbb;
    vertecies[ startIndex + 23 ].tPos = Vec2< float >( 1.0f, 1.0f );

    // front side
    Polygon3D *p = new Polygon3D();
    p->indexAnz = 6;
    p->indexList = new int[ p->indexAnz ];
    p->indexList[ 0 ] = startIndex + 0;
    p->indexList[ 1 ] = startIndex + 2;
    p->indexList[ 2 ] = startIndex + 3;
    p->indexList[ 3 ] = startIndex + 0;
    p->indexList[ 4 ] = startIndex + 3;
    p->indexList[ 5 ] = startIndex + 1;
    zModel->addPolygon( p );
    // back side
    p = new Polygon3D();
    p->indexAnz = 6;
    p->indexList = new int[ p->indexAnz ];
    p->indexList[ 0 ] = startIndex + 4;
    p->indexList[ 1 ] = startIndex + 7;
    p->indexList[ 2 ] = startIndex + 6;
    p->indexList[ 3 ] = startIndex + 4;
    p->indexList[ 4 ] = startIndex + 5;
    p->indexList[ 5 ] = startIndex + 7;
    zModel->addPolygon( p );
    // right side
    p = new Polygon3D();
    p->indexAnz = 6;
    p->indexList = new int[ p->indexAnz ];
    p->indexList[ 0 ] = startIndex + 1 + 8;
    p->indexList[ 1 ] = startIndex + 3 + 8;
    p->indexList[ 2 ] = startIndex + 7 + 8;
    p->indexList[ 3 ] = startIndex + 1 + 8;
    p->indexList[ 4 ] = startIndex + 7 + 8;
    p->indexList[ 5 ] = startIndex + 5 + 8;
    zModel->addPolygon( p );
    // left side
    p = new Polygon3D();
    p->indexAnz = 6;
    p->indexList = new int[ p->indexAnz ];
    p->indexList[ 0 ] = startIndex + 0 + 8;
    p->indexList[ 1 ] = startIndex + 6 + 8;
    p->indexList[ 2 ] = startIndex + 2 + 8;
    p->indexList[ 3 ] = startIndex + 0 + 8;
    p->indexList[ 4 ] = startIndex + 4 + 8;
    p->indexList[ 5 ] = startIndex + 6 + 8;
    zModel->addPolygon( p );
    // top side
    p = new Polygon3D();
    p->indexAnz = 6;
    p->indexList = new int[ p->indexAnz ];
    p->indexList[ 0 ] = startIndex + 4 + 16;
    p->indexList[ 1 ] = startIndex + 0 + 16;
    p->indexList[ 2 ] = startIndex + 1 + 16;
    p->indexList[ 3 ] = startIndex + 4 + 16;
    p->indexList[ 4 ] = startIndex + 1 + 16;
    p->indexList[ 5 ] = startIndex + 5 + 16;
    zModel->addPolygon( p );
    // down side
    p = new Polygon3D();
    p->indexAnz = 6;
    p->indexList = new int[ p->indexAnz ];
    p->indexList[ 0 ] = startIndex + 6 + 16;
    p->indexList[ 1 ] = startIndex + 3 + 16;
    p->indexList[ 2 ] = startIndex + 2 + 16;
    p->indexList[ 3 ] = startIndex + 6 + 16;
    p->indexList[ 4 ] = startIndex + 7 + 16;
    p->indexList[ 5 ] = startIndex + 3 + 16;
    zModel->addPolygon( p );
}

void makeQuader( Vertex3D *vertecies, int startIndex, Vec3< float > pos, Vec3< float > size, Model3DData *zModel )
{
    float left, right, top, bottom;
    // Calculate the screen coordinates of the left side of the bitmap.
    left = pos.x;
    // Calculate the screen coordinates of the right side of the bitmap.
    right = pos.x + size.x;
    // Calculate the screen coordinates of the top of the bitmap.
    top = pos.y + size.y;
    // Calculate the screen coordinates of the bottom of the bitmap.
    bottom = pos.y;
    float front = pos.z + size.z;
    float back = pos.z;

    makeQuader( vertecies, startIndex, Vec3< float >( left, top, front ), Vec3< float >( right, top, front ), Vec3< float >( left, bottom, front ), Vec3< float >( right, bottom, front ),
                Vec3< float >( left, top, back ), Vec3< float >( right, top, back ), Vec3< float >( left, bottom, back ), Vec3< float >( right, bottom, back ), zModel );
}

class Treppe : public Model3D
{
public:
    // Konstruktor
    //  size: Die Größe des Würfels
    Treppe()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 11 * 24 ];
        for( int i = 0; i < 11 * 24; i++ )
            vertecies[ i ].knochenId = 0;
        for( int i = 0; i < 11; i++ )
        {
            float fullRad = (float)PI;
            float curr = ( fullRad / 10 ) * i;
            Mat4< float > rotation = Mat4< float >::rotationZ( curr );
            Mat4< float > rotation2 = Mat4< float >::rotationZ( fullRad / 10 );
            Vec3< float > test( 50, 0, -50 - i * 10 );
            Vec3< float > diff = rotation2 * test;
            Vec3< float > rbf( 50, -diff.y / 2, -50 + i * 10 + 20 );
            Vec3< float > rtf( 50, diff.y / 2, -50 + i * 10 + 20 );
            Vec3< float > rbb( 50, -diff.y / 2, -50 + i * 10 + 10 );
            Vec3< float > rtb( 50, diff.y / 2, -50 + i * 10 + 10 );
            Vec3< float > ltf( 0, 5, -50 + i * 10 + 20 );
            Vec3< float > lbf( 0, -5, -50 + i * 10 + 20 );
            Vec3< float > ltb( 0, 5, -50 + i * 10 + 10 );
            Vec3< float > lbb( 0, -5, -50 + i * 10 + 10 );
            rtf = rotation * rtf;
            rtb = rotation * rtb;
            rbf = rotation * rbf;
            rbb = rotation * rbb;
            ltf = rotation * ltf;
            ltb = rotation * ltb;
            lbf = rotation * lbf;
            lbb = rotation * lbb;
            makeQuader( vertecies, i * 24, ltf, rtf, lbf, rbf, ltb, rtb, lbb, rbb, model );
        }
        model->setVertecies( vertecies, 24 * 11 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }
    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }
};

class Mauer : public Model3D
{
public:
    // Konstruktor
    //  size: Die Größe des Würfels
    Mauer()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 24 ];
        for( int i = 0; i < 24; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -50, -5, -50 ), Vec3< float >( 100, 10, 100 ), model );
        model->setVertecies( vertecies, 24 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }
    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }
};

class MauerEcke : public Model3D
{
public:
    // Konstruktor
    //  size: Die Größe des Würfels
    MauerEcke()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );
        float stdSize = 100;
        float left, right, top, bottom;
        // Calculate the screen coordinates of the left side of the bitmap.
        left = (float)( ( stdSize / 2.0 ) * -1 );
        // Calculate the screen coordinates of the right side of the bitmap.
        right = left + (float)stdSize;
        // Calculate the screen coordinates of the top of the bitmap.
        top = (float)( stdSize / 2.0 );
        // Calculate the screen coordinates of the bottom of the bitmap.
        bottom = top - (float)stdSize;
        float front = -stdSize / 2;
        float back = front + stdSize;

        Vertex3D *vertecies = new Vertex3D[ 48 ];
        for( int i = 0; i < 48; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( 0, -5, -50 ), Vec3< float >( 50, 10, 100 ), model );
        makeQuader( vertecies, 24, Vec3< float >( -5, 0, -50 ), Vec3< float >( 10, 50, 100 ), model );
        model->setVertecies( vertecies, 48 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }
    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }
};

class MauerKreuz : public Model3D
{
public:
    // Konstruktor
    //  size: Die Größe des Würfels
    MauerKreuz()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 48 ];
        for( int i = 0; i < 48; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -50, -5, -50 ), Vec3< float >( 100, 10, 100 ), model );
        makeQuader( vertecies, 24, Vec3< float >( -5, -50, -50 ), Vec3< float >( 10, 100, 100 ), model );
        model->setVertecies( vertecies, 48 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }
    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }
};

class Boden : public Model3D
{
public:
    // Konstruktor
    //  size: Die Größe des Würfels
    Boden()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 24 ];
        for( int i = 0; i < 24; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -50, -50, -10 ), Vec3< float >( 100, 100, 10 ), model );
        model->setVertecies( vertecies, 24 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }
    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }
};

class HalberBoden : public Model3D
{
public:
    // Konstruktor
    //  size: Die Größe des Würfels
    HalberBoden()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 24 ];
        for( int i = 0; i < 24; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -50, 0, -50 ), Vec3< float >( 100, 50, 10 ), model );
        model->setVertecies( vertecies, 24 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }
    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }
};

class TürZu : public Model3D
{
public:
    // Konstruktor
    //  size: Die Größe des Würfels
    TürZu()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 216 ];
        for( int i = 0; i < 216; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -50, -5, -50 ), Vec3< float >( 15, 10, 100 ), model ); // linke wand
        makeQuader( vertecies, 24, Vec3< float >( -35, -7, -50 ), Vec3< float >( 15, 15, 90 ), model ); // linker rahmen
        makeQuader( vertecies, 48, Vec3< float >( 20, -7, -50 ), Vec3< float >( 15, 15, 90 ), model ); // rechter rahmen
        makeQuader( vertecies, 72, Vec3< float >( -20, -7, 25 ), Vec3< float >( 40, 15, 15 ), model ); // oberer rahmen
        makeQuader( vertecies, 96, Vec3< float >( -20, -2, -50 ), Vec3< float >( 40, 5, 75 ), model ); // tür
        makeQuader( vertecies, 120, Vec3< float >( 12, -10, -2 ), Vec3< float >( 4, 20, 4 ), model ); // tür knauf
        makeQuader( vertecies, 144, Vec3< float >( 35, -5, -50 ), Vec3< float >( 15, 10, 100 ), model ); // rechte wand
        makeQuader( vertecies, 168, Vec3< float >( -50, -5, 40 ), Vec3< float >( 100, 10, 10 ), model ); // obere wand
        makeQuader( vertecies, 192, Vec3< float >( -50, -7, -50 ), Vec3< float >( 100, 15, 2 ), model ); // untere wand
        model->setVertecies( vertecies, 216 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }
    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }
};

class FensterZu : public Model3D
{
public:
    // Konstruktor
    //  size: Die Größe des Würfels
    FensterZu()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 216 ];
        for( int i = 0; i < 216; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -20, -2, -20 ), Vec3< float >( 40, 4, 40 ), model ); // fenster
        makeQuader( vertecies, 24, Vec3< float >( -50, -5, -50 ), Vec3< float >( 15, 10, 100 ), model ); // linke wand
        makeQuader( vertecies, 48, Vec3< float >( -35, -7, -35 ), Vec3< float >( 15, 15, 70 ), model ); // linker rahmen
        makeQuader( vertecies, 72, Vec3< float >( 20, -7, -35 ), Vec3< float >( 15, 15, 70 ), model ); // rechter rahmen
        makeQuader( vertecies, 96, Vec3< float >( -20, -7, 20 ), Vec3< float >( 40, 15, 15 ), model ); // oberer rahmen
        makeQuader( vertecies, 120, Vec3< float >( -20, -7, -35 ), Vec3< float >( 40, 15, 15 ), model ); // unterer rahmen
        makeQuader( vertecies, 144, Vec3< float >( 35, -5, -50 ), Vec3< float >( 15, 10, 100 ), model ); // rechte wand
        makeQuader( vertecies, 168, Vec3< float >( -50, -5, 35 ), Vec3< float >( 100, 10, 15 ), model ); // obere wand
        makeQuader( vertecies, 192, Vec3< float >( -50, -7, -50 ), Vec3< float >( 100, 15, 15 ), model ); // untere wand
        model->setVertecies( vertecies, 216 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }
    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }
};

class FensterOffen : public Model3D
{
public:
    // Konstruktor
    //  size: Die Größe des Würfels
    FensterOffen()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 216 ];
        for( int i = 0; i < 216; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -20, -2, -20 ), Vec3< float >( 4, 40, 40 ), model ); // fenster
        makeQuader( vertecies, 24, Vec3< float >( -50, -5, -50 ), Vec3< float >( 15, 10, 100 ), model ); // linke wand
        makeQuader( vertecies, 48, Vec3< float >( -35, -7, -35 ), Vec3< float >( 15, 15, 70 ), model ); // linker rahmen
        makeQuader( vertecies, 72, Vec3< float >( 20, -7, -35 ), Vec3< float >( 15, 15, 70 ), model ); // rechter rahmen
        makeQuader( vertecies, 96, Vec3< float >( -20, -7, 20 ), Vec3< float >( 40, 15, 15 ), model ); // oberer rahmen
        makeQuader( vertecies, 120, Vec3< float >( -20, -7, -35 ), Vec3< float >( 40, 15, 15 ), model ); // unterer rahmen
        makeQuader( vertecies, 144, Vec3< float >( 35, -5, -50 ), Vec3< float >( 15, 10, 100 ), model ); // rechte wand
        makeQuader( vertecies, 168, Vec3< float >( -50, -5, 35 ), Vec3< float >( 100, 10, 15 ), model ); // obere wand
        makeQuader( vertecies, 192, Vec3< float >( -50, -7, -50 ), Vec3< float >( 100, 15, 15 ), model ); // untere wand
        model->setVertecies( vertecies, 216 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }
    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }
};

class TürOffen : public Model3D
{
public:
    // Konstruktor
    //  size: Die Größe des Würfels
    TürOffen()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 216 ];
        for( int i = 0; i < 216; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -50, -5, -50 ), Vec3< float >( 15, 10, 100 ), model ); // linke wand
        makeQuader( vertecies, 24, Vec3< float >( -35, -7, -50 ), Vec3< float >( 15, 15, 90 ), model ); // linker rahmen
        makeQuader( vertecies, 48, Vec3< float >( 20, -7, -50 ), Vec3< float >( 15, 15, 90 ), model ); // rechter rahmen
        makeQuader( vertecies, 72, Vec3< float >( -20, -7, 25 ), Vec3< float >( 40, 15, 15 ), model ); // oberer rahmen
        makeQuader( vertecies, 96, Vec3< float >( -20, -2, -50 ), Vec3< float >( 5, 40, 75 ), model ); // tür
        makeQuader( vertecies, 120, Vec3< float >( -28, 30, -2 ), Vec3< float >( 20, 4, 4 ), model ); // tür knauf
        makeQuader( vertecies, 144, Vec3< float >( 35, -5, -50 ), Vec3< float >( 15, 10, 100 ), model ); // rechte wand
        makeQuader( vertecies, 168, Vec3< float >( -50, -5, 40 ), Vec3< float >( 100, 10, 10 ), model ); // obere wand
        makeQuader( vertecies, 192, Vec3< float >( -50, -7, -50 ), Vec3< float >( 100, 15, 2 ), model ); // untere wand
        model->setVertecies( vertecies, 216 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }
    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }
};

class Hero : public Model3D
{
public:
    // Konstruktor
    //  size: Die Größe des Würfels
    Hero()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 240 ];
        for( int i = 0; i < 240; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -7, -7, 20 ), Vec3< float >( 15, 15, 15 ), model ); // kopf
        makeQuader( vertecies, 24, Vec3< float >( -10, -4, -5 ), Vec3< float >( 20, 8, 25 ), model ); // oberkörper
        makeQuader( vertecies, 48, Vec3< float >( -20, -5, 10 ), Vec3< float >( 10, 10, 10 ), model ); // linke schulter
        makeQuader( vertecies, 72, Vec3< float >( 10, -5, 10 ), Vec3< float >( 10, 10, 10 ), model ); // rechte schulter
        makeQuader( vertecies, 96, Vec3< float >( -18, -3, -10 ), Vec3< float >( 5, 5, 30 ), model ); // linker arm
        makeQuader( vertecies, 120, Vec3< float >( 13, -3, -10 ), Vec3< float >( 5, 5, 30 ), model ); // rechter arm
        makeQuader( vertecies, 144, Vec3< float >( -10, -4, -30 ), Vec3< float >( 8, 8, 25 ), model ); // linkes bein
        makeQuader( vertecies, 168, Vec3< float >( 2, -4, -30 ), Vec3< float >( 8, 8, 25 ), model ); // rechtes bein
        makeQuader( vertecies, 192, Vec3< float >( -9, -10, -35 ), Vec3< float >( 6, 15, 5 ), model ); // linker fuß
        makeQuader( vertecies, 216, Vec3< float >( 3, -10, -35 ), Vec3< float >( 6, 15, 5 ), model ); // rechter fuß
        model->setVertecies( vertecies, 240 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }
    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }
};

class Unbekannt : public Model3D
{
public:
    Unbekannt()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 216 ];
        for( int i = 0; i < 216; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -5, -5, -25 ), Vec3< float >( 10, 10, 10 ), model );
        makeQuader( vertecies, 24, Vec3< float >( -5, -5, -10 ), Vec3< float >( 10, 10, 10 ), model );
        makeQuader( vertecies, 48, Vec3< float >( 0, -5, 0 ), Vec3< float >( 10, 10, 10 ), model );
        makeQuader( vertecies, 72, Vec3< float >( 5, -5, 10 ), Vec3< float >( 10, 10, 10 ), model );
        makeQuader( vertecies, 96, Vec3< float >( 10, -5, 20 ), Vec3< float >( 10, 10, 10 ), model );
        makeQuader( vertecies, 120, Vec3< float >( 5, -5, 30 ), Vec3< float >( 10, 10, 10 ), model );
        makeQuader( vertecies, 144, Vec3< float >( -5, -5, 35 ), Vec3< float >( 10, 10, 10 ), model );
        makeQuader( vertecies, 168, Vec3< float >( -15, -5, 30 ), Vec3< float >( 10, 10, 10 ), model );
        makeQuader( vertecies, 192, Vec3< float >( -20, -5, 20 ), Vec3< float >( 10, 10, 10 ), model );
        model->setVertecies( vertecies, 216 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }

    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }

    bool tick( double time ) override
    {
        this->setDrehungZ( getZDrehung() + time );
        return Model3D::tick( time );
    }
};

class Schrank : public Model3D
{
public:
    Schrank()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 216 ];
        for( int i = 0; i < 216; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -25, -15, -30 ), Vec3< float >( 50, 30, 70 ), model ); // haupt schrank
        makeQuader( vertecies, 24, Vec3< float >( -27, -17, 40 ), Vec3< float >( 54, 34, 2 ), model ); // dach
        makeQuader( vertecies, 48, Vec3< float >( -27, -17, -32 ), Vec3< float >( 54, 34, 2 ), model ); // boden
        makeQuader( vertecies, 72, Vec3< float >( -27, -17, -37 ), Vec3< float >( 10, 10, 77 ), model ); // fus
        makeQuader( vertecies, 96, Vec3< float >( 17, -17, -37 ), Vec3< float >( 10, 10, 77 ), model ); // fus
        makeQuader( vertecies, 120, Vec3< float >( -27, 7, -37 ), Vec3< float >( 10, 10, 77 ), model ); // fus
        makeQuader( vertecies, 144, Vec3< float >( 17, 7, -37 ), Vec3< float >( 10, 10, 77 ), model ); // fus
        makeQuader( vertecies, 168, Vec3< float >( -4, -17, -1 ), Vec3< float >( 2, 2, 2 ), model ); // griff
        makeQuader( vertecies, 192, Vec3< float >( 2, -17, -1 ), Vec3< float >( 2, 2, 2 ), model ); // griff
        model->setVertecies( vertecies, 216 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }

    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }

    bool tick( double time ) override
    {
        this->setDrehungZ( getZDrehung() + time );
        return Model3D::tick( time );
    }
};

class Stapel : public Model3D
{
public:
    Stapel()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 240 ];
        for( int i = 0; i < 240; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -25, -25, -25 ), Vec3< float >( 50, 50, 5 ), model );
        makeQuader( vertecies, 24, Vec3< float >( -20, -25, -20 ), Vec3< float >( 50, 50, 5 ), model );
        makeQuader( vertecies, 48, Vec3< float >( -25, -20, -15 ), Vec3< float >( 50, 50, 5 ), model );
        makeQuader( vertecies, 72, Vec3< float >( -30, -20, -10 ), Vec3< float >( 50, 50, 5 ), model );
        makeQuader( vertecies, 96, Vec3< float >( -25, -25, -5 ), Vec3< float >( 50, 50, 5 ), model );
        makeQuader( vertecies, 120, Vec3< float >( -20, -30, 0 ), Vec3< float >( 50, 50, 5 ), model );
        makeQuader( vertecies, 144, Vec3< float >( -25, -30, 5 ), Vec3< float >( 50, 50, 5 ), model );
        makeQuader( vertecies, 168, Vec3< float >( -30, -25, 10 ), Vec3< float >( 50, 50, 5 ), model );
        makeQuader( vertecies, 192, Vec3< float >( -25, -25, 15 ), Vec3< float >( 50, 50, 5 ), model );
        makeQuader( vertecies, 216, Vec3< float >( -20, -20, 20 ), Vec3< float >( 50, 50, 5 ), model );
        model->setVertecies( vertecies, 240 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }

    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }

    bool tick( double time ) override
    {
        this->setDrehungZ( getZDrehung() + time );
        return Model3D::tick( time );
    }
};

class Wanne : public Model3D
{
public:
    Wanne()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 120 ];
        for( int i = 0; i < 120; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -30, -15, -17 ), Vec3< float >( 60, 30, 2 ), model ); // boden
        makeQuader( vertecies, 24, Vec3< float >( -30, -15, -15 ), Vec3< float >( 5, 30, 30 ), model ); // wand links
        makeQuader( vertecies, 48, Vec3< float >( 25, -15, -15 ), Vec3< float >( 5, 30, 30 ), model ); // wand rechts
        makeQuader( vertecies, 72, Vec3< float >( -25, -15, -15 ), Vec3< float >( 50, 5, 30 ), model ); // wand forne
        makeQuader( vertecies, 96, Vec3< float >( -25, 10, -15 ), Vec3< float >( 50, 5, 30 ), model ); // wand hinten
        model->setVertecies( vertecies, 120 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }

    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }

    bool tick( double time ) override
    {
        this->setDrehungZ( getZDrehung() + time );
        return Model3D::tick( time );
    }
};

class Truhe : public Model3D
{
public:
    Truhe()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 144 ];
        for( int i = 0; i < 144; i++ )
            vertecies[ i ].knochenId = 0;
        makeQuader( vertecies, 0, Vec3< float >( -30, -15, -17 ), Vec3< float >( 60, 30, 2 ), model ); // boden
        makeQuader( vertecies, 24, Vec3< float >( -30, -15, -15 ), Vec3< float >( 5, 30, 30 ), model ); // wand links
        makeQuader( vertecies, 48, Vec3< float >( 25, -15, -15 ), Vec3< float >( 5, 30, 30 ), model ); // wand rechts
        makeQuader( vertecies, 72, Vec3< float >( -25, -15, -15 ), Vec3< float >( 50, 5, 30 ), model ); // wand forne
        makeQuader( vertecies, 96, Vec3< float >( -25, 10, -15 ), Vec3< float >( 50, 5, 30 ), model ); // wand hinten
        makeQuader( vertecies, 120, Vec3< float >( -32, -17, 15 ), Vec3< float >( 64, 34, 2 ), model ); // deckel
        model->setVertecies( vertecies, 144 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }

    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }

    bool tick( double time ) override
    {
        this->setDrehungZ( getZDrehung() + time );
        return Model3D::tick( time );
    }
};

class Fass : public Model3D
{
public:
    Fass()
    {
        model = new Model3DData();
        model->setAmbientFactor( ambient );
        model->setDiffusFactor( diffus );
        model->setSpecularFactor( specular );

        Vertex3D *vertecies = new Vertex3D[ 52 ];
        for( int i = 0; i < 52; i++ )
            vertecies[ i ].knochenId = 0;
        Vec3<float> p = Vec3<float>( 20, 0, -30 );
        Mat4<float> rm = Mat4<float>::rotationZ( (float)( 2 * PI / 8 ) );
        for( int i = 0; i < 8; i++ )
        {
            vertecies[ i ].pos = p;
            vertecies[ i ].tPos.x = ( p.x + 20.f ) / 40.f;
            vertecies[ i ].tPos.y = ( p.y + 20.f ) / 40.f;
            p = rm * p;
        }
        p = Vec3<float>( 20, 0, -30 );
        for( int i = 0; i < 9; i++ )
        {
            vertecies[ 8 + i ].pos = p;
            vertecies[ 8 + i ].tPos.x = 1.f - i * ( 1.f / 8.f );
            vertecies[ 8 + i ].tPos.y = 1.f;
            p = rm * p;
        }
        p = Vec3<float>( 25, 0, -10 );
        for( int i = 0; i < 9; i++ )
        {
            vertecies[ 17 + i ].pos = p;
            vertecies[ 17 + i ].tPos.x = 1.f - i * ( 1.f / 8.f );
            vertecies[ 17 + i ].tPos.y = 0.7777777f;
            p = rm * p;
        }
        p = Vec3<float>( 25, 0, 10 );
        for( int i = 0; i < 9; i++ )
        {
            vertecies[ 26 + i ].pos = p;
            vertecies[ 26 + i ].tPos.x = 1.f - i * ( 1.f / 8.f );
            vertecies[ 26 + i ].tPos.y = 0.3333333f;
            p = rm * p;
        }
        p = Vec3<float>( 20, 0, 30 );
        for( int i = 0; i < 9; i++ )
        {
            vertecies[ 35 + i ].pos = p;
            vertecies[ 35 + i ].tPos.x = 1.f - i * ( 1.f / 8.f );
            vertecies[ 35 + i ].tPos.y = 0.f;
            p = rm * p;
        }
        p = Vec3<float>( 20, 0, 30 );
        for( int i = 0; i < 8; i++ )
        {
            vertecies[ 44 + i ].pos = p;
            vertecies[ 44 + i ].tPos.x = ( p.x + 20.f ) / 40.f;
            vertecies[ 44 + i ].tPos.y = ( p.y + 20.f ) / 40.f;
            p = rm * p;
        }
        // top side
        Polygon3D *pol = new Polygon3D();
        pol->indexAnz = 18;
        pol->indexList = new int[ pol->indexAnz ];
        pol->indexList[ 0 ] = 44 + 0;
        pol->indexList[ 1 ] = 44 + 1;
        pol->indexList[ 2 ] = 44 + 2;
        pol->indexList[ 3 ] = 44 + 0;
        pol->indexList[ 4 ] = 44 + 2;
        pol->indexList[ 5 ] = 44 + 3;
        pol->indexList[ 6 ] = 44 + 0;
        pol->indexList[ 7 ] = 44 + 3;
        pol->indexList[ 8 ] = 44 + 4;
        pol->indexList[ 9 ] = 44 + 0;
        pol->indexList[ 10 ] = 44 + 4;
        pol->indexList[ 11 ] = 44 + 5;
        pol->indexList[ 12 ] = 44 + 0;
        pol->indexList[ 13 ] = 44 + 5;
        pol->indexList[ 14 ] = 44 + 6;
        pol->indexList[ 15 ] = 44 + 0;
        pol->indexList[ 16 ] = 44 + 6;
        pol->indexList[ 17 ] = 44 + 7;
        model->addPolygon( pol );
        // bottom side
        pol = new Polygon3D();
        pol->indexAnz = 18;
        pol->indexList = new int[ pol->indexAnz ];
        pol->indexList[ 0 ] = 0;
        pol->indexList[ 1 ] = 2;
        pol->indexList[ 2 ] = 1;
        pol->indexList[ 3 ] = 0;
        pol->indexList[ 4 ] = 3;
        pol->indexList[ 5 ] = 2;
        pol->indexList[ 6 ] = 0;
        pol->indexList[ 7 ] = 4;
        pol->indexList[ 8 ] = 3;
        pol->indexList[ 9 ] = 0;
        pol->indexList[ 10 ] = 5;
        pol->indexList[ 11 ] = 4;
        pol->indexList[ 12 ] = 0;
        pol->indexList[ 13 ] = 6;
        pol->indexList[ 14 ] = 5;
        pol->indexList[ 15 ] = 0;
        pol->indexList[ 16 ] = 7;
        pol->indexList[ 17 ] = 6;
        model->addPolygon( pol );
        // out side
        pol = new Polygon3D();
        pol->indexAnz = 18 * 8;
        pol->indexList = new int[ pol->indexAnz ];
        for( int i = 0; i < 8; i++ )
        {
            pol->indexList[ i * 18 + 0 ] = i + 8;
            pol->indexList[ i * 18 + 1 ] = i + 9;
            pol->indexList[ i * 18 + 2 ] = i + 17;

            pol->indexList[ i * 18 + 3 ] = i + 17;
            pol->indexList[ i * 18 + 4 ] = i + 9;
            pol->indexList[ i * 18 + 5 ] = i + 18;

            pol->indexList[ i * 18 + 6 ] = i + 26;
            pol->indexList[ i * 18 + 7 ] = i + 17;
            pol->indexList[ i * 18 + 8 ] = i + 18;

            pol->indexList[ i * 18 + 9 ] = i + 26;
            pol->indexList[ i * 18 + 10 ] = i + 18;
            pol->indexList[ i * 18 + 11 ] = i + 27;

            pol->indexList[ i * 18 + 12 ] = i + 35;
            pol->indexList[ i * 18 + 13 ] = i + 26;
            pol->indexList[ i * 18 + 14 ] = i + 27;

            pol->indexList[ i * 18 + 15 ] = i + 35;
            pol->indexList[ i * 18 + 16 ] = i + 27;
            pol->indexList[ i * 18 + 17 ] = i + 36;
        }
        model->addPolygon( pol );
        model->setVertecies( vertecies, 52 );

        model->calculateNormals();

        textur = new Model3DTextur();
    }

    // Setzt die Textur des Würfels, so dass sie an allen Seiten gleich ist
    //  textur: Die Textur als Bild
    void setTextur( Textur *textur )
    {
        int anz = model->getPolygonAnzahl();
        for( int i = 0; i < anz; i++ )
            this->textur->setPolygonTextur( i, textur->getThis() );
        textur->release();
        rend = 1;
    }

    bool tick( double time ) override
    {
        this->setDrehungZ( getZDrehung() + time );
        return Model3D::tick( time );
    }
};

// Aktion beim schließen des Fensters
void schließen( void *p, void *f )
{
    // Stoppe Nachrichten Loop
    StopNachrichtenSchleife( ( (WFenster *)f )->getFensterHandle() );
}

int __stdcall Framework::Start( Startparam p )
{
    /*Vec3< float > v1( 0, rand(), rand() );
    Vec3< float > v2 = v1 * rand();
    for( float angle = 1; angle <= 360; angle++ )
    {
        v2.rotateX( ( 1.f / 180.f ) * (float)PI );
        std::cout << "Angle: " << angle << " acos(x): " << v1.angle( v2 ) << " x: " << ( ( v1 * v2 ) / ( v1.getLength() * v2.getLength() ) ) << " y: " << ( ( v1 * v2 ) / ( v1.getLengthSq() * v2.getLengthSq() ) ) << " z: " << ( v1 * v2 ) << "\n";
    }
    v1 = Vec3< float >( 0, rand(), rand() );
    v2 = Vec3< float >( v1 * rand() );
    std::cout << "\n\n";
    for( float angle = 1; angle <= 360; angle++ )
    {
        v2.rotateX( -( 1.f / 180.f ) * (float)PI );
        std::cout << "Angle: " << -angle << " acos(x): " << v1.angle( v2 ) << " x: " << ( ( v1 * v2 ) / ( v1.getLength() * v2.getLength() ) ) << " y: " << ( ( v1 * v2 ) / ( v1.getLengthSq() * v2.getLengthSq() ) ) << " z: " << ( v1 * v2 ) << "\n";
    }
    return 0;*/
    // Fenster erstellen
    WNDCLASS wc = F_Normal( p.hinst );
    wc.lpszClassName = "3D Creator";

    WFenster *f = new WFenster();
    f->erstellen( WS_OVERLAPPEDWINDOW, wc );
    f->setVSchließAktion( schließen );
    f->setAnzeigeModus( SW_SHOWNORMAL );
    f->setSize( 1300, 820 );
    f->setPosition( Punkt( 100, 100 ) );

    // 3D Umgebung erstellen
    Bildschirm3D *b = new Bildschirm3D( f->getThis(), DIRECTX11 );
    f->setBildschirm( b->getThis() );
    b->setFillFarbe( 0 );
    b->setTestRend( 0 );

    Welt3D *welt = new Welt3D();

    LTDBDatei *assets = new LTDBDatei();
    assets->setDatei( new Text( "textures.ltdb" ) );
    assets->leseDaten( 0 );
    Bild *b1 = assets->laden( 0, new Text( "holz.png" ) );
    Textur *t = b->zGraphicsApi()->createOrGetTextur( "ground", b1 );
    assets->release();
    Treppe *test2 = new Treppe();
    test2->setTextur( t->getThis() );
    test2->setPosition( 150, 0, 0 );
    welt->addZeichnung( test2 );
    Mauer *test3 = new Mauer();
    test3->setTextur( t->getThis() );
    test3->setPosition( 150, 150, 0 );
    welt->addZeichnung( test3 );
    MauerEcke *test4 = new MauerEcke();
    test4->setTextur( t->getThis() );
    test4->setPosition( -150, 0, 0 );
    welt->addZeichnung( test4 );
    MauerKreuz *test5 = new MauerKreuz();
    test5->setTextur( t->getThis() );
    test5->setPosition( 0, 150, 0 );
    welt->addZeichnung( test5 );
    Boden *test6 = new Boden();
    test6->setTextur( t->getThis() );
    test6->setPosition( -150, 150, 0 );
    welt->addZeichnung( test6 );
    Unbekannt *test7 = new Unbekannt();
    test7->setTextur( t->getThis() );
    test7->setPosition( -250, 150, 0 );
    welt->addZeichnung( test7 );
    HalberBoden *test8 = new HalberBoden();
    test8->setTextur( t->getThis() );
    test8->setPosition( -150, 250, 0 );
    welt->addZeichnung( test8 );
    Hero *test9 = new Hero();
    test9->setTextur( t->getThis() );
    test9->setPosition( -250, 250, 0 );
    welt->addZeichnung( test9 );
    TürZu *test10 = new TürZu();
    test10->setTextur( t->getThis() );
    test10->setPosition( -350, 250, 0 );
    welt->addZeichnung( test10 );
    TürOffen *test11 = new TürOffen();
    test11->setTextur( t->getThis() );
    test11->setPosition( -250, 350, 0 );
    welt->addZeichnung( test11 );
    FensterZu *test12 = new FensterZu();
    test12->setTextur( t->getThis() );
    test12->setPosition( -350, 350, 0 );
    welt->addZeichnung( test12 );
    FensterOffen *test13 = new FensterOffen();
    test13->setTextur( t->getThis() );
    test13->setPosition( -350, 450, 0 );
    welt->addZeichnung( test13 );
    Fass *test14 = new Fass();
    test14->setTextur( t->getThis() );
    test14->setPosition( -350, 150, 0 );
    welt->addZeichnung( test14 );
    Schrank *test15 = new Schrank();
    test15->setTextur( t->getThis() );
    test15->setPosition( -350, 50, 0 );
    welt->addZeichnung( test15 );
    Stapel *test16 = new Stapel();
    test16->setTextur( t->getThis() );
    test16->setPosition( -350, -50, 0 );
    welt->addZeichnung( test16 );
    Wanne *test17 = new Wanne();
    test17->setTextur( t->getThis() );
    test17->setPosition( -350, -150, 0 );
    welt->addZeichnung( test17 );
    Truhe *test18 = new Truhe();
    test18->setTextur( t->getThis() );
    test18->setPosition( -250, -150, 0 );
    welt->addZeichnung( test18 );


    M3Datei m3;
    m3.setPfad( "models.m3" );
    m3.leseDaten();
    m3.saveModel( test2->zModelData(), "TREPPE" );
    m3.saveModel( test3->zModelData(), "MAUER" );
    m3.saveModel( test4->zModelData(), "mauer_ecke" );
    m3.saveModel( test5->zModelData(), "mauer_kreuz" );
    m3.saveModel( test6->zModelData(), "BODEN" );
    m3.saveModel( test8->zModelData(), "boden_halb" );
    m3.saveModel( test9->zModelData(), "HERO" );
    m3.saveModel( test9->zModelData(), "NPC" );
    m3.saveModel( test10->zModelData(), "TÜR (ZU)" );
    m3.saveModel( test11->zModelData(), "TÜR (OFFEN)" );
    m3.saveModel( test12->zModelData(), "FENSTER (ZU)" );
    m3.saveModel( test13->zModelData(), "FENSTER (OFFEN)" );
    m3.saveModel( test14->zModelData(), "FASS" );
    m3.saveModel( test15->zModelData(), "SCHRANK" );
    m3.saveModel( test16->zModelData(), "STAPEL" );
    m3.saveModel( test17->zModelData(), "WANNE" );
    m3.saveModel( test18->zModelData(), "TRUHE" );
    m3.saveModel( test7->zModelData(), "unbekannt" );


    t->release();

    Kam3D *kamA = new Kam3D();
    kamA->setBildschirmPosition( 10, 10 );
    kamA->setBildschirmSize( 385, 385 );
    kamA->setPosition( Vec3<float>( -1000, 0, 0 ) );
    kamA->setAusrichtung( Vec3<float>( 0, 0, 0 ) );
    kamA->setWelt( welt->getThis() );
    b->addKamera( kamA );

    Kam3D *kamB = new Kam3D();
    kamB->setBildschirmPosition( 10, 405 );
    kamB->setBildschirmSize( 385, 385 );
    kamB->setPosition( Vec3<float>( 0, -1000, 0 ) );
    kamB->setAusrichtung( Vec3<float>( 0, 0, 0 ) );
    kamB->setWelt( welt->getThis() );
    b->addKamera( kamB );

    Kam3D *kamC = new Kam3D();
    kamC->setBildschirmPosition( 405, 10 );
    kamC->setBildschirmSize( 385, 385 );
    kamC->setPosition( Vec3<float>( 0, 0, -1000 ) );
    kamC->setAusrichtung( Vec3<float>( 0, 0, 0 ) );
    kamC->setWelt( welt->getThis() );
    b->addKamera( kamC );

    Kam3D *kamD = new Kam3D();
    kamD->setStyle( Kam3D::Style::Movable | Kam3D::Style::Rotatable | Kam3D::Style::Tick );
    kamD->setBildschirmPosition( 405, 405 );
    kamD->setBildschirmSize( 385, 385 );
    kamD->setPosition( Vec3<float>( 0, 0, 1000 ) );
    kamD->setAusrichtung( Vec3<float>( 0, 0, 0 ) );
    kamD->setWelt( welt->getThis() );
    b->addKamera( kamD );

    LRahmen *kamAR = new LRahmen();
    kamAR->setPosition( 10, 10 );
    kamAR->setFarbe( 0xFFFFFFFF );
    kamAR->setRamenBreite( 1 );
    kamAR->setSize( 385, 385 );
    b->addMember( kamAR );
    LRahmen *kamBR = new LRahmen();
    kamBR->setPosition( 404, 10 );
    kamBR->setFarbe( 0xFFFFFFFF );
    kamBR->setRamenBreite( 1 );
    kamBR->setSize( 385, 385 );
    b->addMember( kamBR );
    LRahmen *kamCR = new LRahmen();
    kamCR->setPosition( 10, 405 );
    kamCR->setFarbe( 0xFFFFFFFF );
    kamCR->setRamenBreite( 1 );
    kamCR->setSize( 385, 385 );
    b->addMember( kamCR );
    LRahmen *kamDR = new LRahmen();
    kamDR->setPosition( 405, 405 );
    kamDR->setFarbe( 0xFFFFFFFF );
    kamDR->setRamenBreite( 1 );
    kamDR->setSize( 385, 385 );
    b->addMember( kamDR );

    // Render Loop starten
    RenderTh *r = new RenderTh();
    r->setMaxFps( 10000 );
    r->setBildschirm( b->getThis() );
    r->setTickFunktion( [ b, kamD ]( void *, void *, double t )
    {
        //test->setDrehung( test->getDrehung() + Vec3<double>( t, t, t ) );
        if( Framework::getTastenStand( T_Enter ) )
        {
            kamD->setAusrichtung( Vec3<float>( 0, 0, 0 ) );
        }
    } );
    r->beginn();

    // Nachrichten Loop starten und warten
    StartNachrichtenSchleife();

    // Speicher Freigeben
    r->beenden();
    r->release();
    b->release();
    f->setBildschirm( 0 );
    f->zerstören();
    f->release();
    welt->release();

    return 0;
}