This is old C++ code originally intended to be a playground for 3D math.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

358 lines
11 KiB

/**
* \file movable.h
*
* \brief Definition eines Templates für bewegte Objekte
*
* Organisiert, verwaltet und steuert die Bewegung bewegter Objekte.
*
* \author Georg Steffers <georg@steffers.org> [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&uuml;r bewegte Objekte
*
* alle Objektklassen, die auch Kind dieses komplett &ouml;ffentlichen
* Interfaces sind lassen sich dadurch rotieren und bewegen, das man die
* Rotations- und Bewegungsgeschwindigkeit bez&uuml;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 \<Punkt\> (view reference point)
//! das Zentrum des Objekts
vertex vfw_t; //!< \<Punkt\> Spitze von \ref vfw
vertex vup_t; //!< \<Punkt\> Spitze von \ref vup
vertex vri_t; //!< \<Punkt\> Spitze von \ref vri
vertex vfw; //!< \brief \<Vektor\> (vektor forward)
//! Objektkoordinatensystem z
vertex vup; //!< \brief \<Vektor\> (vektor up)
//! Objektkoordinatensystem y
vertex vri; //!< \brief \<Vektor\> (vektor right)
//! Objektkoordinatensystem x
Mmn<double> 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&auml;&szlig;t sich der genaue
//! Zeitraum seit der letzten Transformation
//! berechnen und in alle Transformations
//! Berechnungen mit einf&uuml;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&ouml;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<double>(4);
}
public:
virtual const Mmn<double>& 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<double>(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&auml;nderung der Position &uuml;ber eine
* vorberechnete Matrize.
* \param trans_mat Eine komplette vorberechnete Transformationsmatrix
*/
void move_im(const Mmn<double>& trans_mat) {
t_mat=trans_mat%t_mat;
}
/**
* \brief Verschiebung &uuml;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 &uuml;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 &uuml;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 &uuml;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 &uuml;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<double> mat_center(4);
Mmn<double> 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<double> mat_center(4);
Mmn<double> 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<double> mat_center(4);
Mmn<double> 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<double> mat_center(4);
Mmn<double> 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__