Browse Source

math: move the matrix-to-quaternion code to a global header.

This lets us use the code for non-float variable types. I also got
rid of the mat4-to-quat code so that users are forced to use the
mat3-to-quat code and possibly discover places where their code is
suboptimal.
undefined
Sam Hocevar 9 years ago
parent
commit
38733fade7
9 changed files with 121 additions and 113 deletions
  1. +12
    -6
      doc/samples/btphystest.cpp
  2. +7
    -5
      doc/samples/physicobject.h
  3. +17
    -15
      doc/samples/physics/easyconstraint.h
  4. +15
    -13
      doc/samples/physics/easyphysics.cpp
  5. +11
    -9
      doc/samples/physics/easyphysics.h
  6. +10
    -8
      src/camera.cpp
  7. +39
    -8
      src/lol/math/transform.h
  8. +8
    -47
      src/math/transform.cpp
  9. +2
    -2
      src/t/entity/camera.cpp

+ 12
- 6
doc/samples/btphystest.cpp View File

@@ -1,8 +1,14 @@
//
// BtPhysTest
// BtPhysTest
//
// Copyright: (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
// (c) 2012-2013 Sam Hocevar <sam@hocevar.net>
// Copyright © 2009—2015 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
// © 2012—2015 Sam Hocevar <sam@hocevar.net>
//
// This program is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#if HAVE_CONFIG_H
@@ -558,7 +564,7 @@ void BtPhysTest::TickGame(float seconds)
GroundMat = CenterMx *
mat4(quat::fromeuler_xyz(vec3(.0f, 20.f, 20.0f) * seconds))
* GroundMat;
PhysObj->SetTransform(GroundMat[3].xyz, quat(GroundMat));
PhysObj->SetTransform(GroundMat[3].xyz, quat(mat3(GroundMat)));
}
}
#endif //USE_ROTATION
@@ -573,14 +579,14 @@ void BtPhysTest::TickGame(float seconds)
if (i == 0)
{
GroundMat = GroundMat * mat4(quat::fromeuler_xyz(vec3(20.f, .0f, .0f) * seconds));
PhysObj->SetTransform(GroundMat[3].xyz, quat(GroundMat));
PhysObj->SetTransform(GroundMat[3].xyz, quat(mat3(GroundMat)));
}
else if (i == 1)
{
GroundMat =
mat4::translate(vec3(-15.0f, 5.0f, lol::cos(m_loop_value) * 8.f)) *
mat4(quat::fromeuler_xyz(vec3(.0f, lol::cos(m_loop_value) * 20.f, .0f)));
PhysObj->SetTransform(GroundMat[3].xyz, quat(GroundMat));
PhysObj->SetTransform(GroundMat[3].xyz, quat(mat3(GroundMat)));
}
}
}


+ 7
- 5
doc/samples/physicobject.h View File

@@ -1,9 +1,11 @@
//
// Orbital
// Orbital
//
// Copyright: (c) 2009-2013 Cédric Lecacheur <jordx@free.fr>
// (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
// (c) 2012 Sam Hocevar <sam@hocevar.net>
// Copyright © 2009—2013 Cédric Lecacheur <jordx@free.fr>
// © 2009—2013 Benjamin “Touky� Huet <huet.benjamin@gmail.com>
// © 2012—2015 Sam Hocevar <sam@hocevar.net>
//
// No licensing terms yet. All rights reserved.
//

#pragma once
@@ -355,7 +357,7 @@ public:
m_physics->AddToSimulation(new_sim);
}

