From ceaa3ac930e2a44dae2ffd696dc3b66815e6ec1e Mon Sep 17 00:00:00 2001 From: Matt Thompson Date: Wed, 4 Mar 2009 16:39:47 -0600 Subject: [PATCH] Fixed some transforms, move to 3d and quaternion math in progress... --- src/backend/shapes.c | 2 +- src/{ => base}/controller.cpp | 61 +++-- src/base/controller.h | 116 ++++++++ src/base/quat.h | 445 ++++++++++++++++++++----------- src/base/time.cpp | 37 +++ src/base/time.h | 18 ++ src/base/vec.cpp | 3 + src/base/vec.h | 163 ++++++++--- src/main.cpp | 2 +- src/mods/list.h | 6 +- src/mods/{space => sandbox}/planet.cpp | 57 ++-- src/mods/{space => sandbox}/planet.h | 12 +- src/mods/sandbox/run.cpp | 215 ++++++++++----- src/mods/space/planet.cpp | 28 +- src/mods/space/planet.h | 10 +- src/mods/space/run.cpp | 10 +- src/phys/camera.cpp | 189 +++++++------ src/phys/camera.h | 53 +++- src/{controller.h => phys/conversion.h} | 42 +-- src/phys/generic_objects.cpp | 18 +- src/phys/generic_objects.h | 10 +- src/phys/object.cpp | 34 ++- src/phys/object.h | 64 +++-- src/phys/player.cpp | 225 ++++++++++++++++ src/phys/{generic_objects.h => player.h} | 45 ++-- src/phys/world.cpp | 110 ++++++-- src/phys/world.h | 17 +- 27 files changed, 1459 insertions(+), 533 deletions(-) rename src/{ => base}/controller.cpp (76%) mode change 100644 => 100755 create mode 100755 src/base/controller.h rewrite src/base/quat.h (60%) create mode 100755 src/base/time.cpp create mode 100755 src/base/time.h copy src/mods/{space => sandbox}/planet.cpp (66%) copy src/mods/{space => sandbox}/planet.h (94%) rename src/{controller.h => phys/conversion.h} (68%) create mode 100644 src/phys/player.cpp copy src/phys/{generic_objects.h => player.h} (67%) diff --git a/src/backend/shapes.c b/src/backend/shapes.c index 5b0cb80..3ef12be 100644 --- a/src/backend/shapes.c +++ b/src/backend/shapes.c @@ -67,7 +67,7 @@ void shapes_init() glNormal3f(0.0f, 0.0f, 1.0f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-0.5f,-0.5f, 0.5f); glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.5f,-0.5f, 0.5f); - glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5f, 1.5f, 0.5f); + glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.5f, 0.5f, 0.5f); glTexCoord2f(0.0f, 1.0f); glVertex3f(-0.5f, 0.5f, 0.5f); // back glNormal3f(0.0f, 0.0f,-1.0f); diff --git a/src/controller.cpp b/src/base/controller.cpp old mode 100644 new mode 100755 similarity index 76% rename from src/controller.cpp rename to src/base/controller.cpp index d708702..405cd1a --- a/src/controller.cpp +++ b/src/base/controller.cpp @@ -1,26 +1,35 @@ -/************************************************************************ - This file is part of NE. - - NE 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 3 of the License, or - (at your option) any later version. - - NE 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 NE. If not, see . -************************************************************************/ - -#include "controller.h" - -Controller::Controller() -{ -} - -Controller::~Controller() -{ -} +/************************************************************************ + This file is part of NE. + + NE 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 3 of the License, or + (at your option) any later version. + + NE 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 NE. If not, see . +************************************************************************/ + +#include "controller.h" +#include + +#include "backend/input.h" + +//using namespace Base; + +Controller::Controller() +{ + memset(digital, 0, sizeof digital); + + memset(analog, 0, sizeof analog); + memset(analogMap, 0, sizeof analogMap); +} + +void Controller::update() +{ +} diff --git a/src/base/controller.h b/src/base/controller.h new file mode 100755 index 0000000..2a07f9f --- /dev/null +++ b/src/base/controller.h @@ -0,0 +1,116 @@ +/************************************************************************ + This file is part of NE. + + NE 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 3 of the License, or + (at your option) any later version. + + NE 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 NE. If not, see . +************************************************************************/ + +#ifndef CONTROLLER_H +#define CONTROLLER_H + +#include + +//namespace Base { + +class Controller +{ +public: + Controller(); + + enum ACTION + { + NOTHING, + + FORWARD, + BACKWARD, + LEFT, + RIGHT, + + LOOK, + LOOK_UP, + LOOK_DOWN, + + TURN, + TURN_LEFT, + TURN_RIGHT, + + JUMP, + SELECT, + CANCEL, + MENU, + + LAST_ACTION + }; + + enum DIGITAL_EVENT + { + KEYBOARD, + MOUSE, + LAST_DIGITAL + }; + + enum ANALOG_EVENT + { + MOUSE_X, + MOUSE_Y, + LAST_ANALOG + }; + + void update(); + + inline void bindDigital(enum DIGITAL_EVENT event, + unsigned int id, enum ACTION action) + { + digitalMap[event][id] = action; + } + + inline void bindAnalog(enum ANALOG_EVENT event, + enum ACTION action) + { + analogMap[event] = action; + } + + inline void eventDigital(enum DIGITAL_EVENT event, + unsigned int id, bool value) + { + enum ACTION a = digitalMap[event][id]; + digital[a] = value; + } + + inline void eventAnalog(enum ANALOG_EVENT event, float value) + { + enum ACTION a = analogMap[event]; + analog[a] = value; + } + + inline bool getDigital(enum ACTION action) + { + return digital[action]; + } + + inline float getAnalog(enum ACTION action) + { + return analog[action]; + } + +private: + bool digital[LAST_ACTION]; + std::map digitalMap[LAST_DIGITAL]; + + float analog[LAST_ACTION]; + enum ACTION analogMap[LAST_ANALOG]; +}; + +//} + +#endif // CONTROLLER_H diff --git a/src/base/quat.h b/src/base/quat.h dissimilarity index 60% index 19d3c2b..198abc6 100644 --- a/src/base/quat.h +++ b/src/base/quat.h @@ -1,149 +1,296 @@ -/************************************************************************ - This file is part of NE. - - NE 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 3 of the License, or - (at your option) any later version. - - NE 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 NE. If not, see . -************************************************************************/ - -#ifndef QUAT_H_ -#define QUAT_H_ - -#include -#include "vec.h" - -template -class Quat -{ -public: - Quat(T x=0, T y=0, T z=0, T w=0) : m_x(x), m_y(y), m_z(z), m_w(w) {} - - inline const Quat set(T x, T y, T z, T w) - { - m_x = x; m_y = y; m_z = z; m_w = w; - return *this; - } - inline const T* get() - { - static T v[4]; - v[0] = m_x; - v[1] = m_y; - v[2] = m_z; - v[3] = m_w; - return &v; - } - - inline const Quat &setFromAxis(const Vec &v, T angle) - { - float a = sin(angle/2); - m_x = v.x()*a; - m_y = v.y()*a; - m_z = v.z()*a; - m_w = cos(angle/2); - return *this; - } - - inline T x() const {return m_x;} - inline T y() const {return m_y;} - inline T z() const {return m_z;} - inline T w() const {return m_w;} - - inline T len() const - { - return sqrt(m_w*m_w + m_x*m_x + m_y*m_y + m_z*m_z); - } - - inline const Quat &norm() const - { - static Quat q; - q = this; - float l = len(); - if (l != 0) - q /= len(); - return q; - } - - inline Quat &conj() const - { - static Quat q; - q = this; - q.m_x = -q.m_x; - q.m_y = -q.m_y; - q.m_z = -q.m_z; - return q; - } - - inline const Quat &operator * (const Quat &q) const - { - static Quat s; - s.m_x = m_w*q.m_x + m_x*q.m_w + m_y*q.m_z - m_z*q.m_y; - s.m_y = m_w*q.m_y - m_x*q.m_z + m_y*q.m_w + m_z*q.m_x; - s.m_z = m_w*q.m_z + m_x*q.m_y + m_y*q.m_x + m_z*q.m_w; - s.m_w = m_w*q.m_w - m_x*q.m_x - m_y*q.m_y - m_z*q.m_z; - return s; - } - - inline const Quat &operator = (const Quat &q) - { - set(q.x(),q.y(),q.z(),q.w()); - return *this; - } - inline bool operator == (const Quat &q) - { - return m_x==q.m_x && m_y==q.m_y && m_z==q.m_z && m_w==q.m_w; - } - - inline const Quat &operator + (T v) const - { - return Quat(m_x+v, m_y+v, m_z+v, m_w+v); - } - inline const Quat &operator += (T v) - { - return set(m_x+v, m_y+v, m_z+v, m_w+v); - } - - inline const Quat &operator - (T v) const - { - return Quat(m_x-v, m_y-v, m_z-v, m_w-v); - } - inline const Quat &operator -= (T v) - { - return set(m_x-v, m_y-v, m_z-v, m_w-v); - } - - inline const Quat &operator * (T v) const - { - return Quat(m_x*v, m_y*v, m_z*v, m_w*v); - } - inline const Quat &operator *= (T v) - { - return set(m_x*v, m_y*v, m_z*v, m_w*v); - } - - inline const Quat &operator / (T v) const - { - return Quat(m_x/v, m_y/v, m_z/v, m_w/v); - } - inline const Quat &operator /= (T v) - { - return set(m_x/v, m_y/v, m_z/v, m_w/v); - } - -protected: - T m_x, m_y, m_z, m_w; - -}; - -typedef Quat Quatf; -typedef Quat Quatd; - -#endif /*QUAT_H_*/ +/************************************************************************ + This file is part of NE. + + NE 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 3 of the License, or + (at your option) any later version. + + NE 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 NE. If not, see . +************************************************************************/ + +#ifndef QUAT_H_ +#define QUAT_H_ + +#include +#include +#include +#include "vec.h" + +//namespace Base { + +#define SLERP_DELTA 0.001 + +template +class Quat +{ +public: + Quat() : m_w(0.0) {} + Quat(T w, const Vec &v) : m_v(v), m_w(w) {} + Quat(T w, T x, T y, T z) : m_v(x, y, z), m_w(w) {} + + /////////////////////// + // Set/Get functions // + /////////////////////// + inline const Quat set(T w, const Vec &v) + { + m_v = v; + m_w = w; + return *this; + } + inline const Quat set(T x, T y, T z, T w) + { + m_v = Vec(x, y, z); + m_w = w; + return *this; + } + + inline void get(T v[4]) const + { + v[0] = x(); + v[1] = y(); + v[2] = z(); + v[3] = w(); + } + + inline const Vec v() const {return m_v;} + inline T x() const {return m_v.x();} + inline T y() const {return m_v.y();} + inline T z() const {return m_v.z();} + inline T w() const {return m_w;} + + //////////////// + // Conversion // + //////////////// + inline T angle() const + { + return acos(w())*2.0; + } + + inline static const Quat FromAxis(T angle, const Vec &v) + { + T a = angle * 0.5; + + return Quat(cos(a), v * sin(a)); + } + + inline static const Quat FromODE(const dReal *q) + { + return Quat(q[0], q[1], q[2], q[3]); + } + + inline const dReal *toODE() + { + static dReal q[4]; + q[0] = w(); + q[1] = x(); + q[2] = y(); + q[3] = z(); + return q; + } + + inline void toMatrixGL(T m[16]) + { + T x2 = x() + x(); + T y2 = y() + y(); + T z2 = z() + z(); + + T xx = x() * x2; + T xy = x() * y2; + T xz = x() * z2; + + T yy = y() * y2; + T yz = y() * z2; + + T zz = z() * z2; + + T wx = w() * x2; + T wy = w() * y2; + T wz = w() * z2; + + m[ 0] = 1.0 - (yy + zz); + m[ 1] = xy + wz; + m[ 2] = xz - wy; + m[ 3] = 0.0; + + m[ 4] = xy - wz; + m[ 5] = 1.0 - (xx + zz); + m[ 6] = yz + wx; + m[ 7] = 0.0; + + m[ 8] = xz + wy; + m[ 9] = yz - wx; + m[10] = 1.0 - (xx + yy); + m[11] = 0.0; + + m[12] = 0.0; + m[13] = 0.0; + m[14] = 0.0; + m[15] = 1.0; + } + + inline const Vec toEuler() const + { + T nx, ny, nz; + double test = x() * y() + z() * w(); + + if (test > 0.5 - SLERP_DELTA) { + nx = 2.0 * atan2(x(), w()); + ny = M_PI * 0.5; + nz = 0.0; + } + else if (test < -0.5 + SLERP_DELTA) { + nx = -2.0 * atan2(x(), w()); + ny = -M_PI * 0.5; + nz = 0.0; + } + else { + T xx, yy, zz, x2, y2, z2, w2; + + x2 = x() * 2.0; + y2 = y() * 2.0; + z2 = z() * 2.0; + w2 = w() * 2.0; + + xx = x2 * x(); + yy = y2 * y(); + zz = z2 * z(); + + nx = atan2(y2 * w() - x2 * z(), 1.0 - yy - zz); + ny = asin(2.0 * test); + nz = atan2(x2 * w() - y2 * z(), 1.0 - xx - zz); + } + + return Vec(nx, ny, nz); + } + + ///////////// + // 3D Math // + ///////////// + + inline T norm() const + { + return w() * w() + v().dot(v()); + } + + inline const Quat unit() const + { + return Quat(*this / norm()); + } + + inline const Quat inverse() const + { + return conjugate() / norm(); + } + + inline const Quat conjugate() const + { + return Quat(w(), -v()); + } + + inline const Quat operator * (const Quat &q) const + { + //T w = m_w * q.m_w - m_v.dot(q.m_v); + //Vec v(m_v.cross(q.m_v) + m_w * q.m_v + q.m_w * m_v); + //return Quat(w, v); + + return Quat(*this) *= q; + } + + inline const Quat &operator *= (const Quat &q) + { + T a, b, c, d, e, f, g, h; + a = (w() + x()) * (q.w() + q.x()); + b = (z() - y()) * (q.y() - q.z()); + c = (w() - x()) * (q.y() + q.z()); + d = (y() + z()) * (q.w() - q.x()); + e = (x() + z()) * (q.x() + q.y()); + f = (x() - z()) * (q.x() - q.y()); + g = (w() + y()) * (q.w() - q.z()); + h = (w() - y()) * (q.w() + q.z()); + + T w = b + (-e - f + g + h) * 0.5; + T x = a - ( e + f + g + h) * 0.5; + T y = c + ( e - f + g - h) * 0.5; + T z = d + ( e - f - g + h) * 0.5; + + m_w = w; + m_v = Vec(x, y, z); + + return *this; + } + + inline const Quat slerp(const Quat &to, T t) + { + double om, cosom, sinom, s1, s2; + + Quat tmp(to); + + cosom = v().dot(to.v()) + w() * to.w(); + + if (cosom < 0.0) { + cosom = -cosom; + tmp.m_w = -tmp.m_w; + tmp.m_v = -tmp.m_v; + } + + if ((1.0 - cosom) > SLERP_DELTA) { + om = acos(cosom); + sinom = sin(om); + s1 = sin((1.0 - t) * om) / sinom; + s2 = sin(t * om) / sinom; + } + else { + // do linear because they are very close + s1 = 1.0 - t; + s2 = t; + } + + return Quat(s1 * x() + s2 * tmp.x(), + s1 * y() + s2 * tmp.y(), + s1 * z() + s2 * tmp.z(), + s1 * w() + s2 * tmp.w()); + } + + /////////////////////// + // Equality overload // + /////////////////////// + + inline const Quat &operator = (const Quat &q) + { + m_w = q.m_w; + m_v = q.m_v; + return *this; + } + inline bool operator == (const Quat &q) const + { + return m_w == q.m_w && m_v == q.m_v; + } + + ///////////////////// + // Scalar overload // + ///////////////////// + + inline const Quat operator / (T s) const + { + return Quat (m_w / s, m_v / s); + } + +protected: + Vec m_v; + T m_w; + +}; + +typedef Quat Quatf; +typedef Quat Quatd; + +//} + +#endif /*QUAT_H_*/ diff --git a/src/base/time.cpp b/src/base/time.cpp new file mode 100755 index 0000000..85fede7 --- /dev/null +++ b/src/base/time.cpp @@ -0,0 +1,37 @@ +#include "time.h" + +//using namespace Base; + +#ifdef WIN32 + #include +#else + #include + #include +#endif + +Time::Stamp Time::Now() +{ + long time; +#ifdef WIN32 + time = timeGetTime(); +#else + static timeval tp; + gettimeofday(&tp, 0); + time = tp.tv_sec * 1000 + tp.tv_usec * 0.001; +#endif + return time; +} + + +void Time::Sleep(unsigned int millisecs) +{ +#ifdef WIN32 + Sleep(millisecs); +#else + struct timespec req, rem; + req.tv_sec = 0; + req.tv_nsec = millisecs * 1000000; + if (nanosleep(&req, &rem) == -1) + nanosleep(&rem, 0); +#endif +} diff --git a/src/base/time.h b/src/base/time.h new file mode 100755 index 0000000..b3a948c --- /dev/null +++ b/src/base/time.h @@ -0,0 +1,18 @@ +#ifndef TIMEUTIL_H +#define TIMEUTIL_H + +//using namespace Base { + +class Time +{ +public: + typedef unsigned long Stamp; + + static Stamp Now(); + + static void Sleep(unsigned int millisecs); +}; + +//} + +#endif // TIMEUTIL_H diff --git a/src/base/vec.cpp b/src/base/vec.cpp index 6bdfabe..7085568 100644 --- a/src/base/vec.cpp +++ b/src/base/vec.cpp @@ -16,3 +16,6 @@ ************************************************************************/ #include "vec.h" + + + diff --git a/src/base/vec.h b/src/base/vec.h index 16aeada..0b94f7b 100644 --- a/src/base/vec.h +++ b/src/base/vec.h @@ -18,42 +18,62 @@ #ifndef VEC_H_ #define VEC_H_ -template +#include +#include + +//namespace Base { + +template class Vec { public: Vec(T v=0) : m_x(v), m_y(v), m_z(v) {} Vec(T x, T y, T z) : m_x(x), m_y(y), m_z(z) {} + //////////////// + // Conversion // + //////////////// + + inline static const Vec FromODE(const dReal *v) + { + return Vec(v[0], v[1], v[2]); + } + /////////////////////// // Set/Get functions // /////////////////////// + inline const Vec set(T v) { m_x = m_y = m_z = v; return *this; } - inline const Vec &set(T x, T y, T z) + inline const Vec set(T x, T y, T z) { m_x = x; m_y = y; m_z = z; return *this; } - inline const T* get() + inline void get(T v[3]) const { - static T v[3]; v[0] = m_x; v[1] = m_y; v[2] = m_z; - return &v; } - inline T x() { return m_x; } - inline T y() { return m_y; } - inline T z() { return m_z; } + + inline T x() const { return m_x; } + inline T y() const { return m_y; } + inline T z() const { return m_z; } + + inline const Vec operator - () const + { + return Vec(-m_x, -m_y, -m_z); + } /////////////////////// // Equality overload // /////////////////////// - inline const Vec &operator = (const Vec &q) + + inline const Vec operator = (const Vec &q) { return set(q.m_x,q.m_y,q.m_z); } @@ -65,55 +85,57 @@ public: ///////////////////// // Vector overload // ///////////////////// - inline const Vec &operator + (const Vec &v) const + + inline const Vec operator + (const Vec &v) const { return Vec(m_x+v.m_x, m_y+v.m_y, m_z+v.m_z); } - inline const Vec &operator += (const Vec &v) + inline const Vec operator += (const Vec &v) { - return set(m_x+v, m_y+v, m_z+v); + return set(m_x+v.m_x, m_y+v.m_y, m_z+v.m_z); } - inline const Vec &operator - (const Vec &v) const + inline const Vec operator - (const Vec &v) const { return Vec(m_x-v.m_x, m_y-v.m_y, m_z-v.m_z); } - inline const Vec &operator -= (const Vec &v) + inline const Vec operator -= (const Vec &v) { - return set(m_x-v, m_y-v, m_z-v); + return set(m_x-v.m_x, m_y-v.m_y, m_z-v.m_z); } - inline const Vec &operator * (const Vec &v) const + inline const Vec operator * (const Vec &v) const { return Vec(m_x*v.m_x, m_y*v.m_y, m_z*v.m_z); } - inline const Vec &operator *= (const Vec &v) + inline const Vec operator *= (const Vec &v) { - return set(m_x*v, m_y*v, m_z*v); + return set(m_x*v.m_x, m_y*v.m_y, m_z*v.m_z); } - inline const Vec &operator / (const Vec &v) const + inline const Vec operator / (const Vec &v) const { return Vec(m_x/v.m_x, m_y/v.m_y, m_z/v.m_z); } - inline const Vec &operator /= (const Vec &v) + inline const Vec operator /= (const Vec &v) { - return set(m_x/v, m_y/v, m_z/v); + return set(m_x/v.m_x, m_y/v.m_y, m_z/v.m_z); } ///////////////////// // Scalar overload // ///////////////////// - inline const Vec &operator + (T v) const + + inline const Vec operator + (T v) const { return *this + Vec(v); } - inline const Vec &operator += (T v) + inline const Vec operator += (T v) { return *this += Vec(v); } - inline const Vec &operator - (T v) const + inline const Vec operator - (T v) const { return *this - Vec(v); } @@ -122,20 +144,20 @@ public: return *this -= Vec(v); } - inline const Vec &operator * (T v) const + inline const Vec operator * (T v) const { return *this * Vec(v); } - inline const Vec &operator *= (T v) + inline const Vec operator *= (T v) { return *this *= Vec(v); } - inline const Vec &operator / (T v) const + inline const Vec operator / (T v) const { return *this / Vec(v); } - inline const Vec &operator /= (T v) + inline const Vec operator /= (T v) { return *this /= Vec(v); } @@ -146,12 +168,12 @@ public: inline T length() const { - return sqrt(dot(&this)); + return sqrt(dot(*this)); } - inline const Vec &normalize() const + inline const Vec unit() const { - return this / length(); + return *this / (T)length(); } inline T dot(const Vec &v) const @@ -159,6 +181,82 @@ public: return m_x*v.m_x + m_y*v.m_y + m_z*v.m_z; } + inline const Vec cross(const Vec &v) const + { + return Vec(m_y * v.m_z - m_z * v.m_y, + m_z * v.m_x - m_x * v.m_z, + m_x * v.m_y - m_y * v.m_x); + } + + // returns a rotation matrix (for OpenGL) that + // specifies a rotation of angle around vector v + inline static void RotateGL(T angle, const Vec &v, GLfloat *r) + { + GLfloat c = cos(angle); + GLfloat s = sin(angle); + GLfloat t = 1.0 - c; + + r[ 0] = t * v.x() * v.x() + c; + r[ 1] = t * v.x() * v.y() + s * v.z(); + r[ 2] = t * v.x() * v.z() + s * v.y(); + r[ 3] = 0.0; + + r[ 4] = t * v.x() * v.y() - s * v.z(); + r[ 5] = t * v.y() * v.y() + c; + r[ 6] = t * v.y() * v.z() + s * v.x(); + r[ 7] = 0.0; + + r[ 8] = t * v.x() * v.z() + s * v.y(); + r[ 9] = t * v.y() * v.z() + s * v.x(); + r[10] = t * v.z() * v.z() + c; + r[11] = 0.0; + + r[12] = 0.0; + r[13] = 0.0; + r[14] = 0.0; + r[15] = 1.0; + } + + inline const Vec rotate(T angle, const Vec &v) + { + GLfloat r[16]; + RotateGL(angle, v, r); + return rotate(r); + } + + // rotate via an OpenGL matrix + inline const Vec rotate(const T *r) + { + return Vec(m_x*r[0] + m_y*r[4] + m_z*r[8], + m_x*r[1] + m_y*r[5] + m_z*r[9], + m_x*r[2] + m_y*r[6] + m_z*r[10]); + } + + /////////////// + // Debugging // + /////////////// + + void draw(const Vec &pos, GLfloat scale = 1.0) const + { + glPushMatrix(); + glTranslatef(pos.x(), pos.y(), pos.z()); + glScalef(scale, scale, scale); + draw(); + glPopMatrix(); + } + + void draw() const + { + glPushAttrib(GL_ALL_ATTRIB_BITS); + //glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glBegin(GL_LINES); + glVertex3f(x(), y(), z()); + glVertex3f(0, 0, 0); + glEnd(); + glPopAttrib(); + } + protected: T m_x, m_y, m_z; }; @@ -166,4 +264,7 @@ protected: typedef Vec Vec3f; typedef Vec Vec3d; +//} + #endif /*VEC_H_*/ + diff --git a/src/main.cpp b/src/main.cpp index 55f19b7..e5d6b83 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -98,7 +98,7 @@ int main(int argc, char **argv) return 1; } } - } + } srand(time(0)); diff --git a/src/mods/list.h b/src/mods/list.h index cec1b38..aef5c2d 100644 --- a/src/mods/list.h +++ b/src/mods/list.h @@ -27,9 +27,9 @@ extern struct mod space_mod; struct mod mod_list[] = { - sandbox_mod, - space_mod, - { 0, 0, 0 } + sandbox_mod, + space_mod, + { 0, 0, 0 } }; #endif /*LIST_H_*/ diff --git a/src/mods/space/planet.cpp b/src/mods/sandbox/planet.cpp similarity index 66% copy from src/mods/space/planet.cpp copy to src/mods/sandbox/planet.cpp index 09beb2d..ef9ad56 100644 --- a/src/mods/space/planet.cpp +++ b/src/mods/sandbox/planet.cpp @@ -17,9 +17,11 @@ #include "planet.h" +using namespace SandBox; + Planet::Planet(Texture *texture, float radius, float density) : Sphere(radius,density), m_tex(texture) { - + } Planet::~Planet() @@ -29,41 +31,38 @@ Planet::~Planet() void Planet::draw() { m_tex->apply(); - Sphere::draw(); + Sphere::draw(); } -const float *Planet::getGravity(Object *target) +const Vec3f Planet::getGravity(Object *target) { static float v[4]; - - const dReal *c = getPosition(); - - const dReal *p = target->getPosition(); - - dVector3 d = {c[0]-p[0], c[1]-p[1], c[2]-p[2]}; - dReal r2 = d[0]*d[0]+d[1]*d[1]+d[2]*d[2]; - dReal n = 1/sqrt(r2); - - dVector3 dir = {d[0]*n,d[1]*n,d[2]*n}; - - dReal mp = getMass(); - dReal mo = target->getMass(); - - dReal g = mp*mo/r2; - - v[0] = g*dir[0]; - v[1] = g*dir[1]; - v[2] = g*dir[2]; - v[3] = g; - - return v; + + Vec3f pos1 = getPositionV(); + + Vec3f pos2 = Vec3f::FromODE(target->getPosition()); + + Vec3f del = pos1 - pos2; + + float r2 = del.dot(del); + + float n = 1.0 / sqrt(r2); + + Vec3f dir = del * n; + + dReal m1 = getMass(); + dReal m2 = target->getMass(); + + dReal g = m1 * m2 / r2; + + return Vec3f(dir * g); } void Planet::applyGravity(Object *target) { if (!target->getBody()->isEnabled()) return; - - const float *g = getGravity(target); - - target->getBody()->addForce(g[0],g[1],g[2]); + + Vec3f grav = getGravity(target); + + target->applyGravity(grav); } diff --git a/src/mods/space/planet.h b/src/mods/sandbox/planet.h similarity index 94% copy from src/mods/space/planet.h copy to src/mods/sandbox/planet.h index fe77e4c..32e83a1 100644 --- a/src/mods/space/planet.h +++ b/src/mods/sandbox/planet.h @@ -21,20 +21,24 @@ #include "phys/generic_objects.h" #include "backend/texture.h" +namespace SandBox { + class Planet : public Sphere { public: Planet(Texture *texture, float radius, float density=1); virtual ~Planet(); - + void draw(); - + // gets gravity as where g is magnitude - const float *getGravity(Object *target); + const Vec3f getGravity(Object *target); void applyGravity(Object *target); - + private: Texture *m_tex; }; +} + #endif /*PLANET_H_*/ diff --git a/src/mods/sandbox/run.cpp b/src/mods/sandbox/run.cpp index 151ecfd..c150f9b 100644 --- a/src/mods/sandbox/run.cpp +++ b/src/mods/sandbox/run.cpp @@ -18,116 +18,201 @@ #include "backend/video.h" #include "backend/input.h" #include "backend/texture.h" +#include "backend/shapes.h" #include "phys/camera.h" #include "phys/world.h" #include "phys/generic_objects.h" -#include "phys/flat.h" +#include "phys/player.h" +#include "phys/conversion.h" #include "mods/mod.h" +#include "base/time.h" + +#include "planet.h" + #include #include #include +using namespace SandBox; + int sandbox_run(void *); /* see mods/list.h for what this is for... */ struct mod sandbox_mod = { - sandbox_run, - "Sandbox Demo", - "A demo showing some features from the physics engine" + sandbox_run, + "Sandbox Demo", + "A demo for testing features" }; int gl_init(); int sandbox_run(void *) { - Camera cam; + Camera cam; - //int width = v_info()->width; - //int height = v_info()->height; + //int width = v_info()->width; + //int height = v_info()->height; - gl_init(); + gl_init(); - int *screen_pos; - double *gl_pos; + int *screen_pos; + double *gl_pos; - World *w = World::Instance(); + World *w = World::Instance(); - std::vector objects; + std::vector objects; - int done = 0; - while (!done) - { - w->step(); + Texture home_tex("data/material/moon.jpg"); - glClearColor(0,0,0,0); - glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + Planet home(&home_tex, 128, 0.02); + home.setStatic(true); - i_pump(); + Player player(5); + //Sphere player(5, 1); + float player_speed = 500; + player.setPosition(0.0, 128.0 + 8, 0.0); + objects.push_back(&player); - keysym_t *key = i_keystate(); + //cam.follow(&player); + cam.setOffset(Vec3f(0.0, 10.0, 10.0)); + cam.setSpeed(0.5); - if (key[K_ESCAPE]) - { - done = 1; - } + cam.setPosition(Vec3f(100.0, 0.0, 400.0)); + //cam.setPosition(Vec3f(0.0, 128.0, 100.0)); + //cam.lookAt(player.getPositionV()); - screen_pos = i_mpos(); - gl_pos = v_unproject(screen_pos[0],screen_pos[1],1); + Time::Stamp delta = 0; + Time::Stamp frame_time = Time::Now(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + int done = 0; + while (!done) + { + frame_time = Time::Now(); - glTranslatef(0, 0, -1000); + glClearColor(0,0,0,0); + glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + cam.apply(); + + { + Vec3f pos = player.getPositionV(); + glColor3f(1.0, 0.0, 0.0); + player.getUp().draw(pos, 10); + player.getForward().draw(pos, 10); + glColor3f(0.0, 1.0, 0.0); + pos.draw(pos, 30); + } + + for (size_t i=0; iclearGravity(); + home.applyGravity(objects[i]); + objects[i]->update(); + } + + cam.update(); + + i_pump(); + + keysym_t *key = i_keystate(); + + if (key[K_ESCAPE]) { + //done = 1; + exit(0); + } + + if (key[K_LEFT]) { + //player.getBody()->addRelForce(player_speed, 0.0, 0.0); + player.getBody()->addTorque(0.0, player_speed * 0.1, 0.0); + } + if (key[K_RIGHT]) { + //player.getBody()->addRelForce(-player_speed, 0.0, 0.0); + player.getBody()->addTorque(0.0, -player_speed * 0.1, 0.0); + } + if (key[K_UP]) { + player.getBody()->addRelForce(0.0, 0.0, player_speed); + } + if (key[K_DOWN]) { + player.getBody()->addRelForce(0.0, 0.0, -player_speed); + } - glDisable(GL_TEXTURE_2D); - glDisable(GL_DEPTH_TEST); - if (1) - { - glPushMatrix(); - glTranslatef(gl_pos[0],gl_pos[1],0); - glColor3f(1,0,0); - glBegin(GL_LINES); - glVertex2f(-10,-10); - glVertex2f(10,10); - glVertex2f(-10,10); - glVertex2f(10,-10); - glEnd(); - glPopMatrix(); - } - glEnable(GL_DEPTH_TEST); + w->step(); - v_flip(); - } + screen_pos = i_mpos(); + gl_pos = v_unproject(screen_pos[0],screen_pos[1],1); + + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + + glDisable(GL_LIGHTING); + + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + if (0) { + glPushMatrix(); + glTranslatef(gl_pos[0],gl_pos[1],0); + glColor3f(1,0,0); + glBegin(GL_LINES); + glVertex2f(-10,-10); + glVertex2f(10,10); + glVertex2f(-10,10); + glVertex2f(10,-10); + glEnd(); + glPopMatrix(); + } + glEnable(GL_DEPTH_TEST); + + glEnable(GL_TEXTURE_2D); + glColor3f(1.0, 1.0, 1.0); + home.draw(); + + glEnable(GL_LIGHTING); + glDisable(GL_TEXTURE_2D); + glColor3f(1.0, 0.0, 0.0); + player.draw(); + static float rot = 0; + rot += 0.1; + + v_flip(); + + delta = Time::Now() - frame_time; + if (20 > delta) { + Time::Sleep(20 - delta); + } + } return 0; -} + } -int gl_init() -{ - //glClearColor(0,0,0,0); + int gl_init() + { + //glClearColor(0,0,0,0); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); - double w = v_info()->width, h = v_info()->height; - double aspect = w/h; + double w = v_info()->width, h = v_info()->height; + double aspect = w/h; - gluPerspective(45,aspect,1,1001); + gluPerspective(45,aspect,1,3000); - glEnable(GL_DEPTH_TEST); - glClearDepth(1); + glEnable(GL_DEPTH_TEST); + glClearDepth(1); - glEnable(GL_CULL_FACE); - glFrontFace(GL_CCW); + glEnable(GL_CULL_FACE); + glFrontFace(GL_CCW); - glShadeModel(GL_SMOOTH); + glShadeModel(GL_SMOOTH); - //glEnable(GL_TEXTURE_2D); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + //glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); - return 0; + return 0; } diff --git a/src/mods/space/planet.cpp b/src/mods/space/planet.cpp index 09beb2d..93dcd03 100644 --- a/src/mods/space/planet.cpp +++ b/src/mods/space/planet.cpp @@ -17,9 +17,11 @@ #include "planet.h" +using namespace Space; + Planet::Planet(Texture *texture, float radius, float density) : Sphere(radius,density), m_tex(texture) { - + } Planet::~Planet() @@ -29,41 +31,41 @@ Planet::~Planet() void Planet::draw() { m_tex->apply(); - Sphere::draw(); + Sphere::draw(); } const float *Planet::getGravity(Object *target) { static float v[4]; - + const dReal *c = getPosition(); - + const dReal *p = target->getPosition(); - + dVector3 d = {c[0]-p[0], c[1]-p[1], c[2]-p[2]}; dReal r2 = d[0]*d[0]+d[1]*d[1]+d[2]*d[2]; dReal n = 1/sqrt(r2); - + dVector3 dir = {d[0]*n,d[1]*n,d[2]*n}; - + dReal mp = getMass(); dReal mo = target->getMass(); - + dReal g = mp*mo/r2; - + v[0] = g*dir[0]; v[1] = g*dir[1]; v[2] = g*dir[2]; v[3] = g; - + return v; } void Planet::applyGravity(Object *target) { if (!target->getBody()->isEnabled()) return; - + const float *g = getGravity(target); - - target->getBody()->addForce(g[0],g[1],g[2]); + + target->getBody()->addForce(g[0],g[1],g[2]); } diff --git a/src/mods/space/planet.h b/src/mods/space/planet.h index fe77e4c..8e79f23 100644 --- a/src/mods/space/planet.h +++ b/src/mods/space/planet.h @@ -21,20 +21,24 @@ #include "phys/generic_objects.h" #include "backend/texture.h" +namespace Space { + class Planet : public Sphere { public: Planet(Texture *texture, float radius, float density=1); virtual ~Planet(); - + void draw(); - + // gets gravity as where g is magnitude const float *getGravity(Object *target); void applyGravity(Object *target); - + private: Texture *m_tex; }; +} + #endif /*PLANET_H_*/ diff --git a/src/mods/space/run.cpp b/src/mods/space/run.cpp index 3fa0421..807e0fd 100644 --- a/src/mods/space/run.cpp +++ b/src/mods/space/run.cpp @@ -34,6 +34,8 @@ #include #include +using namespace Space; + int space_run(void *); /* see mods/list.h for what this is for... */ @@ -183,8 +185,8 @@ int space_run(void *) rpos[0] -= x; rpos[1] += y; - cam.setTarget(-x,y,-10); - cam.setPosition(-x,y,0); + cam.lookAt(Vec3f(-x,y,-10)); + cam.setPosition(Vec3f(-x,y,0)); cam.update(); cam.apply(); //glScalef(zoom,zoom,zoom); @@ -366,6 +368,10 @@ int space_run(void *) v_flip(); } + for (size_t i=0; i @@ -27,113 +28,131 @@ Camera::Camera() : m_object(0), m_speed(0.5) { - m_up[0] = 0; - m_up[1] = 1; - m_up[2] = 0; - - for (int i=0; i<3; i++) - { - m_pos[i] = m_cpos[i] = m_target[i] = m_ctarget[i] = 0; - } + setUp(Vec3f(0.0, 1.0, 0.0)); } Camera::~Camera() { } -void par(const char *s, const float *v) +void Camera::follow(Object *o) { - printf("%s: %f %f %f\n", s ,v[0], v[1], v[2]); -} + m_object = o; -void update_pass(float *cvec, const float *tvec, float speed) -{ - float x, y, z; - x = tvec[0] - cvec[0]; - y = tvec[1] - cvec[1]; - z = tvec[2] - cvec[2]; - float dist = x*x + y*y + z*z; - - if (dist != 0) - { - x /= dist; - y /= dist; - z /= dist; - dist *= speed; - - cvec[0] += dist * x; - cvec[1] += dist * y; - cvec[2] += dist * z; + if (m_object) { + const dReal *q = m_object->getRotation(); + m_cquat = Quatf(q[0], q[1], q[2], q[3]).inverse(); } -} +} void Camera::update() { - if (!m_object) - { - update_pass(m_cpos,m_pos,m_speed); - update_pass(m_ctarget,m_target,m_speed); + Vec3f delta; + float dist; + + if (m_object) { + const dReal *t = m_object->getPosition(); + + m_target = Vec3f(t[0], t[1], t[2]); + + //Vec3f v = m_target + m_offset - m_cpos; + //m_cpos += v * m_speed; + + m_cpos = m_target + m_object->getForward()*-10; + //+ m_offset; + + m_ctarget = m_target; + + m_up = m_object->getUp(); + } + else { + delta = m_pos - m_cpos; + dist = delta.dot(delta); + if (dist != 0) { + delta /= dist; + dist *= m_speed; + + m_cpos += delta * dist; + } + + delta = m_target - m_ctarget; + dist = delta.dot(delta); + if (dist != 0) { + delta /= dist; + dist *= m_speed; + + m_ctarget += delta * dist; + } } } void Camera::apply() -{ - if (m_object) - { - GLfloat m[16]; - const float *r = m_object->getRotation(); - const float *t = m_object->getPosition(); +{ + //GLfloat m[16]; + + //const dReal *r = m_object->getRotation(); + //const dReal *t = m_object->getPosition(); + // the ODE rotation matrix is already transposed from opengl's viewpoint + /* m[0] =r[0]; - m[1] =r[1]; - m[2] =r[2]; - m[3] =0; - - m[4] =r[4]; - m[5] =r[5]; - m[6] =r[6]; - m[7] =0; - - m[8] =r[8]; - m[9] =r[9]; - m[10]=r[10]; - m[11]=0; - - m[12]=0; - m[13]=0; - m[14]=0; - m[15]=1; - - glMultMatrixf (m); - glTranslatef(-t[0],-t[1],-t[2]); - + m[1] =r[1]; + m[2] =r[2]; + m[3] =0; + + m[4] =r[4]; + m[5] =r[5]; + m[6] =r[6]; + m[7] =0; + + m[8] =r[8]; + m[9] =r[9]; + m[10]=r[10]; + m[11]=0; + + m[12]=0; + m[13]=0; + m[14]=0; + m[15]=1; + */ + + //glMultMatrixf (m); + + if (m_object) { + const dReal *oq = m_object->getQuaternion(); + const dReal *op = m_object->getPosition(); + + Quatf q(oq[0], oq[1], oq[2], oq[3]); + q = q.conjugate(); + + //Quatf d = m_cquat.slerp(q, 0.1); + + m_cquat = q;//.conjugate(); + + GLfloat m[16]; + //m_cquat.toMatrixGL(m); + m_cquat.toMatrixGL(m); + + glMultMatrixf(m); + + glTranslatef(-op[0], + -op[1], + -op[2]); + + //gluLookAt() + + //Vec3f off = m_offset * 100; + //glTranslatef(-m_offset.x(), -m_offset.y(), -m_offset.z()); + //glTranslatef(-off.x(), -off.y(), -off.z()); } - else - { - gluLookAt(m_cpos[0], m_cpos[1], m_cpos[2], - m_ctarget[0], m_ctarget[1], m_ctarget[2], - m_up[0], m_up[1], m_up[2]); + else { + gluLookAt(m_cpos.x(), m_cpos.y(), m_cpos.z(), + m_ctarget.x(), m_ctarget.y(), m_ctarget.z(), + m_up.z(), m_up.y(), m_up.z()); } -} -void Camera::setUp(float x, float y, float z) -{ - m_up[0] = x; - m_up[1] = y; - m_up[2] = z; + //printf("%f.2 %f.2 %f.2\n", m_cpos.x(), m_cpos.y(), m_cpos.z()); } -void Camera::setPosition(float x, float y, float z) -{ - m_pos[0] = x; - m_pos[1] = y; - m_pos[2] = z; -} -void Camera::setTarget(float x, float y, float z) -{ - m_target[0] = x; - m_target[1] = y; - m_target[2] = z; -} diff --git a/src/phys/camera.h b/src/phys/camera.h index 46782d7..59d081b 100644 --- a/src/phys/camera.h +++ b/src/phys/camera.h @@ -18,6 +18,9 @@ #ifndef CAMERA_H_ #define CAMERA_H_ +#include "base/vec.h" +#include "base/quat.h" + class Object; class Camera @@ -26,25 +29,47 @@ public: Camera(); virtual ~Camera(); - + void update(); void apply(); - - void follow(Object *o, float dist=0) { m_object = o; m_dist = dist; } - void setFollowDistance(float dist) { m_dist = dist; } - - void setUp(float x, float y, float z); - void setSpeed(float speed) { m_speed = speed; } - void setPosition(float x, float y, float z); - void setTarget(float x, float y, float z); - + + void follow(Object *o); + + inline void setOffset(const Vec3f &offset) + { + m_offset = offset; + } + + inline void setUp(const Vec3f &up) + { + m_up = up; + } + + inline void setSpeed(float speed) + { + m_speed = speed; + } + + inline void setPosition(const Vec3f &pos) + { + m_pos = pos; + } + + inline void lookAt(const Vec3f &target) + { + m_target = target; + } + private: + const Vec3f getUp(); + Object *m_object; - float m_dist; + float m_speed; - float m_up[3]; - float m_pos[3], m_cpos[3]; - float m_target[3], m_ctarget[3]; + Vec3f m_up, m_pos, m_offset, m_target; + Vec3f m_cpos, m_ctarget; + + Quatf m_cquat; }; #endif /*CAMERA_H_*/ diff --git a/src/controller.h b/src/phys/conversion.h similarity index 68% rename from src/controller.h rename to src/phys/conversion.h index 4340170..36c077f 100644 --- a/src/controller.h +++ b/src/phys/conversion.h @@ -15,24 +15,32 @@ along with NE. If not, see . ************************************************************************/ -#ifndef CONTROLLER_H_ -#define CONTROLLER_H_ +#ifndef CONVERSION_H_ +#define CONVERSION_H_ -class Action +#include +#include + +inline const dReal *Matrix_GL_to_ODE(const GLfloat *m) { -public: - Action(); -}; + static dReal r[12]; + r[0] = m[0]; + r[4] = m[1]; + r[8] = m[2]; -typedef unsigned int ActionID; + r[1] = m[4]; + r[5] = m[5]; + r[9] = m[6]; -class Controller -{ -public: - Controller(); - virtual ~Controller(); - - void addAction(unsigned int , Action a); -}; - -#endif /*CONTROLLER_H_*/ + r[2] = m[8]; + r[6] = m[9]; + r[10]= m[10]; + + r[3] = 0.0; + r[7] = 0.0; + r[11]= 0.0; + + return r; +} + +#endif /* CONVERSION_H_ */ diff --git a/src/phys/generic_objects.cpp b/src/phys/generic_objects.cpp index 01db790..8cd8cfd 100644 --- a/src/phys/generic_objects.cpp +++ b/src/phys/generic_objects.cpp @@ -31,10 +31,12 @@ Box::Box(float x, float y, float z, float density) { m_box = new dBox(World::Instance()->getSpace()->id(),x,y,z); m_geom = m_box; - dMassSetBox(&m_mass, density, x,y,z); - m_body->setMass(&m_mass); - init_geom(); - shapes_init(); + + m_mass.setBox(density, x, y, z); + m_body->setMass(&m_mass); + + shapes_init(); + init_geom(); } Box::~Box() @@ -64,9 +66,11 @@ Sphere::Sphere(float r, float density) { m_sphere = new dSphere(World::Instance()->getSpace()->id(),r); m_geom = m_sphere; - dMassSetSphere(&m_mass, density, r); - m_body->setMass(&m_mass); - init_geom(); + + m_mass.setSphere(density, r); + m_body->setMass(&m_mass); + + init_geom(); } Sphere::~Sphere() diff --git a/src/phys/generic_objects.h b/src/phys/generic_objects.h index 391b620..268a0e1 100644 --- a/src/phys/generic_objects.h +++ b/src/phys/generic_objects.h @@ -25,9 +25,9 @@ class Box : public Object public: Box(float x, float y, float z, float density); virtual ~Box(); - + virtual void draw(); - + private: dBox *m_box; }; @@ -37,11 +37,11 @@ class Sphere : public Object public: Sphere(float r, float density); virtual ~Sphere(); - + void draw(); - + private: dSphere *m_sphere; }; -#endif +#endif diff --git a/src/phys/object.cpp b/src/phys/object.cpp index 5ef9baf..db17cb8 100644 --- a/src/phys/object.cpp +++ b/src/phys/object.cpp @@ -26,7 +26,8 @@ #include #include -Object::Object() : m_geom(0), m_static(false), m_colfunc(0) +Object::Object() + : m_gravity_mag(0), m_geom(0), m_static(false), m_colfunc(0) { m_body = new dBody(World::Instance()->getWorld()->id()); } @@ -70,7 +71,7 @@ void Object::apply_matrix() matrix[13]=pos[1]; matrix[14]=pos[2]; matrix[15]=1; - + glMultMatrixf (matrix); } @@ -83,7 +84,7 @@ void Object::init_geom() } } -void Object::setStatic(bool is_static) +void Object::setStatic(bool is_static) { m_static = is_static; if (m_geom) @@ -95,20 +96,37 @@ void Object::setStatic(bool is_static) } } +bool Object::applyGravity(const Vec3f &grav) +{ + m_body->addForce(grav.x(), grav.y(), grav.z()); + + float mag = grav.length(); + + if (m_gravity_mag < mag) + { + m_gravity_mag = mag; + m_gravity = grav; + + return true; + } + + return false; +} + std::string &Object::serialize() { std::stringstream stream; - + const dReal *p = getPosition(); - + stream << "pos: "; stream << p[0] << ' ' << p[1] << ' ' << p[2] << ' '; - + p = getQuaternion(); - + stream << "quat: "; stream << p[0] << ' ' << p[1] << ' ' << p[2] << ' ' << p[3] << ' '; - + static std::string out = stream.str(); return out; } diff --git a/src/phys/object.h b/src/phys/object.h index 23fcc05..e12c065 100644 --- a/src/phys/object.h +++ b/src/phys/object.h @@ -22,50 +22,84 @@ #include #include #include +#include "base/vec.h" class Object { - public: +public: Object(); virtual ~Object(); - + void setCollide(int (*func)(Object*,Object*)) { m_colfunc = func; } - int collide(Object* o); - + virtual int collide(Object* o); + virtual void update() {} - + virtual void draw() = 0; - + dBody *getBody() { return m_body; } dGeom *getGeom() { return m_geom; } float getMass() { return m_mass.mass; } - + + inline const Vec3f getUp() + { + const dReal *r = getRotation(); + + return Vec3f(r[1], r[5], r[9]); + } + + inline const Vec3f getForward() + { + const dReal *r = getRotation(); + + return Vec3f(r[2], r[6], r[10]); + } + void setPosition(dReal x, dReal y, dReal z); const dReal *getPosition(); - + inline const Vec3f getPositionV() + { + const dReal *v = getPosition(); + return Vec3f(v[0], v[1], v[2]); + } + void setRotation(const dMatrix3 r); const dReal *getRotation(); void setQuaternion(const dQuaternion q); const dReal *getQuaternion(); - + bool isStatic() { return m_static; } void setStatic(bool is_static); - + virtual std::string &serialize(); virtual void unserialize(std::string &s); - - protected: + + // returns true when the gravity applied is the strongest + virtual bool applyGravity(const Vec3f &force); + + inline void clearGravity() + { + m_gravity_mag = 0; + } + +protected: void apply_matrix(); void init_geom(); - + + long int m_framestamp; + Vec3f m_gravity; + float m_gravity_mag; + dMass m_mass; dBody *m_body; dGeom *m_geom; - - private: + +private: bool m_static; int (*m_colfunc)(Object*,Object*); + + float m_spring, m_damp; }; #endif diff --git a/src/phys/player.cpp b/src/phys/player.cpp new file mode 100644 index 0000000..eaeaf1e --- /dev/null +++ b/src/phys/player.cpp @@ -0,0 +1,225 @@ +/************************************************************************ + This file is part of NE. + + NE 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 3 of the License, or + (at your option) any later version. + + NE 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 NE. If not, see . +************************************************************************/ + +#include "player.h" + +#include "world.h" +#include "backend/shapes.h" +#include "base/quat.h" + +#include +#include +#include + +Player::Player(float height, float density) : m_standing(false) +{ + float radius, length; + radius = height * 0.618; + length = height * 0.85; + + World *w = World::Instance(); + m_capsule = new dCapsule(w->getSpace()->id(), radius, length); + m_geom = m_capsule; + + m_ray = new dRay(0, getBodyHeight() - length); + m_ray->setParams(0, 1); + m_ray->setClosestHit(1); + + m_mass.setCapsule(density, 2, radius, length); + m_body->setMass(&m_mass); + + init_geom(); + shapes_init(); +} + +Player::~Player() +{ + delete m_capsule; + delete m_ray; +} + +void Player::draw() +{ + glPushMatrix(); + apply_matrix(); + + dReal radius, length; + m_capsule->getParams(&radius, &length); + + if (m_standing) + glColor3f(0,0,1); + else + glColor3f(1,1,1); + + glScalef(radius, length, radius); + draw_cube(); + glPopMatrix(); + + static GLUquadricObj *q = 0; + if (q == 0) + { + q = gluNewQuadric(); + gluQuadricNormals(q, GL_SMOOTH); + gluQuadricTexture(q, GL_TRUE); + glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + } + + float hr = radius * 0.5; + + glPushMatrix(); + apply_matrix(); + glTranslatef(0.0, length*0.5, 0.0); + glScalef(hr, hr, hr); + gluSphere(q,1,16,16); + glPopMatrix(); + + glPushMatrix(); + apply_matrix(); + glTranslatef(0.0, -length*0.5, 0.0); + glScalef(hr, hr, hr); + gluSphere(q,1,16,16); + glPopMatrix(); + + if (m_standing) + glColor3f(0,1,0); + else + glColor3f(1,1,0); + + Vec3f a = getBottom(); + Vec3f b = getFeet(); + + glDisable(GL_LIGHTING); + glBegin(GL_LINES); + glVertex3f(a.x(), a.y(), a.z()); + glVertex3f(b.x(), b.y(), b.z()); + glEnd(); + glEnable(GL_LIGHTING); +} + +void Player::update() +{ + update_ray(); + + World *w = World::Instance(); + + dReal depth = w->trace(m_ray); + + if (depth != dInfinity) { + m_standing = true; + m_depth = depth; + + Vec3f g = -m_gravity; + + printf("%.2f, %.2f, %.2f\n", g.x(), g.y(), g.z()); + + Quatf to = Quatf(m_body->getQuaternion()[0], -m_gravity.unit()); + printf("%.2f, %.2f, %.2f, %.2f\n", to.w(), to.x(), to.y(), to.z()); + to = to.unit(); + printf("%.2f, %.2f, %.2f, %.2f\n", to.w(), to.x(), to.y(), to.z()); + + to.v().draw(getPositionV(), 100); + + m_body->setQuaternion(to.toODE()); + m_body->setAngularVel(0.0, 0.0, 0.0); + m_body->setTorque(0.0, 0.0, 0.0); + + dReal x = m_ray->getLength() - m_depth; + + dReal k = m_mass.mass * 2; + + Vec3f vel = Vec3f::FromODE(m_body->getLinearVel()); + vel *= w->getStepSize() * w->getStepCount(); + + dReal vdamp = vel.dot(-getUp()); + + dReal force = k * x + k * vdamp; + + printf("------------------\n"); + printf("x = %.2f k = %.2f\n", x, k); + printf("applying %.2f force\n", force); + + m_body->addRelForce(0.0, force, 0.0); + + //m_body->addTorque(ang_damp.x(), ang_damp.y(), ang_damp.z()); + + // do damping + dReal damp = -0.25; + + vel *= damp; + //m_body->addForce(vel.x(), vel.y(), vel.z()); + + //Vec3f tor = Vec3f::FromODE(m_body->getTorque()) * damp; + + //m_body->addTorque(tor.x(), tor.y(), tor.z()); + } + else { + Vec3f norm = getUp().unit(); + Vec3f grav = m_gravity.unit(); + + float tip = 1.0 - norm.dot(grav); + + Quatf from = Quatf::FromODE(getQuaternion()); + + Quatf to = Quatf::FromAxis(from.angle(), grav); + Quatf q = from.slerp(to, 0.5); + + Vec3f eu = q.toEuler() * tip; + getBody()->addTorque(eu.x(), eu.y(), eu.z()); + } +} + +float Player::getBodyHeight() +{ + dReal length, radius; + m_capsule->getParams(&radius, &length); + + return length + 2 * radius; +} + +const Vec3f Player::getFeet() +{ + dReal dist = m_ray->getLength(); + Quatf quat = Quatf::FromODE(getQuaternion()); + + return getBottom() + getUp() * -dist; +} + +const Vec3f Player::getBottom() +{ + Vec3f pos = getPositionV(); + Quatf quat = Quatf::FromODE(getQuaternion()); + + dReal radius, length; + m_capsule->getParams(&radius, &length); + + length *= 0.5; + + Vec3f offset = getUp() * -length; + + return pos + offset; +} + +void Player::update_ray() +{ + Vec3f bottom = getBottom(); + Vec3f down = -getUp(); + + m_ray->set(bottom.x(), bottom.y(), bottom.z(), + down.x(), down.y(), down.z()); +} + diff --git a/src/phys/generic_objects.h b/src/phys/player.h similarity index 67% copy from src/phys/generic_objects.h copy to src/phys/player.h index 391b620..7b730df 100644 --- a/src/phys/generic_objects.h +++ b/src/phys/player.h @@ -15,33 +15,36 @@ along with NE. If not, see . ************************************************************************/ -#ifndef GENERIC_OBJECTS_H_ -#define GENERIC_OBJECTS_H_ +#ifndef PLAYER_H_ +#define PLAYER_H_ #include "object.h" +#include "base/vec.h" -class Box : public Object -{ +class Player: public Object { public: - Box(float x, float y, float z, float density); - virtual ~Box(); - + Player(float height, float density=1); + virtual ~Player(); + virtual void draw(); - -private: - dBox *m_box; -}; + virtual void update(); + + const Vec3f getFeet(); + const Vec3f getBottom(); + + float getBodyHeight(); + + inline bool isStanding() {return m_standing;} + +protected: + void update_ray(); + + dCapsule *m_capsule; + dRay *m_ray; -class Sphere : public Object -{ -public: - Sphere(float r, float density); - virtual ~Sphere(); - - void draw(); - private: - dSphere *m_sphere; + bool m_standing; + dReal m_depth; }; -#endif +#endif /* PLAYER_H_ */ diff --git a/src/phys/world.cpp b/src/phys/world.cpp index 1b71976..50893da 100644 --- a/src/phys/world.cpp +++ b/src/phys/world.cpp @@ -17,6 +17,7 @@ #include "world.h" +#include "base/vec.h" #include "object.h" #include @@ -27,18 +28,32 @@ #define MAX_CONTACTS 3 void collision_callback(void *data, dGeomID g1, dGeomID g2) { + if (dGeomIsSpace (g1) || dGeomIsSpace (g2)) { + + // colliding a space with something : + dSpaceCollide2 (g1, g2, data,&collision_callback); + + // collide all geoms internal to the space(s) + if (dGeomIsSpace (g1)) + dSpaceCollide ((dSpaceID)g1, data, &collision_callback); + if (dGeomIsSpace (g2)) + dSpaceCollide ((dSpaceID)g2, data, &collision_callback); + + return; + } + dWorld *world = World::Instance()->getWorld(); dJointGroup *jgroup = World::Instance()->getJointGroup(); - - dContact contacts[MAX_CONTACTS]; - - Object *o1 = (Object*)dGeomGetData(g1); - Object *o2 = (Object*)dGeomGetData(g2); - - int num = dCollide(g1,g2,MAX_CONTACTS,&contacts[0].geom,sizeof(dContact)); - - if (num && o1 && o2) - { + + dContact contacts[MAX_CONTACTS]; + + Object *o1 = (Object*)dGeomGetData(g1); + Object *o2 = (Object*)dGeomGetData(g2); + + int num = dCollide(g1,g2,MAX_CONTACTS,&contacts[0].geom,sizeof(dContact)); + + if (num && o1 && o2) + { if ( o1->collide(o2) && o2->collide(o1) ) { // they collide @@ -48,21 +63,25 @@ void collision_callback(void *data, dGeomID g1, dGeomID g2) // they don't return; } - } - - dWorldID world_id = world->id(); - dJointGroupID jgroup_id = jgroup->id(); - - for (int i=0; iid(); + dJointGroupID jgroup_id = jgroup->id(); + + for (int i=0; icollide(0,collision_callback); - + for (int i=0; iempty(); } + +void ray_callback(void *data, dGeomID g1, dGeomID g2) +{ + dContactGeom *res = (dContactGeom*)data; + + //Object *o1 = (Object*)dGeomGetData(g1); + //Object *o2 = (Object*)dGeomGetData(g2); + + if (dGeomGetClass(g1) != dRayClass && + dGeomGetClass(g2) != dRayClass) { + return; + } + + dCollide(g1, g2, 1, res, sizeof(dContactGeom)); + + /* + printf("Got %d contacts\n", num); + + if (num) { + printf("Found one\n"); + if (geom.depth <= res->depth) { + *res = geom; + printf("HIT\n"); + } + } + */ +} + +dReal World::trace(dRay *ray) +{ + dContactGeom geom; + geom.depth = dInfinity; + ray->collide2((dGeomID)m_space->id(), &geom, ray_callback); + return geom.depth; +} diff --git a/src/phys/world.h b/src/phys/world.h index c46a1fe..5954e3f 100644 --- a/src/phys/world.h +++ b/src/phys/world.h @@ -26,26 +26,31 @@ class World { World(); ~World(); - + public: static World* Instance(); - + void setStepCount(int count) { m_stepcount = count; } + inline int getStepCount() { return m_stepcount; } + void setStepSize(float size) { m_stepsize = size; } + inline float getStepSize() { return m_stepsize; } + void step(); - + dReal trace(dRay *ray); + dWorld *getWorld() { return &m_world; } dSpace *getSpace() { return m_space; } dJointGroup *getJointGroup() { return m_jointgroup; } - + private: int m_maxcontacts; int m_stepcount; float m_stepsize; - + dJointGroup *m_jointgroup; dSpace *m_space; dWorld m_world; }; -#endif +#endif -- 2.11.4.GIT