From 41f6650b209b213e35c03ae7f0e6dd91fb565bb8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 7 Feb 2014 01:23:30 -0800 Subject: [PATCH] implement movable independent camera with hydra --- examples/cameraExample.js | 125 ++++++++++++++++++ interface/src/Application.h | 1 + .../src/ControllerScriptingInterface.cpp | 16 +++ interface/src/ControllerScriptingInterface.h | 6 +- interface/src/avatar/MyAvatar.cpp | 36 ++--- libraries/script-engine/src/Quat.cpp | 13 ++ libraries/script-engine/src/Quat.h | 3 + libraries/script-engine/src/ScriptEngine.cpp | 1 + libraries/script-engine/src/ScriptEngine.h | 2 + libraries/script-engine/src/Vec3.cpp | 24 ++++ libraries/script-engine/src/Vec3.h | 31 +++++ 11 files changed, 241 insertions(+), 17 deletions(-) create mode 100644 examples/cameraExample.js create mode 100644 libraries/script-engine/src/Vec3.cpp create mode 100644 libraries/script-engine/src/Vec3.h diff --git a/examples/cameraExample.js b/examples/cameraExample.js new file mode 100644 index 0000000000..d1d91e6ed5 --- /dev/null +++ b/examples/cameraExample.js @@ -0,0 +1,125 @@ +// +// cameraExample.js +// hifi +// +// Created by Brad Hefta-Gaub on 2/6/14. +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// +// This is an example script that demonstrates use of the Camera class +// +// + +var damping = 0.9; +var yaw = 0.0; +var pitch = 0.0; +var roll = 0.0; +var thrust = { x: 0, y: 0, z: 0 }; +var velocity = { x: 0, y: 0, z: 0 }; +var position = { x: MyAvatar.position.x, y: MyAvatar.position.y + 1, z: MyAvatar.position.z }; +var joysticksCaptured = false; +var THRUST_CONTROLLER = 0; +var VIEW_CONTROLLER = 1; + +function checkCamera() { + if (Camera.getMode() == "independent") { + var deltaTime = 1/60; // approximately our FPS - maybe better to be elapsed time since last call + var THRUST_MAG_UP = 800.0; + var THRUST_MAG_DOWN = 300.0; + var THRUST_MAG_FWD = 500.0; + var THRUST_MAG_BACK = 300.0; + var THRUST_MAG_LATERAL = 250.0; + var THRUST_JUMP = 120.0; + var scale = 1.0; + var thrustMultiplier = 1.0; // maybe increase this as you hold it down? + + var YAW_MAG = 500.0; + var PITCH_MAG = 100.0; + var THRUST_MAG_HAND_JETS = THRUST_MAG_FWD; + var JOYSTICK_YAW_MAG = YAW_MAG; + var JOYSTICK_PITCH_MAG = PITCH_MAG * 0.5; + + var thrustJoystickPosition = Controller.getJoystickPosition(THRUST_CONTROLLER); + + var currentOrientation = Camera.getOrientation(); + + var front = Quat.getFront(currentOrientation); + var right = Quat.getRight(currentOrientation); + var up = Quat.getUp(currentOrientation); + + var thrustFront = Vec3.multiply(front, scale * THRUST_MAG_HAND_JETS * thrustJoystickPosition.y * thrustMultiplier * deltaTime); + var thrustRight = Vec3.multiply(right, scale * THRUST_MAG_HAND_JETS * thrustJoystickPosition.x * thrustMultiplier * deltaTime); + + thrust = Vec3.sum(thrust, thrustFront); + thrust = Vec3.sum(thrust, thrustRight); + + // add thrust to velocity + velocity = Vec3.sum(velocity, Vec3.multiply(thrust, deltaTime)); + + // add velocity to position + position = Vec3.sum(position, Vec3.multiply(velocity, deltaTime)); + Camera.setPosition(position); + + // reset thrust + thrust = { x: 0, y: 0, z: 0 }; + + // damp velocity + velocity = Vec3.multiply(velocity, damping); + + // View Controller + var viewJoystickPosition = Controller.getJoystickPosition(VIEW_CONTROLLER); + yaw -= viewJoystickPosition.x * JOYSTICK_YAW_MAG * deltaTime; + pitch += viewJoystickPosition.y * JOYSTICK_PITCH_MAG * deltaTime; + var orientation = Quat.fromPitchYawRoll(pitch, yaw, roll); + Camera.setOrientation(orientation); + } +} + +Script.willSendVisualDataCallback.connect(checkCamera); + + +function keyPressEvent(event) { + if (joysticksCaptured) { + Controller.releaseJoystick(THRUST_CONTROLLER); + Controller.releaseJoystick(VIEW_CONTROLLER); + joysticksCaptured = false; + } + + if (event.text == "1") { + Camera.setMode("first person"); + } + + if (event.text == "2") { + Camera.setMode("mirror"); + } + + if (event.text == "3") { + Camera.setMode("third person"); + } + + if (event.text == "4") { + Camera.setMode("independent"); + joysticksCaptured = true; + Controller.captureJoystick(THRUST_CONTROLLER); + Controller.captureJoystick(VIEW_CONTROLLER); + position = { x: MyAvatar.position.x, y: MyAvatar.position.y + 1, z: MyAvatar.position.z }; + } +} + + +// Map keyPress and mouse move events to our callbacks +Controller.keyPressEvent.connect(keyPressEvent); +Controller.captureKeyEvents({ text: "1" }); +Controller.captureKeyEvents({ text: "2" }); +Controller.captureKeyEvents({ text: "3" }); +Controller.captureKeyEvents({ text: "4" }); +function scriptEnding() { + // re-enabled the standard application for touch events + Controller.releaseKeyEvents({ text: "1" }); + Controller.releaseKeyEvents({ text: "2" }); + Controller.releaseKeyEvents({ text: "3" }); + Controller.releaseKeyEvents({ text: "4" }); + Controller.releaseJoystick(THRUST_CONTROLLER); + Controller.releaseJoystick(VIEW_CONTROLLER); +} +Script.scriptEnding.connect(scriptEnding); + diff --git a/interface/src/Application.h b/interface/src/Application.h index 16173b809c..1ca34a910a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -170,6 +170,7 @@ public: GeometryCache* getGeometryCache() { return &_geometryCache; } TextureCache* getTextureCache() { return &_textureCache; } GlowEffect* getGlowEffect() { return &_glowEffect; } + ControllerScriptingInterface* getControllerScriptingInterface() { return &_controllerScriptingInterface; } AvatarManager& getAvatarManager() { return _avatarManager; } Profile* getProfile() { return &_profile; } diff --git a/interface/src/ControllerScriptingInterface.cpp b/interface/src/ControllerScriptingInterface.cpp index 4d7540c06c..8716116877 100644 --- a/interface/src/ControllerScriptingInterface.cpp +++ b/interface/src/ControllerScriptingInterface.cpp @@ -219,3 +219,19 @@ void ControllerScriptingInterface::releaseKeyEvents(const KeyEvent& event) { } } +bool ControllerScriptingInterface::isJoystickCaptured(int joystickIndex) const { + return _capturedJoysticks.contains(joystickIndex); +} + +void ControllerScriptingInterface::captureJoystick(int joystickIndex) { + if (!isJoystickCaptured(joystickIndex)) { + _capturedJoysticks.insert(joystickIndex); + } +} + +void ControllerScriptingInterface::releaseJoystick(int joystickIndex) { + if (isJoystickCaptured(joystickIndex)) { + _capturedJoysticks.remove(joystickIndex); + } +} + diff --git a/interface/src/ControllerScriptingInterface.h b/interface/src/ControllerScriptingInterface.h index e84039bcb0..1446809a13 100644 --- a/interface/src/ControllerScriptingInterface.h +++ b/interface/src/ControllerScriptingInterface.h @@ -38,7 +38,7 @@ public: bool isMouseCaptured() const { return _mouseCaptured; } bool isTouchCaptured() const { return _touchCaptured; } bool isWheelCaptured() const { return _wheelCaptured; } - + bool isJoystickCaptured(int joystickIndex) const; public slots: virtual bool isPrimaryButtonPressed() const; @@ -70,6 +70,9 @@ public slots: virtual void captureWheelEvents() { _wheelCaptured = true; } virtual void releaseWheelEvents() { _wheelCaptured = false; } + virtual void captureJoystick(int joystickIndex); + virtual void releaseJoystick(int joystickIndex); + private: const PalmData* getPrimaryPalm() const; const PalmData* getPalm(int palmIndex) const; @@ -80,6 +83,7 @@ private: bool _touchCaptured; bool _wheelCaptured; QMultiMap _capturedKeys; + QSet _capturedJoysticks; }; const int NUMBER_OF_SPATIALCONTROLS_PER_PALM = 2; // the hand and the tip diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0bdc5e9748..ba0c98123c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -792,23 +792,27 @@ void MyAvatar::updateThrust(float deltaTime) { const int VIEW_CONTROLLER = 1; for (size_t i = 0; i < getHand().getPalms().size(); ++i) { PalmData& palm = getHand().getPalms()[i]; - if (palm.isActive() && (palm.getSixenseID() == THRUST_CONTROLLER)) { - if (palm.getJoystickY() != 0.f) { - FingerData& finger = palm.getFingers()[0]; - if (finger.isActive()) { + + // If the script hasn't captured this joystick, then let the default behavior work + if (!Application::getInstance()->getControllerScriptingInterface()->isJoystickCaptured(palm.getSixenseID())) { + if (palm.isActive() && (palm.getSixenseID() == THRUST_CONTROLLER)) { + if (palm.getJoystickY() != 0.f) { + FingerData& finger = palm.getFingers()[0]; + if (finger.isActive()) { + } + _thrust += front * _scale * THRUST_MAG_HAND_JETS * palm.getJoystickY() * _thrustMultiplier * deltaTime; + } + if (palm.getJoystickX() != 0.f) { + _thrust += right * _scale * THRUST_MAG_HAND_JETS * palm.getJoystickX() * _thrustMultiplier * deltaTime; + } + } else if (palm.isActive() && (palm.getSixenseID() == VIEW_CONTROLLER)) { + if (palm.getJoystickX() != 0.f) { + _bodyYawDelta -= palm.getJoystickX() * JOYSTICK_YAW_MAG * deltaTime; + } + if (palm.getJoystickY() != 0.f) { + getHand().setPitchUpdate(getHand().getPitchUpdate() + + (palm.getJoystickY() * JOYSTICK_PITCH_MAG * deltaTime)); } - _thrust += front * _scale * THRUST_MAG_HAND_JETS * palm.getJoystickY() * _thrustMultiplier * deltaTime; - } - if (palm.getJoystickX() != 0.f) { - _thrust += right * _scale * THRUST_MAG_HAND_JETS * palm.getJoystickX() * _thrustMultiplier * deltaTime; - } - } else if (palm.isActive() && (palm.getSixenseID() == VIEW_CONTROLLER)) { - if (palm.getJoystickX() != 0.f) { - _bodyYawDelta -= palm.getJoystickX() * JOYSTICK_YAW_MAG * deltaTime; - } - if (palm.getJoystickY() != 0.f) { - getHand().setPitchUpdate(getHand().getPitchUpdate() + - (palm.getJoystickY() * JOYSTICK_PITCH_MAG * deltaTime)); } } diff --git a/libraries/script-engine/src/Quat.cpp b/libraries/script-engine/src/Quat.cpp index 41dafcf40a..a197d59aeb 100644 --- a/libraries/script-engine/src/Quat.cpp +++ b/libraries/script-engine/src/Quat.cpp @@ -9,6 +9,7 @@ // // +#include #include "Quat.h" glm::quat Quat::multiply(const glm::quat& q1, const glm::quat& q2) { @@ -22,3 +23,15 @@ glm::quat Quat::fromVec3(const glm::vec3& vec3) { glm::quat Quat::fromPitchYawRoll(float pitch, float yaw, float roll) { return glm::quat(glm::radians(glm::vec3(pitch, yaw, roll))); } + +glm::vec3 Quat::getFront(const glm::quat& orientation) { + return orientation * IDENTITY_FRONT; +} + +glm::vec3 Quat::getRight(const glm::quat& orientation) { + return orientation * IDENTITY_RIGHT; +} + +glm::vec3 Quat::getUp(const glm::quat& orientation) { + return orientation * IDENTITY_UP; +} diff --git a/libraries/script-engine/src/Quat.h b/libraries/script-engine/src/Quat.h index 7695fe9daf..72fec6d6dc 100644 --- a/libraries/script-engine/src/Quat.h +++ b/libraries/script-engine/src/Quat.h @@ -23,6 +23,9 @@ public slots: glm::quat multiply(const glm::quat& q1, const glm::quat& q2); glm::quat fromVec3(const glm::vec3& vec3); glm::quat fromPitchYawRoll(float pitch, float yaw, float roll); + glm::vec3 getFront(const glm::quat& orientation); + glm::vec3 getRight(const glm::quat& orientation); + glm::vec3 getUp(const glm::quat& orientation); }; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index b3b0736114..738896495b 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -140,6 +140,7 @@ void ScriptEngine::init() { registerGlobalObject("Data", &_dataServerScriptingInterface); registerGlobalObject("Particles", &_particlesScriptingInterface); registerGlobalObject("Quat", &_quatLibrary); + registerGlobalObject("Vec3", &_vec3Library); registerGlobalObject("Voxels", &_voxelsScriptingInterface); diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 98d5860332..b9443c5fe5 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -26,6 +26,7 @@ class ParticlesScriptingInterface; #include "AbstractControllerScriptingInterface.h" #include "DataServerScriptingInterface.h" #include "Quat.h" +#include "Vec3.h" const QString NO_SCRIPT(""); @@ -105,6 +106,7 @@ private: AbstractMenuInterface* _menu; static int _scriptNumber; Quat _quatLibrary; + Vec3 _vec3Library; }; #endif /* defined(__hifi__ScriptEngine__) */ diff --git a/libraries/script-engine/src/Vec3.cpp b/libraries/script-engine/src/Vec3.cpp new file mode 100644 index 0000000000..87b1b510a4 --- /dev/null +++ b/libraries/script-engine/src/Vec3.cpp @@ -0,0 +1,24 @@ +// +// Vec3.cpp +// hifi +// +// Created by Brad Hefta-Gaub on 1/29/14 +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// +// Scriptable Vec3 class library. +// +// + +#include "Vec3.h" + +glm::vec3 Vec3::multiply(const glm::vec3& v1, const glm::vec3& v2) { + return v1 * v2; +} + +glm::vec3 Vec3::multiply(const glm::vec3& v1, float f) { + return v1 * f; +} + +glm::vec3 Vec3::sum(const glm::vec3& v1, const glm::vec3& v2) { + return v1 + v2; +} diff --git a/libraries/script-engine/src/Vec3.h b/libraries/script-engine/src/Vec3.h new file mode 100644 index 0000000000..1cc44f3061 --- /dev/null +++ b/libraries/script-engine/src/Vec3.h @@ -0,0 +1,31 @@ +// +// Vec3.h +// hifi +// +// Created by Brad Hefta-Gaub on 1/29/14 +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// +// Scriptable Vec3 class library. +// +// + +#ifndef __hifi__Vec3__ +#define __hifi__Vec3__ + +#include +#include +#include + +/// Scriptable interface a Vec3ernion helper class object. Used exclusively in the JavaScript API +class Vec3 : public QObject { + Q_OBJECT + +public slots: + glm::vec3 multiply(const glm::vec3& v1, const glm::vec3& v2); + glm::vec3 multiply(const glm::vec3& v1, float f); + glm::vec3 sum(const glm::vec3& v1, const glm::vec3& v2); +}; + + + +#endif /* defined(__hifi__Vec3__) */