void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f)))
void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation = lol::quat(lol::mat3(1.0f)))
{
if (m_is_character)
m_character->SetTransform(base_location, base_rotation);


+ 17
- 15
doc/samples/physics/easyconstraint.h View File

@@ -1,12 +1,14 @@
//
// Lol Engine
// Lol Engine
//
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
// (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
// © 2009—2013 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
//
// This library is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#pragma once
@@ -90,8 +92,8 @@ private:
void CustomInitConstraintToHinge()
{
m_hinge_constraint = new btHingeConstraint(*m_a_physobj->m_rigid_body, *m_b_physobj->m_rigid_body,
btTransform(LOL2BT_QUAT(quat(m_a_transform)), LOL2BT_VEC3(m_a_transform[3].xyz * LOL2BT_UNIT)),
btTransform(LOL2BT_QUAT(quat(m_b_transform)), LOL2BT_VEC3(m_b_transform[3].xyz * LOL2BT_UNIT)),
btTransform(LOL2BT_QUAT(quat(mat3(m_a_transform))), LOL2BT_VEC3(m_a_transform[3].xyz * LOL2BT_UNIT)),
btTransform(LOL2BT_QUAT(quat(mat3(m_b_transform))), LOL2BT_VEC3(m_b_transform[3].xyz * LOL2BT_UNIT)),
m_using_ref_a);
m_typed_constraint = m_hinge_constraint;
}
@@ -99,8 +101,8 @@ private:
void CustomInitConstraintToSlider()
{
m_slider_constraint = new btSliderConstraint(*m_a_physobj->m_rigid_body, *m_b_physobj->m_rigid_body,
btTransform(LOL2BT_QUAT(quat(m_a_transform)), LOL2BT_VEC3(m_a_transform[3].xyz * LOL2BT_UNIT)),
btTransform(LOL2BT_QUAT(quat(m_b_transform)), LOL2BT_VEC3(m_b_transform[3].xyz * LOL2BT_UNIT)),
btTransform(LOL2BT_QUAT(quat(mat3(m_a_transform))), LOL2BT_VEC3(m_a_transform[3].xyz * LOL2BT_UNIT)),
btTransform(LOL2BT_QUAT(quat(mat3(m_b_transform))), LOL2BT_VEC3(m_b_transform[3].xyz * LOL2BT_UNIT)),
m_using_ref_a);
m_typed_constraint = m_slider_constraint;
}
@@ -108,16 +110,16 @@ private:
void CustomInitConstraintToConeTwist()
{
m_cone_twist_constraint = new btConeTwistConstraint(*m_a_physobj->m_rigid_body, *m_b_physobj->m_rigid_body,
btTransform(LOL2BT_QUAT(quat(m_a_transform)), LOL2BT_VEC3(m_a_transform[3].xyz * LOL2BT_UNIT)),
btTransform(LOL2BT_QUAT(quat(m_b_transform)), LOL2BT_VEC3(m_b_transform[3].xyz * LOL2BT_UNIT)));
btTransform(LOL2BT_QUAT(quat(mat3(m_a_transform))), LOL2BT_VEC3(m_a_transform[3].xyz * LOL2BT_UNIT)),
btTransform(LOL2BT_QUAT(quat(mat3(m_b_transform))), LOL2BT_VEC3(m_b_transform[3].xyz * LOL2BT_UNIT)));
m_typed_constraint = m_cone_twist_constraint;
}

void CustomInitConstraintTo6Dof()
{
m_6dof_constraint = new btGeneric6DofConstraint(*m_a_physobj->m_rigid_body, *m_b_physobj->m_rigid_body,
btTransform(LOL2BT_QUAT(quat(m_a_transform)), LOL2BT_VEC3(m_a_transform[3].xyz * LOL2BT_UNIT)),
btTransform(LOL2BT_QUAT(quat(m_b_transform)), LOL2BT_VEC3(m_b_transform[3].xyz * LOL2BT_UNIT)),
btTransform(LOL2BT_QUAT(quat(mat3(m_a_transform))), LOL2BT_VEC3(m_a_transform[3].xyz * LOL2BT_UNIT)),
btTransform(LOL2BT_QUAT(quat(mat3(m_b_transform))), LOL2BT_VEC3(m_b_transform[3].xyz * LOL2BT_UNIT)),
m_using_ref_a);
m_typed_constraint = m_6dof_constraint;
}


+ 15
- 13
doc/samples/physics/easyphysics.cpp View File

