/** * \file movable.h * * \brief Definition eines Templates für bewegte Objekte * * Organisiert, verwaltet und steuert die Bewegung bewegter Objekte. * * \author Georg Steffers [gs] * * \date 19.12.2003 * * \version 19.12.2003 [gs]: erste Implementation aus gra_app gezogen. * \version 21.12.2003 [gs]: Bug in rotate_im_axis(double, vertex, vertex) * gefixt. Dort wurden immer die Objektkoordinaten * auf den Weltursprung verschoben und nicht die * Vektorbasis wie es eigentlich sein sollte. */ /* * Copyright (C)2003 Georg Steffers * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef __movable_h__ #define __movable_h__ #include "vertex.h" #include "../math/Mmn.h" /** * \brief Ein Interface für bewegte Objekte * * alle Objektklassen, die auch Kind dieses komplett öffentlichen * Interfaces sind lassen sich dadurch rotieren und bewegen, das man die * Rotations- und Bewegungsgeschwindigkeit bezüglich der lokalen, * bzw. der Weltkoordinaten angibt. * jeder Aufruf der Methode update aktualisiert dann die Positionen der * Vektoren dieses Objekts. */ class movable { protected: vertex vrp; //!< \brief \ (view reference point) //! das Zentrum des Objekts vertex vfw_t; //!< \ Spitze von \ref vfw vertex vup_t; //!< \ Spitze von \ref vup vertex vri_t; //!< \ Spitze von \ref vri vertex vfw; //!< \brief \ (vektor forward) //! Objektkoordinatensystem z vertex vup; //!< \brief \ (vektor up) //! Objektkoordinatensystem y vertex vri; //!< \brief \ (vektor right) //! Objektkoordinatensystem x Mmn t_mat; //!< Die aktuelle Transformationsmatrize //! \brief Geschwinidigkeiten //! relativ zu Weltkoordinaten double speed_x, speed_y, speed_z, rot_speed_x, rot_speed_y, rot_speed_z; //! \brief Geschwinidigkeiten //! relativ zu Objekt double speed_vfw, speed_vri, speed_vup, rot_speed_vfw, rot_speed_vri, rot_speed_vup; time_t last_transform; //!<\brief Zeitpunkt der letzten Transformation //! //! Damit läßt sich der genaue //! Zeitraum seit der letzten Transformation //! berechnen und in alle Transformations //! Berechnungen mit einfügen, so das //! wir wirkliche Echtzeit bekommen. //! Speed-Falloffs pro Sekunde double speed_x_falloff, speed_y_falloff, speed_z_falloff, rot_speed_x_falloff, rot_speed_y_falloff, rot_speed_z_falloff; double speed_vfw_falloff, speed_vri_falloff, speed_vup_falloff, rot_speed_vfw_falloff, rot_speed_vri_falloff, rot_speed_vup_falloff; //! \brief Konstruktor //! //! privater Kontruktor, da man von dem Interface //! keinen Eigenen Instanzen bilden können soll. movable() { vrp=vertex(0,0,0,1); vfw_t=vertex(0,0,1,1); vup_t=vertex(0,1,0,1); vri_t=vertex(1,0,0,1); vfw=vfw_t-vrp; vup=vup_t-vrp; vri=vri_t-vrp; t_mat=Mmn(4); } public: virtual const Mmn& get_t_mat(void) { return t_mat; } virtual void reset(void) { vrp.reset(); vfw_t.reset(); vup_t.reset(); vri_t.reset(); vfw=vfw_t-vrp; vup=vup_t-vrp; vri=vri_t-vrp; t_mat=Mmn(4); } /** * \param t_st Transformationsstufe */ virtual void transform(unsigned t_st) { vrp.transform(t_mat, t_st); vfw_t.transform(t_mat, t_st); vup_t.transform(t_mat, t_st); vri_t.transform(t_mat, t_st); vfw=vfw_t-vrp; vup=vup_t-vrp; vri=vri_t-vrp; } void print(void) { t_mat.print(); } const vertex& get_vrp(void) { return vrp; } const vertex& get_vfw_t(void) { return vfw_t; } const vertex& get_vup_t(void) { return vup_t; } const vertex& get_vri_t(void) { return vri_t; } const vertex& get_vfw(void) { return vfw; } const vertex& get_vup(void) { return vup; } const vertex& get_vri(void) { return vri; } /** * \brief direkte Veränderung der Position über eine * vorberechnete Matrize. * \param trans_mat Eine komplette vorberechnete Transformationsmatrix */ void move_im(const Mmn& trans_mat) { t_mat=trans_mat%t_mat; } /** * \brief Verschiebung über (lokale) Objekkoordinaten * \param axe Achse entlang der verschoben wird * \param step wie weit verschoben wird */ void translate_im_axe(vertex axe, double step) { axe=axe.norm()*step; t_mat=mat_translate(axe[X], axe[Y], axe[Z])%t_mat; } /** * \brief Verschiebung über (globale) Weltkoordinaten * \param x Verschiebung in VRI * \param y Verschiebung in VUP * \param z Verschiebung in VFW */ void translate_im_global(double x, double y, double z) { t_mat=mat_translate(x, y, z)%t_mat; } /** * \brief Drehung über (lokale) Objekkoordinaten vfw * \param angle Wieviel Grad soll gedreht werden */ void rotate_im_vfw(double angle) { vfw_t.transform(t_mat, 1); vrp.transform(t_mat, 1); rotate_im_axis(angle, vfw_t, vrp); vfw_t.reset(); vrp.reset(); } /** * \brief Drehung über (lokale) Objekkoordinaten vup * \param angle Wieviel Grad soll gedreht werden */ void rotate_im_vup(double angle) { vup_t.transform(t_mat, 1); vrp.transform(t_mat, 1); rotate_im_axis(angle, vup_t, vrp); vup_t.reset(); vrp.reset(); } /** * \brief Drehung über (lokale) Objekkoordinaten vri * \param angle Wieviel Grad soll gedreht werden */ void rotate_im_vri(double angle) { vri_t.transform(t_mat, 1); vrp.transform(t_mat, 1); rotate_im_axis(angle, vri_t, vrp); vri_t.reset(); vrp.reset(); } /** * \brief Drehung um X-Achse im Weltkoordinaten-Zentrum * \param angle Wieviel Grad soll gedreht werden */ void rotate_im_g_x(double angle) { t_mat=mat_rot_x(angle)%t_mat; } /** * \brief Drehung um Y-Achse im Weltkoordinaten-Zentrum * \param angle Wieviel Grad soll gedreht werden */ void rotate_im_g_y(double angle) { t_mat=mat_rot_y(angle)%t_mat; } /** * \brief Drehung um Z-Achse im Weltkoordinaten-Zentrum * \param angle Wieviel Grad soll gedreht werden */ void rotate_im_g_z(double angle) { t_mat=mat_rot_z(angle)%t_mat; } /** * \brief Drehung um X-Achse im Objektkoordinaten-Zentrum * \param angle Wieviel Grad soll gedreht werden */ void rotate_im_l_x(double angle) { Mmn mat_center(4); Mmn mat_reset(4); mat_center.a(0,3)=-t_mat.a(0,3); mat_center.a(1,3)=-t_mat.a(1,3); mat_center.a(2,3)=-t_mat.a(2,3); mat_reset.a(0,3)=t_mat.a(0,3); mat_reset.a(1,3)=t_mat.a(1,3); mat_reset.a(2,3)=t_mat.a(2,3); t_mat=mat_reset%mat_rot_x(angle)%mat_center%t_mat; } /** * \brief Drehung um Y-Achse im Objektkoordinaten-Zentrum * \param angle Wieviel Grad soll gedreht werden */ void rotate_im_l_y(double angle) { Mmn mat_center(4); Mmn mat_reset(4); mat_center.a(0,3)=-t_mat.a(0,3); mat_center.a(1,3)=-t_mat.a(1,3); mat_center.a(2,3)=-t_mat.a(2,3); mat_reset.a(0,3)=t_mat.a(0,3); mat_reset.a(1,3)=t_mat.a(1,3); mat_reset.a(2,3)=t_mat.a(2,3); t_mat=mat_reset%mat_rot_y(angle)%mat_center%t_mat; } /** * \brief Drehung um Z-Achse im Objektkoordinaten-Zentrum * \param angle Wieviel Grad soll gedreht werden */ void rotate_im_l_z(double angle) { Mmn mat_center(4); Mmn mat_reset(4); mat_center.a(0,3)=-t_mat.a(0,3); mat_center.a(1,3)=-t_mat.a(1,3); mat_center.a(2,3)=-t_mat.a(2,3); mat_reset.a(0,3)=t_mat.a(0,3); mat_reset.a(1,3)=t_mat.a(1,3); mat_reset.a(2,3)=t_mat.a(2,3); t_mat=mat_reset%mat_rot_z(angle)%mat_center%t_mat; } /** * \brief Drehung um eine beliebige Achse * \param angle Wieviel Grad soll gedreht werden * \param axe Die Achse um die gedreht werden soll als * Ursprungsvektor (also einer der in WC(0,0,0) beginnt) */ void rotate_im_axis(double angle, const vertex& axe) { t_mat=mat_rot_axe(angle, axe.get_t())%t_mat; } /** * \brief Drehung um Z-Achse im Objektkoordinaten-Zentrum * \param angle Wieviel Grad soll gedreht werden * \param tip Vertexspitze der Rotationsachse * \param base Vertexbasis der Rotationsachse */ void rotate_im_axis(double angle, vertex tip, vertex base) { Mmn mat_center(4); Mmn mat_reset(4); mat_center.a(0,3)=-base[X]; mat_center.a(1,3)=-base[Y]; mat_center.a(2,3)=-base[Z]; mat_reset.a(0,3)=base[X]; mat_reset.a(1,3)=base[Y]; mat_reset.a(2,3)=base[Z]; // if(angle==0 || angle==180) { // cout << "------------------------------\n"; // cout << "Winkel: " << angle << "Grad\n"; // t_mat.print(); // } t_mat=mat_reset%mat_rot_axe(angle, (tip-base).get_t())%mat_center%t_mat; // if(angle==0 || angle==180) { // t_mat.print(); // cout << "------------------------------\n"; // } } // sowohl für translatio, als auch für Rotation sollte ich denke // ich eigene Methoden für jede Richtung schreiben.!!! }; #endif // __movable_h__