#include "Kam3D.h" #include #include #include "Globals.h" #include "MausEreignis.h" #include "Shader.h" #include "TastaturEreignis.h" #include "Welt3D.h" using namespace Framework; // Inhalt der Kam3D Klasse // Konstruktor Kam3D::Kam3D() : ReferenceCounter(), rend(0) { openingAngle = (float)PI / 4; minZ = 0.1f; maxZ = 5000; pos = Vec3(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; speed = 1; 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(-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 pos) { this->pos = pos; rend = 1; 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 n(0, 0, 1); Mat4 tmp = tmp.rotationY(rotY) * tmp.rotationX(rotX) * tmp.rotationZ(rotZ); n = tmp * n * val; pos += n; rend = 1; updateMatrix(); } // 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 n(0, 0, 1); Mat4 tmp = tmp.rotationY(rotY) * tmp.rotationX(rotX) * tmp.rotationZ(rotZ); n = tmp * n * val; pos -= n; rend = 1; updateMatrix(); } // 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 ziel) { Vec3 target = (ziel - pos).normalize(); if (Vec3(0, target.y, target.z).getLength() == 0) rotX = 0; else rotX = -lowPrecisionACos( target.z / Vec3(0, target.y, target.z).getLength()); if (target.y < 0) rotX = -rotX; if (Vec3(target.x, 0, target.z).getLength() == 0) rotY = 0; else rotY = lowPrecisionACos( abs(target.z) / Vec3(target.x, 0, target.z).getLength()); if (target.x < 0) rotY = -rotY; rotZ = 0; rend = 1; updateMatrix(); } //! Legt die Drehung der Kamera um die einzelnen Axen fest //! \param rotation Die Drehung um die einzelnen Axen void Kam3D::setRotation(Vec3 rotation) { rotX = rotation.x; rotY = rotation.y; rotZ = rotation.z; rend = 1; 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; } //! Set the movement speed per second if the camera has style Movable void Kam3D::setMovementSpeed(float speed) { this->speed = speed; } // 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 = rend; rend = 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 n(0, 0, 1); Vec3 n2(1, 0, 0); Vec3 n3(0, 1, 0); Mat4 tmp = tmp.rotationY(rotY) * tmp.rotationX(rotX); n = tmp * n; n = n * (float)tv * speed; n2 = tmp * n2; n2 = n2 * (float)tv * speed; n3 = tmp * n3; n3 = n3 * (float)tv * speed; 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 mausP = Vec3((me.mx - viewport.x) / (0.5f * viewport.width) - 1, (me.my - viewport.y) / (0.5f * viewport.height) - 1, 0); Vec3 mausT = Vec3(mausP.x, mausP.y, 1); Mat4 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& 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 Kam3D::getWorldPosition(Punkt screen) const { Vec3 point = Vec3( (screen.x - viewport.x) / (0.5f * viewport.width) - 1, (viewport.height - (screen.y - viewport.y)) / (0.5f * viewport.height) - 1, 0.1f); Mat4 mat = getProjectionMatrix(); Mat4 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 Kam3D::getWorldDirection(Punkt screen) const { Vec3 point = Vec3( (screen.x - viewport.x) / (0.5f * viewport.width) - 1, (viewport.height - (screen.y - viewport.y)) / (0.5f * viewport.height) - 1, 0.1f); Vec3 pointT = Vec3(point.x, point.y, 1); Mat4 mat = getProjectionMatrix(); Mat4 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& Kam3D::getProjectionMatrix() const { return proj; } // Gibt die Ansichtsmatrix der Kamera zurück const Mat4& Kam3D::getViewMatrix() const { return view; } //! Gibt die Rotation um die einzelnen axen zurück const Vec3 Kam3D::getRotation() const { return {rotX, rotY, rotZ}; } //! Gibt die Position der Kamera auf dem Bildschirm zurück const Punkt Kam3D::getScreenPos() const { return Punkt((int)viewport.x, (int)viewport.y); } //! Gibt die Größe der Kamera auf dem Bildschirm zurück const Punkt Kam3D::getScreenSize() const { return Punkt((int)viewport.width, (int)viewport.height); } // Gibt die Welt zurück Welt3D* Kam3D::getWelt() const { return welt ? dynamic_cast(welt->getThis()) : 0; } // Gibt die Welt zurück Welt3D* Kam3D::zWelt() const { return welt; }