@@ -1,13 +1,15 @@
//
// Lol Engine
// Lol Engine
//
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
// (c) 2009-2013 Cédric Lecacheur <jordx@free.fr>
// (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
// © 2009—2013 Cédric Lecacheur <jordx@free.fr>
// © 2009—2013 Benjamin “Touky� Huet <huet.benjamin@gmail.com>
//
// This library is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#if HAVE_CONFIG_H
@@ -158,15 +160,15 @@ void EasyPhysic::SetTransform(const lol::vec3& base_location, const lol::quat& b
void EasyPhysic::BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix)
{
mat4 PreviousMatrixLoc = ((m_base_lock_location)?(PreviousMatrix):(lol::mat4::translate(PreviousMatrix[3].xyz)));
mat4 PreviousMatrixRot = ((m_base_lock_rotation)?(lol::mat4(lol::quat(PreviousMatrix))):(lol::mat4(1.f)));
mat4 PreviousMatrixRot = ((m_base_lock_rotation)?(lol::mat4(lol::quat(lol::mat3(PreviousMatrix)))):(lol::mat4(1.f)));
mat4 NewMatrixLoc = ((m_base_lock_location)?(NewMatrix):(lol::mat4::translate(NewMatrix[3].xyz)));
mat4 NewMatrixRot = ((m_base_lock_rotation)?(lol::mat4(lol::quat(NewMatrix))):(lol::mat4(1.f)));
mat4 NewMatrixRot = ((m_base_lock_rotation)?(lol::mat4(lol::quat(lol::mat3(NewMatrix)))):(lol::mat4(1.f)));

if (m_ghost_object || (m_rigid_body->getCollisionFlags() & btCollisionObject::CF_KINEMATIC_OBJECT))
{
mat4 ThisMatrixLoc = NewMatrixLoc * inverse(PreviousMatrixLoc) * lol::mat4::translate(m_local_to_world[3].xyz);
mat4 ThisMatrixRot = NewMatrixRot * inverse(PreviousMatrixRot) * lol::mat4(lol::quat(m_local_to_world));
SetTransform(ThisMatrixLoc[3].xyz, lol::quat(ThisMatrixRot));
mat4 ThisMatrixRot = NewMatrixRot * inverse(PreviousMatrixRot) * lol::mat4(lol::quat(lol::mat3(m_local_to_world)));
SetTransform(ThisMatrixLoc[3].xyz, lol::quat(lol::mat3(ThisMatrixRot)));
}
}

@@ -247,7 +249,7 @@ void EasyPhysic::InitBodyToGhost()
m_collision_object = m_ghost_object;
m_collision_object->setUserPointer(this);

SetTransform(m_local_to_world[3].xyz, lol::quat(m_local_to_world));
SetTransform(m_local_to_world[3].xyz, lol::quat(lol::mat3(m_local_to_world)));

m_ghost_object->setCollisionFlags(m_ghost_object->getCollisionFlags());
}


+ 11
- 9
doc/samples/physics/easyphysics.h View File

@@ -1,12 +1,14 @@
//
// Lol Engine
// Lol Engine
//
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
// (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
// © 2009—2013 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
//
// This library is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#pragma once
@@ -46,9 +48,9 @@ public:

virtual bool CanChangeCollisionChannel() { return (m_rigid_body == NULL); }
virtual mat4 GetTransform();
virtual void SetTransform(const lol::vec3& base_location, const lol::quat& base_rotation=lol::quat(lol::mat4(1.0f)));
virtual void SetTransform(const vec3& base_location, const quat& base_rotation = quat(mat3(1.0f)));
protected:
virtual void BaseTransformChanged(const lol::mat4& PreviousMatrix, const lol::mat4& NewMatrix);
virtual void BaseTransformChanged(const mat4& PreviousMatrix, const mat4& NewMatrix);
public:
virtual void SetMass(float mass);
virtual float GetMass() { return m_mass; }


+ 10
- 8
src/camera.cpp View File

@@ -1,12 +1,14 @@
//
// Lol Engine
// Lol Engine
//
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
// 2012-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
// © 2009—2013 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
//
// This library is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#include <lol/engine-internal.h>
@@ -215,7 +217,7 @@ vec3 Camera::GetRotationEuler() const

quat Camera::GetRotation() const
{
return quat(inverse(m_view_matrix));
return quat(inverse(mat3(m_view_matrix)));
}

// Calculate the frustum height at a given distance from the camera.


+ 39
- 8
src/lol/math/transform.h View File

@@ -1,11 +1,13 @@
//
// Lol Engine
// Lol Engine
//
// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
//
// This library is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#pragma once
@@ -97,8 +99,37 @@ struct quat_t : public linear_ops::base<T>
explicit inline constexpr quat_t(T W)
: w(W), x(0), y(0), z(0) {}

