#include "Kam3D.h" #include "Welt3D.h" #include "Shader.h" #include "TastaturEreignis.h" #include "Globals.h" #include "MausEreignis.h" #include #include using namespace Framework; // Inhalt der Kam3D Klasse // Konstruktor Kam3D::Kam3D() : ReferenceCounter() { openingAngle = (float)PI / 4; minZ = 0.1f; maxZ = 5000; pos = Vec3< float >( 0, 0, -1000 ); rotX = 0; rotY = 0; rotZ = 0; viewport.x = 0; viewport.y = 0; viewport.front = 0.f; viewport.back = 1.f; viewport.width = 200; viewport.height = 200; welt = 0; style = 0; updateMatrix(); } // Destruktor Kam3D::~Kam3D() { if( welt ) welt->release(); } // private // Aktualisiert die view und projektion matrizen void Kam3D::updateMatrix() { view = view.rotationX( -rotX ) * view.rotationY( -rotY ) * view.rotationZ( -rotZ ) * view.translation( Vec3< float >( -pos.x, -pos.y, -pos.z ) ); proj = proj.projektion( openingAngle, viewport.width / viewport.height, minZ, maxZ ); } // Setzt die Position der Kamera in der 3D Welt void Kam3D::setPosition( Vec3< float > pos ) { this->pos = pos; updateMatrix(); } // zoomt heran, indem sich die Kamera etwas auf das Blickziel zubewegt // val: Die länge der Strecke um die sich die Kamera bewegen soll void Kam3D::scrollIn( float val ) { Vec3< float > n( 0, 0, 1 ); Mat4< float > tmp = tmp.rotationY( rotY ) * tmp.rotationX( rotX ) * tmp.rotationZ( rotZ ); n = tmp * n * val; pos += n; } // zppmt heraus, indem sich die Kamera etwas von dem Blockziel entfernt // val: Die länge der Strecke um die sich die Kamera bewegen soll void Kam3D::scrollOut( float val ) { Vec3< float > n( 0, 0, 1 ); Mat4< float > tmp = tmp.rotationY( rotY ) * tmp.rotationX( rotX ) * tmp.rotationZ( rotZ ); n = tmp * n * val; pos -= n; } // Richtet die Kamera so aus, dass sie genau auf einen bestimmten Punkt zeigt // ziel: Der Punkt, auf den die Kamera zeigen soll void Kam3D::setAusrichtung( Vec3< float > ziel ) { Vec3< float > target = ( ziel - pos ).normalize(); if( Vec3< float >( 0, target.y, target.z ).getLength() == 0 ) rotX = 0; else rotX = -lowPrecisionACos( target.z / Vec3< float >( 0, target.y, target.z ).getLength() ); if( target.y < 0 ) rotX = -rotX; if( Vec3< float >( target.x, 0, target.z ).getLength() == 0 ) rotY = 0; else rotY = lowPrecisionACos( abs( target.z ) / Vec3< float >( target.x, 0, target.z ).getLength() ); if( target.x < 0 ) rotY = -rotY; rotZ = 0; updateMatrix(); } // Setzt die Position des Bildes auf dem Bildschirm // p: Ein Punkt mit x und y Koordinaten in Pixeln void Kam3D::setBildschirmPosition( Punkt p ) { viewport.x = (float)p.x; viewport.y = (float)p.y; } // Setzt die Position des Bildes auf dem Bildschirm // x: Die x Koordinate in Pixeln // y: Die y Koordinate in Pixeln void Kam3D::setBildschirmPosition( int x, int y ) { viewport.x = (float)x; viewport.y = (float)y; } // Setzt die Größe des Bildes auf dem Bildschirm // p: Ein Punkt, mit x als Breite und y als Höhe in Pixlen void Kam3D::setBildschirmSize( Punkt p ) { viewport.width = (float)p.x; viewport.height = (float)p.y; updateMatrix(); } // Setzt die Größe des Bildes auf dem Bildschirm // br: Die Breite in Pixeln // hö: Die Höhe in Pixeln void Kam3D::setBildschirmSize( int br, int hö ) { viewport.width = (float)br; viewport.height = (float)hö; updateMatrix(); } // Setzt die Welt, die gezeichnet werden soll // w: Die Welt void Kam3D::setWelt( Welt3D *w ) { if( welt ) welt->release(); welt = w; } // Setzt den Style der Kamera // style: Der neue Style bestehend aus den Flags aus der zugehörigen Style Klasse void Kam3D::setStyle( __int64 style ) { this->style = style; } // Setzt den Style der Kamera // style: Alle Style Flags, die verändert werden sollen // add_remove: 1, falls der Style hinzugefügt werden soll. 0, falls der Style entfernt weden soll void Kam3D::setStyle( __int64 style, bool add_remove ) { if( add_remove ) this->style |= style; else if( !add_remove ) this->style &= ~style; } // Fügt Style Flags hinzu // style: Der Style, der hinzugefügt werden soll void Kam3D::addStyle( __int64 style ) { this->style |= style; } // Entfernt Style Flags // style: Der Style, der entfernt werden soll void Kam3D::removeStyle( __int64 style ) { this->style &= ~style; } // Verarbeitet die vergangene Zeit // tickval: Die zeit in sekunden, die seit dem letzten Aufruf der Funktion vergangen ist // return: true, wenn sich das Bild neu gezeichnet werden muss, false sonnst. bool Kam3D::tick( double tv ) { bool ret = 0; if( hatStyle( Style::Rotatable ) ) { if( getTastenStand( T_Oben ) ) { rotX -= (float)tv; ret = 1; } if( getTastenStand( T_Unten ) ) { rotX += (float)tv; ret = 1; } if( getTastenStand( T_Links ) ) { rotY -= (float)tv; ret = 1; } if( getTastenStand( T_Rechts ) ) { rotY += (float)tv; ret = 1; } } if( hatStyle( Style::Movable ) ) { Vec3< float > n( 0, 0, 1 ); Vec3< float > n2( 1, 0, 0 ); Vec3< float > n3( 0, 1, 0 ); Mat4< float > tmp = tmp.rotationY( rotY ) * tmp.rotationX( rotX ); n = tmp * n; n = n * (float)tv * 60; n2 = tmp * n2; n2 = n2 * (float)tv * 60; n3 = tmp * n3; n3 = n3 * (float)tv * 60; if( getTastenStand( 'w' ) ) { pos += n; ret = 1; } if( getTastenStand( 's' ) ) { pos -= n; ret = 1; } if( getTastenStand( 'd' ) ) { pos += n2; ret = 1; } if( getTastenStand( 'a' ) ) { pos -= n2; ret = 1; } if( getTastenStand( ' ' ) ) { pos += n3; ret = 1; } if( getTastenStand( T_Shift ) ) { pos -= n3; ret = 1; } } updateMatrix(); if( welt && hatStyle( Style::Tick ) ) return welt->tick( tv ) || ret; return ret; } // Verarbeitet ein Mausereignis // me: Das Mausereignis, das verarbeitet werden soll void Kam3D::doMausEreignis( MausEreignis &me ) { if( me.verarbeitet ) return; if( me.mx > viewport.x && me.my > viewport.y && me.mx < viewport.x + viewport.width && me.my < viewport.y + viewport.height ) { MausEreignis3D me3d; me3d.id = me.id; me3d.verarbeitet = me.verarbeitet; Vec3< float > mausP = Vec3< float >( ( me.mx - viewport.x ) / ( 0.5f * viewport.width ) - 1, ( me.my - viewport.y ) / ( 0.5f * viewport.height ) - 1, 0 ); Vec3< float > mausT = Vec3< float >( mausP.x, mausP.y, 1 ); Mat4< float > mat = proj * view; mat = mat.getInverse(); mausP = mat * mausP; mausT = mat * mausT; me3d.pos = mausP; me3d.dir = mausT - mausP; me.verarbeitet = 1; } } // Verarbeitet ein Tastaturereignis // te: das Tastaturereignis, das verarbeitet werden soll void Kam3D::doTastaturEreignis( TastaturEreignis &te ) { } // Gibt zurück, ob bestimmte Styles gesetzt wurden // style: Die Styles, die überprüft werden sollen // return: 1, falls alle Styles in style gesetzt wurden bool Kam3D::hatStyle( __int64 style ) const { return ( this->style | style ) == this->style; } // Gibt zurück, ob bestimmte Styles nicht gesetzt wurden // style: Die Styles, die geprüft werden sollen // return: 1, falls alle Styles in style nicht gesetzt wurden bool Kam3D::hatStyleNicht( __int64 style ) const { return ( this->style | style ) != this->style; } // Gibt einen Zeiger auf den Viewport zurück const ViewPort *Kam3D::zViewPort() const { return &viewport; } // Gibt die Position der Kamera in der Welt zurück const Vec3< float > &Kam3D::getWorldPosition() const { return pos; } // Gibt die Position in der Welt zurück // screen: die Position auf dem Bildschirm, die übersetzt werden soll const Vec3< float > Kam3D::getWorldPosition( Punkt screen ) const { Vec3< float > point = Vec3< float >( ( screen.x - viewport.x ) / ( 0.5f * viewport.width ) - 1, ( viewport.height - ( screen.y - viewport.y ) ) / ( 0.5f * viewport.height ) - 1, 0.1f ); Mat4< float > mat = getProjectionMatrix(); Mat4< float > inv = getViewMatrix().getInverse(); point.x = ( point.x * 0.1f ) / mat.elements[ 0 ][ 0 ]; point.y = ( point.y * 0.1f ) / mat.elements[ 1 ][ 1 ]; return inv * point; } // Gibt die Richtung der Kamera in der Welt zurück // screen: die Position auf dem Bildschirm, die übersetzt werden soll const Vec3< float > Kam3D::getWorldDirection( Punkt screen ) const { Vec3< float > point = Vec3< float >( ( screen.x - viewport.x ) / ( 0.5f * viewport.width ) - 1, ( viewport.height - ( screen.y - viewport.y ) ) / ( 0.5f * viewport.height ) - 1, 0.1f ); Vec3< float > pointT = Vec3< float >( point.x, point.y, 1 ); Mat4< float > mat = getProjectionMatrix(); Mat4< float > inv = getViewMatrix().getInverse(); point.x = ( point.x * 0.1f ) / mat.elements[ 0 ][ 0 ]; point.y = ( point.y * 0.1f ) / mat.elements[ 1 ][ 1 ]; pointT.x = ( pointT.x ) / mat.elements[ 0 ][ 0 ]; pointT.y = ( pointT.y ) / mat.elements[ 1 ][ 1 ]; point = inv * point; pointT = inv * pointT; return pointT - point; } // Gibt die Projektionsmatrix der Kamera zurück const Mat4< float > &Kam3D::getProjectionMatrix() const { return proj; } // Gibt die Ansichtsmatrix der Kamera zurück const Mat4< float > &Kam3D::getViewMatrix() const { return view; } // Gibt die Welt zurück Welt3D *Kam3D::getWelt() const { return welt ? (Welt3D *)welt->getThis() : 0; } // Gibt die Welt zurück Welt3D *Kam3D::zWelt() const { return welt; }