From 98cdc656c44f01286af1011fc3bb3aae9d1e0800 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 29 Jan 2014 00:56:08 -0800 Subject: [PATCH] more scripting support, including adding a Quat helper class that makes JS quat math easier --- interface/src/Util.cpp | 28 ------------------- interface/src/Util.h | 2 -- interface/src/world.h | 3 +- libraries/avatars/src/AvatarData.cpp | 7 +++++ libraries/avatars/src/AvatarData.h | 4 +++ libraries/script-engine/src/Quat.cpp | 20 ++++++++++++++ libraries/script-engine/src/Quat.h | 29 ++++++++++++++++++++ libraries/script-engine/src/ScriptEngine.cpp | 2 ++ libraries/script-engine/src/ScriptEngine.h | 2 ++ libraries/shared/src/SharedUtil.cpp | 28 +++++++++++++++++++ libraries/shared/src/SharedUtil.h | 6 ++++ 11 files changed, 100 insertions(+), 31 deletions(-) create mode 100644 libraries/script-engine/src/Quat.cpp create mode 100644 libraries/script-engine/src/Quat.h diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index a2e518b2d7..ef7e049d75 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -105,34 +105,6 @@ glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2) { return glm::angleAxis(angle, axis); } -// Safe version of glm::eulerAngles; uses the factorization method described in David Eberly's -// http://www.geometrictools.com/Documentation/EulerAngles.pdf (via Clyde, -// https://github.com/threerings/clyde/blob/master/src/main/java/com/threerings/math/Quaternion.java) -glm::vec3 safeEulerAngles(const glm::quat& q) { - float sy = 2.0f * (q.y * q.w - q.x * q.z); - if (sy < 1.0f - EPSILON) { - if (sy > -1.0f + EPSILON) { - return glm::degrees(glm::vec3( - atan2f(q.y * q.z + q.x * q.w, 0.5f - (q.x * q.x + q.y * q.y)), - asinf(sy), - atan2f(q.x * q.y + q.z * q.w, 0.5f - (q.y * q.y + q.z * q.z)))); - - } else { - // not a unique solution; x + z = atan2(-m21, m11) - return glm::degrees(glm::vec3( - 0.0f, - PIf * -0.5f, - atan2f(q.x * q.w - q.y * q.z, 0.5f - (q.x * q.x + q.z * q.z)))); - } - } else { - // not a unique solution; x - z = atan2(-m21, m11) - return glm::degrees(glm::vec3( - 0.0f, - PIf * 0.5f, - -atan2f(q.x * q.w - q.y * q.z, 0.5f - (q.x * q.x + q.z * q.z)))); - } -} - // Safe version of glm::mix; based on the code in Nick Bobick's article, // http://www.gamasutra.com/features/19980703/quaternions_01.htm (via Clyde, // https://github.com/threerings/clyde/blob/master/src/main/java/com/threerings/math/Quaternion.java) diff --git a/interface/src/Util.h b/interface/src/Util.h index 2a812120f0..09d1fa0484 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -54,8 +54,6 @@ float angleBetween(const glm::vec3& v1, const glm::vec3& v2); glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2); -glm::vec3 safeEulerAngles(const glm::quat& q); - glm::quat safeMix(const glm::quat& q1, const glm::quat& q2, float alpha); glm::vec3 extractTranslation(const glm::mat4& matrix); diff --git a/interface/src/world.h b/interface/src/world.h index a226dc228e..8d3bd7322e 100644 --- a/interface/src/world.h +++ b/interface/src/world.h @@ -9,8 +9,9 @@ #ifndef __interface__world__ #define __interface__world__ - +#ifndef PIf #define PIf 3.14159265f +#endif const float GRAVITY_EARTH = 9.80665f; const float EDGE_SIZE_GROUND_PLANE = 20.f; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 8f548869ec..44f71c7aec 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -276,3 +276,10 @@ void AvatarData::setClampedTargetScale(float targetScale) { _targetScale = targetScale; qDebug() << "Changed scale to " << _targetScale; } + +void AvatarData::setOrientation(const glm::quat& orientation) { + glm::vec3 eulerAngles = safeEulerAngles(orientation); + _bodyPitch = eulerAngles.x; + _bodyYaw = eulerAngles.y; + _bodyRoll = eulerAngles.z; +} diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index fc9bad7f02..7300da041e 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -69,6 +69,9 @@ class AvatarData : public NodeData { Q_PROPERTY(float bodyPitch READ getBodyPitch WRITE setBodyPitch) Q_PROPERTY(float bodyRoll READ getBodyRoll WRITE setBodyRoll) Q_PROPERTY(QString chatMessage READ getQStringChatMessage WRITE setChatMessage) + + Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation) + public: AvatarData(); ~AvatarData(); @@ -91,6 +94,7 @@ public: void setBodyRoll(float bodyRoll) { _bodyRoll = bodyRoll; } glm::quat getOrientation() const { return glm::quat(glm::radians(glm::vec3(_bodyPitch, _bodyYaw, _bodyRoll))); } + void setOrientation(const glm::quat& orientation); // Scale float getTargetScale() const { return _targetScale; } diff --git a/libraries/script-engine/src/Quat.cpp b/libraries/script-engine/src/Quat.cpp new file mode 100644 index 0000000000..12900c29c7 --- /dev/null +++ b/libraries/script-engine/src/Quat.cpp @@ -0,0 +1,20 @@ +// +// Quat.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 1/29/14 +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// +// Scriptable Quaternion class library. +// +// + +#include "Quat.h" + +glm::quat Quat::multiply(const glm::quat& q1, const glm::quat& q2) { + return q1 * q2; +} + +glm::quat Quat::fromVec3(const glm::vec3& vec3) { + return glm::quat(vec3); +} diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h new file mode 100644 index 0000000000..6bcd121808 --- /dev/null +++ b/libraries/script-engine/src/Quat.h @@ -0,0 +1,29 @@ +// +// Quat.h +// hifi +// +// Created by Brad Hefta-Gaub on 1/29/14 +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// +// Scriptable Quaternion class library. +// +// + +#ifndef __hifi__Quat__ +#define __hifi__Quat__ + +#include +#include + +/// Scriptable interface a Quaternion helper class object. Used exclusively in the JavaScript API +class Quat : public QObject { + Q_OBJECT + +public slots: + glm::quat multiply(const glm::quat& q1, const glm::quat& q2); + glm::quat fromVec3(const glm::vec3& vec3); +}; + + + +#endif /* defined(__hifi__Quat__) */ diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 6ca59137be..28cb49f6f7 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -134,6 +134,8 @@ void ScriptEngine::init() { registerGlobalObject("Controller", _controllerScriptingInterface); registerGlobalObject("Data", &_dataServerScriptingInterface); registerGlobalObject("Particles", &_particlesScriptingInterface); + registerGlobalObject("Quat", &_quatLibrary); + registerGlobalObject("Voxels", &_voxelsScriptingInterface); QScriptValue treeScaleValue = _engine.newVariant(QVariant(TREE_SCALE)); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index b36e2425fe..ef55e14109 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -25,6 +25,7 @@ class ParticlesScriptingInterface; #include "AbstractControllerScriptingInterface.h" #include "DataServerScriptingInterface.h" +#include "Quat.h" const QString NO_SCRIPT(""); @@ -94,6 +95,7 @@ private: QString _fileNameString; AbstractMenuInterface* _menu; static int _scriptNumber; + Quat _quatLibrary; }; #endif /* defined(__hifi__ScriptEngine__) */ diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 00e11e2b19..54a4291c25 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -715,3 +715,31 @@ void debug::checkDeadBeef(void* memoryVoid, int size) { assert(memcmp(memoryAt, DEADBEEF, std::min(size, DEADBEEF_SIZE)) != 0); } +// Safe version of glm::eulerAngles; uses the factorization method described in David Eberly's +// http://www.geometrictools.com/Documentation/EulerAngles.pdf (via Clyde, +// https://github.com/threerings/clyde/blob/master/src/main/java/com/threerings/math/Quaternion.java) +glm::vec3 safeEulerAngles(const glm::quat& q) { + float sy = 2.0f * (q.y * q.w - q.x * q.z); + if (sy < 1.0f - EPSILON) { + if (sy > -1.0f + EPSILON) { + return glm::degrees(glm::vec3( + atan2f(q.y * q.z + q.x * q.w, 0.5f - (q.x * q.x + q.y * q.y)), + asinf(sy), + atan2f(q.x * q.y + q.z * q.w, 0.5f - (q.y * q.y + q.z * q.z)))); + + } else { + // not a unique solution; x + z = atan2(-m21, m11) + return glm::degrees(glm::vec3( + 0.0f, + PIf * -0.5f, + atan2f(q.x * q.w - q.y * q.z, 0.5f - (q.x * q.x + q.z * q.z)))); + } + } else { + // not a unique solution; x - z = atan2(-m21, m11) + return glm::degrees(glm::vec3( + 0.0f, + PIf * 0.5f, + -atan2f(q.x * q.w - q.y * q.z, 0.5f - (q.x * q.x + q.z * q.z)))); + } +} + diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 174742fcf3..399bf40204 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -176,4 +176,10 @@ int unpackFloatScalarFromSignedTwoByteFixed(int16_t* byteFixedPointer, float* de int packFloatVec3ToSignedTwoByteFixed(unsigned char* destBuffer, const glm::vec3& srcVector, int radix); int unpackFloatVec3FromSignedTwoByteFixed(unsigned char* sourceBuffer, glm::vec3& destination, int radix); +#ifndef PIf +#define PIf 3.14159265f +#endif + +glm::vec3 safeEulerAngles(const glm::quat& q); + #endif /* defined(__hifi__SharedUtil__) */