explicit quat_t(mat_t<T,3,3> const &m);
explicit quat_t(mat_t<T,4,4> const &m);
/* Construct a unit quaternion from a pure rotation matrix */
explicit quat_t(mat_t<T,3,3> const &m)
{
T tr = m[0][0] + m[1][1] + m[2][2];

if (tr > T(0))
{
T const p = T(0.5) * std::sqrt(T(1) + tr);
T const q = T(0.25) / p;

w = p;
x = q * (m[1][2] - m[2][1]);
y = q * (m[2][0] - m[0][2]);
z = q * (m[0][1] - m[1][0]);
}
else
{
int i = (m[0][0] > m[1][1] && m[0][0] > m[2][2]) ? 0
: (m[1][1] > m[2][2]) ? 1
: 2;
int j = (i + 1) % 3, k = (i + 2) % 3;

T const p = T(0.5) * lol::sqrt(T(1) - tr + m[i][i] + m[i][i]);
T const q = T(0.25) / p;

w = q * (m[j][k] - m[k][j]);
(*this)[1 + i] = p;
(*this)[1 + j] = q * (m[i][j] + m[j][i]);
(*this)[1 + k] = q * (m[k][i] + m[i][k]);
}
}

LOL_COMMON_MEMBER_OPS(w)



+ 8
- 47
src/math/transform.cpp View File

@@ -1,11 +1,13 @@
//
// Lol Engine
// Lol Engine
//
// Copyright: (c) 2010-2014 Sam Hocevar <sam@hocevar.net>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
// Copyright © 2010—2015 Sam Hocevar <sam@hocevar.net>
//
// This library is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
// and/or modify it under the terms of the Do What the Fuck You Want
// to Public License, Version 2, as published by the WTFPL Task Force.
// See http://www.wtfpl.net/ for more details.
//

#include <lol/engine-internal.h>
@@ -13,47 +15,6 @@
namespace lol
{

static inline void mat_to_quat(quat &that, mat3 const &m)
{
float tr = m[0][0] + m[1][1] + m[2][2];

if (tr > 0)
{
float const p = 0.5f * std::sqrt(1.0f + tr);
float const q = 0.25f / p;

that.w = p;
that.x = q * (m[1][2] - m[2][1]);
that.y = q * (m[2][0] - m[0][2]);
that.z = q * (m[0][1] - m[1][0]);
}
else
{
int i = (m[0][0] > m[1][1] && m[0][0] > m[2][2]) ? 0
: (m[1][1] > m[2][2]) ? 1
: 2;
int j = (i + 1) % 3, k = (i + 2) % 3;

float const p = 0.5f * std::sqrt(1.0f - tr + 2.f * m[i][i]);
float const q = 0.25f / p;

that.w = q * (m[j][k] - m[k][j]);
that[1 + i] = p;
that[1 + j] = q * (m[i][j] + m[j][i]);
that[1 + k] = q * (m[k][i] + m[i][k]);
}
}

template<> quat::quat_t(mat3 const &m)
{
mat_to_quat(*this, m);
}

template<> quat::quat_t(mat4 const &m)
{
mat_to_quat(*this, mat3(m));
}

template<> quat quat::rotate(float degrees, vec3 const &v)
{
float half_angle = radians(degrees) * 0.5f;


+ 2
- 2
src/t/entity/camera.cpp View File

@@ -2,7 +2,7 @@
// Lol Engine — Unit tests
//
// Copyright © 2010—2014 Sam Hocevar <sam@hocevar.net>
// © 2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
// © 2013 Benjamin “Touky” Huet <huet.benjamin@gmail.com>
//
// This program is free software. It comes without any warranty, to
// the extent permitted by applicable law. You can redistribute it
@@ -40,7 +40,7 @@ lolunit_declare_fixture(CameraTest)
target = vec3::zero;
up = vec3::axis_y;
m_lookat = mat4::lookat(eye, target, up);
q_lookat = quat(m_lookat);
q_lookat = quat(mat3(m_lookat));
v_lookat = vec3::toeuler_zyx(q_lookat);
fov = 90.f;
screen_size = 800.f;


Loading…
Cancel
Save