#include "Camera3D.h" #include #include #include "Globals.h" #include "MouseEvent.h" #include "Shader.h" #include "KeyboardEvent.h" #include "World3D.h" using namespace Framework; // Contents of the Kam3D class // Constructor 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(); } // Destructor Kam3D::~Kam3D() { if (welt) welt->release(); } // private // Updates the view and projection matrices 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); } // Sets the position of the camera in the 3D world void Kam3D::setPosition(Vec3 pos) { this->pos = pos; rend = 1; updateMatrix(); } // Zooms in by moving the camera closer to the view target // val: The length of the distance the camera should move 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(); } // Zooms out by moving the camera away from the view target // val: The length of the distance the camera should move 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(); } // Aligns the camera so that it points exactly at a specific point // ziel: The point the camera should point at 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(); } //! Sets the rotation of the camera around each axis //! \param rotation The rotation around each axis void Kam3D::setRotation(Vec3 rotation) { rotX = rotation.x; rotY = rotation.y; rotZ = rotation.z; rend = 1; updateMatrix(); } // Sets the position of the image on the screen // p: A point with x and y coordinates in pixels void Kam3D::setBildschirmPosition(Punkt p) { viewport.x = (float)p.x; viewport.y = (float)p.y; } // Sets the position of the image on the screen // x: The x coordinate in pixels // y: The y coordinate in pixels void Kam3D::setBildschirmPosition(int x, int y) { viewport.x = (float)x; viewport.y = (float)y; } // Sets the size of the image on the screen // p: A point, with x as width and y as height in pixels void Kam3D::setBildschirmSize(Punkt p) { viewport.width = (float)p.x; viewport.height = (float)p.y; updateMatrix(); } // Sets the size of the image on the screen // br: The width in pixels // hoe: The height in pixels void Kam3D::setBildschirmSize(int br, int hoe) { viewport.width = (float)br; viewport.height = (float)hoe; updateMatrix(); } // Sets the world to be drawn // w: The world void Kam3D::setWelt(Welt3D* w) { if (welt) welt->release(); welt = w; } // Sets the style of the camera // style: The new style consisting of the flags from the associated Style // class void Kam3D::setStyle(__int64 style) { this->style = style; } // Sets the style of the camera // style: All Style Flags to be changed // add_remove: 1 if the style should be added. 0 if the style // should be removed void Kam3D::setStyle(__int64 style, bool add_remove) { if (add_remove) this->style |= style; else if (!add_remove) this->style &= ~style; } // Adds style flags // style: The style to be added void Kam3D::addStyle(__int64 style) { this->style |= style; } // Removes style flags // style: The style to be removed 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; } // Processes the elapsed time // tickval: The time in seconds since the last call of the function // has passed return: true, if the image needs to be redrawn, // false otherwise. 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; } // Processes a mouse event // me: The mouse event to be processed 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; } } // Processes a keyboard event // te: The keyboard event to be processed void Kam3D::doTastaturEreignis(TastaturEreignis& te) {} // Returns whether certain styles are set // style: The styles to be checked // return: 1, if all styles in style are set bool Kam3D::hatStyle(__int64 style) const { return (this->style | style) == this->style; } // Returns whether certain styles are not set // style: The styles to be checked // return: 1, if all styles in style are not set bool Kam3D::hatStyleNicht(__int64 style) const { return (this->style | style) != this->style; } // Returns a pointer to the viewport const ViewPort* Kam3D::zViewPort() const { return &viewport; } // Returns the position of the camera in the world const Vec3& Kam3D::getWorldPosition() const { return pos; } // Returns the position in the world // screen: the screen position to be translated 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; } // Returns the direction of the camera in the world // screen: the screen position to be translated 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; } // Returns the projection matrix of the camera const Mat4& Kam3D::getProjectionMatrix() const { return proj; } // Returns the view matrix of the camera const Mat4& Kam3D::getViewMatrix() const { return view; } //! Returns the rotation around each axis const Vec3 Kam3D::getRotation() const { return {rotX, rotY, rotZ}; } //! Returns the position of the camera on the screen const Punkt Kam3D::getScreenPos() const { return Punkt((int)viewport.x, (int)viewport.y); } //! Returns the size of the camera on the screen const Punkt Kam3D::getScreenSize() const { return Punkt((int)viewport.width, (int)viewport.height); } // Returns the world Welt3D* Kam3D::getWelt() const { return welt ? dynamic_cast(welt->getThis()) : 0; } // Returns the world Welt3D* Kam3D::zWelt() const { return welt; }