Merge branch 'master' of https://github.com/worklist/hifi into 19495

This commit is contained in:
stojce 2014-03-15 19:46:26 +01:00
commit 19e60a1fc0
35 changed files with 436 additions and 174 deletions

View file

@ -74,7 +74,7 @@ function checkCamera(deltaTime) {
if (yaw < -360) {
yaw += 360;
}
var orientation = Quat.fromPitchYawRoll(pitch, yaw, roll);
var orientation = Quat.fromPitchYawRollDegrees(pitch, yaw, roll);
Camera.setOrientation(orientation);
}
}

View file

@ -14,10 +14,17 @@ var cumulativeTime = 0.0;
Script.update.connect(function(deltaTime) {
cumulativeTime += deltaTime;
MyAvatar.setJointData("joint_R_hip", Quat.fromPitchYawRoll(0.0, 0.0, AMPLITUDE * Math.sin(cumulativeTime * FREQUENCY)));
MyAvatar.setJointData("joint_L_hip", Quat.fromPitchYawRoll(0.0, 0.0, -AMPLITUDE * Math.sin(cumulativeTime * FREQUENCY)));
MyAvatar.setJointData("joint_R_knee", Quat.fromPitchYawRoll(0.0, 0.0,
MyAvatar.setJointData("joint_R_hip", Quat.fromPitchYawRollDegrees(0.0, 0.0, AMPLITUDE * Math.sin(cumulativeTime * FREQUENCY)));
MyAvatar.setJointData("joint_L_hip", Quat.fromPitchYawRollDegrees(0.0, 0.0, -AMPLITUDE * Math.sin(cumulativeTime * FREQUENCY)));
MyAvatar.setJointData("joint_R_knee", Quat.fromPitchYawRollDegrees(0.0, 0.0,
AMPLITUDE * (1.0 + Math.sin(cumulativeTime * FREQUENCY))));
MyAvatar.setJointData("joint_L_knee", Quat.fromPitchYawRoll(0.0, 0.0,
MyAvatar.setJointData("joint_L_knee", Quat.fromPitchYawRollDegrees(0.0, 0.0,
AMPLITUDE * (1.0 - Math.sin(cumulativeTime * FREQUENCY))));
});
Script.scriptEnding.connect(function() {
MyAvatar.clearJointData("joint_R_hip");
MyAvatar.clearJointData("joint_L_hip");
MyAvatar.clearJointData("joint_R_knee");
MyAvatar.clearJointData("joint_L_knee");
});

View file

@ -19,11 +19,14 @@ var pitchFromMouse = 0;
var isMouseDown = false;
var BULLET_VELOCITY = 5.0;
var LEFT_BUTTON_3 = 3;
// Load some sound to use for loading and firing
var fireSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guns/GUN-SHOT2.raw");
var loadSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guns/Gun_Reload_Weapon22.raw");
var impactSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guns/BulletImpact2.raw");
var targetLaunchSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Guns/GUN-SHOT2.raw");
var audioOptions = new AudioInjectionOptions();
audioOptions.volume = 0.9;
@ -34,6 +37,10 @@ for (t = 0; t < numberOfTriggers; t++) {
triggerPulled[t] = false;
}
var isLaunchButtonPressed = false;
var score = 0;
// Create a reticle image in center of screen
var screenSize = Controller.getViewportDimensions();
var reticle = Overlays.addOverlay("image", {
@ -46,14 +53,32 @@ var reticle = Overlays.addOverlay("image", {
alpha: 1
});
var text = Overlays.addOverlay("text", {
x: screenSize.x / 2 - 100,
y: screenSize.y / 2 - 50,
width: 150,
height: 50,
color: { red: 0, green: 0, blue: 0},
textColor: { red: 255, green: 0, blue: 0},
topMargin: 4,
leftMargin: 4,
text: "Score: " + score
});
function printVector(string, vector) {
print(string + " " + vector.x + ", " + vector.y + ", " + vector.z);
}
function shootBullet(position, velocity) {
var BULLET_SIZE = 0.02;
var BULLET_GRAVITY = -0.02;
Particles.addParticle(
{ position: position,
radius: BULLET_SIZE,
color: { red: 200, green: 0, blue: 0 },
velocity: velocity,
gravity: { x: 0, y: -0.1, z: 0 },
gravity: { x: 0, y: BULLET_GRAVITY, z: 0 },
damping: 0 });
// Play firing sounds
@ -61,8 +86,41 @@ function shootBullet(position, velocity) {
Audio.playSound(fireSound, audioOptions);
}
function shootTarget() {
var TARGET_SIZE = 0.25;
var TARGET_GRAVITY = -0.6;
var TARGET_UP_VELOCITY = 3.0;
var TARGET_FWD_VELOCITY = 5.0;
var DISTANCE_TO_LAUNCH_FROM = 3.0;
var camera = Camera.getPosition();
//printVector("camera", camera);
var forwardVector = Quat.getFront(Camera.getOrientation());
//printVector("forwardVector", forwardVector);
var newPosition = Vec3.sum(camera, Vec3.multiply(forwardVector, DISTANCE_TO_LAUNCH_FROM));
//printVector("newPosition", newPosition);
var velocity = Vec3.multiply(forwardVector, TARGET_FWD_VELOCITY);
velocity.y += TARGET_UP_VELOCITY;
//printVector("velocity", velocity);
Particles.addParticle(
{ position: newPosition,
radius: TARGET_SIZE,
color: { red: 0, green: 200, blue: 200 },
velocity: velocity,
gravity: { x: 0, y: TARGET_GRAVITY, z: 0 },
lifetime: 1000.0,
damping: 0.99 });
// Play target shoot sound
audioOptions.position = newPosition;
Audio.playSound(targetLaunchSound, audioOptions);
}
function particleCollisionWithVoxel(particle, voxel, penetration) {
Vec3.print('particleCollisionWithVoxel() ... penetration=', penetration);
var HOLE_SIZE = 0.125;
var particleProperties = Particles.getParticleProperties(particle);
var position = particleProperties.position;
@ -74,11 +132,27 @@ function particleCollisionWithVoxel(particle, voxel, penetration) {
Audio.playSound(impactSound, audioOptions);
}
function particleCollisionWithParticle(particle1, particle2) {
print("Particle/Particle!");
score++;
Overlays.editOverlay(text, { text: "Score: " + score } );
Particles.deleteParticle(particle1);
Particles.deleteParticle(particle2);
}
function keyPressEvent(event) {
// if our tools are off, then don't do anything
if (event.text == "t") {
shootTarget();
}
}
function update(deltaTime) {
// Check for mouseLook movement, update rotation
// rotate body yaw for yaw received from mouse
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3( { x: 0, y: yawFromMouse, z: 0 } ));
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3Radians( { x: 0, y: yawFromMouse, z: 0 } ));
MyAvatar.orientation = newOrientation;
yawFromMouse = 0;
@ -87,6 +161,15 @@ function update(deltaTime) {
MyAvatar.headPitch = newPitch;
pitchFromMouse = 0;
// Check hydra controller for launch button press
if (!isLaunchButtonPressed && Controller.isButtonPressed(LEFT_BUTTON_3)) {
isLaunchButtonPressed = true;
shootTarget();
} else if (isLaunchButtonPressed && !Controller.isButtonPressed(LEFT_BUTTON_3)) {
isLaunchButtonPressed = false;
}
// Check hydra controller for trigger press
var numberOfTriggers = Controller.getNumberOfTriggers();
@ -175,14 +258,17 @@ function mouseMoveEvent(event) {
function scriptEnding() {
Overlays.deleteOverlay(reticle);
Overlays.deleteOverlay(text);
}
Particles.particleCollisionWithVoxel.connect(particleCollisionWithVoxel);
Particles.particleCollisionWithParticle.connect(particleCollisionWithParticle);
Script.scriptEnding.connect(scriptEnding);
Script.update.connect(update);
Controller.mousePressEvent.connect(mousePressEvent);
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
Controller.mouseMoveEvent.connect(mouseMoveEvent);
Controller.keyPressEvent.connect(keyPressEvent);

View file

@ -184,7 +184,7 @@ function flyWithHydra(deltaTime) {
// change the body yaw based on our x controller
var orientation = MyAvatar.orientation;
var deltaOrientation = Quat.fromPitchYawRoll(0, (-1 * viewJoystickPosition.x * JOYSTICK_YAW_MAG * deltaTime), 0);
var deltaOrientation = Quat.fromPitchYawRollDegrees(0, (-1 * viewJoystickPosition.x * JOYSTICK_YAW_MAG * deltaTime), 0);
MyAvatar.orientation = Quat.multiply(orientation, deltaOrientation);
// change the headPitch based on our x controller

View file

@ -54,7 +54,7 @@ function update(deltaTime) {
print("update()...");
}
// rotate body yaw for yaw received from mouse
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3( { x: 0, y: yawFromMouse, z: 0 } ));
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3Radians( { x: 0, y: yawFromMouse, z: 0 } ));
if (wantDebugging) {
print("changing orientation"
+ " [old]MyAvatar.orientation="+MyAvatar.orientation.x + "," + MyAvatar.orientation.y + ","

View file

@ -45,7 +45,7 @@ function touchUpdateEvent(event) {
function update(deltaTime) {
// rotate body yaw for yaw received from mouse
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3( { x: 0, y: yawFromMouse, z: 0 } ));
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromPitchYawRollRadians(0, yawFromMouse, 0));
if (wantDebugging) {
print("changing orientation"
+ " [old]MyAvatar.orientation="+MyAvatar.orientation.x + "," + MyAvatar.orientation.y + ","

View file

@ -92,7 +92,7 @@ Controller.touchEndEvent.connect(touchEndEvent);
function update(deltaTime) {
// rotate body yaw for yaw received from multitouch rotate
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3( { x: 0, y: yawFromMultiTouch, z: 0 } ));
var newOrientation = Quat.multiply(MyAvatar.orientation, Quat.fromVec3Radians( { x: 0, y: yawFromMultiTouch, z: 0 } ));
if (wantDebugging) {
print("changing orientation"
+ " [old]MyAvatar.orientation="+MyAvatar.orientation.x + "," + MyAvatar.orientation.y + ","

View file

@ -17,7 +17,7 @@ var yawMin = 20;
var isLocal = false;
// set up our VoxelViewer with a position and orientation
var orientation = Quat.fromPitchYawRoll(0, yaw, 0);
var orientation = Quat.fromPitchYawRollDegrees(0, yaw, 0);
function init() {
if (isLocal) {
@ -40,7 +40,7 @@ function keepLooking(deltaTime) {
count++;
if (count % 10 == 0) {
yaw += yawDirection;
orientation = Quat.fromPitchYawRoll(0, yaw, 0);
orientation = Quat.fromPitchYawRollDegrees(0, yaw, 0);
if (yaw > yawMax || yaw < yawMin) {
yawDirection = yawDirection * -1;
}

View file

@ -4,22 +4,22 @@
<context>
<name>Application</name>
<message>
<location filename="src/Application.cpp" line="1362"/>
<location filename="src/Application.cpp" line="1354"/>
<source>Export Voxels</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="1363"/>
<location filename="src/Application.cpp" line="1355"/>
<source>Sparse Voxel Octree Files (*.svo)</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="3573"/>
<location filename="src/Application.cpp" line="3565"/>
<source>Open Script</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="3574"/>
<location filename="src/Application.cpp" line="3566"/>
<source>JavaScript Files (*.js)</source>
<translation type="unfinished"></translation>
</message>
@ -45,7 +45,7 @@
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<location filename="src/ui/ChatWindow.cpp" line="124"/>
<location filename="src/ui/ChatWindow.cpp" line="128"/>
<source>day</source>
<translation>
<numerusform>%n day</numerusform>
@ -53,7 +53,7 @@
</translation>
</message>
<message numerus="yes">
<location filename="src/ui/ChatWindow.cpp" line="124"/>
<location filename="src/ui/ChatWindow.cpp" line="128"/>
<source>hour</source>
<translation>
<numerusform>%n hour</numerusform>
@ -61,7 +61,7 @@
</translation>
</message>
<message numerus="yes">
<location filename="src/ui/ChatWindow.cpp" line="124"/>
<location filename="src/ui/ChatWindow.cpp" line="128"/>
<source>minute</source>
<translation>
<numerusform>%n minute</numerusform>
@ -76,7 +76,7 @@
</translation>
</message>
<message>
<location filename="src/ui/ChatWindow.cpp" line="179"/>
<location filename="src/ui/ChatWindow.cpp" line="183"/>
<source>%1 online now:</source>
<translation type="unfinished"></translation>
</message>

View file

@ -27,7 +27,6 @@
#include <QColorDialog>
#include <QDesktopWidget>
#include <QCheckBox>
#include <QHBoxLayout>
#include <QImage>
#include <QKeyEvent>
#include <QMainWindow>
@ -292,14 +291,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
ResourceCache::setNetworkAccessManager(_networkAccessManager);
ResourceCache::setRequestLimit(3);
QWidget* centralWidget = new QWidget();
QHBoxLayout* mainLayout = new QHBoxLayout();
mainLayout->setSpacing(0);
mainLayout->setContentsMargins(0, 0, 0, 0);
centralWidget->setLayout(mainLayout);
_glWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
centralWidget->layout()->addWidget(_glWidget);
_window->setCentralWidget(centralWidget);
_window->setCentralWidget(_glWidget);
restoreSizeAndPosition();
@ -1615,8 +1607,8 @@ bool Application::isLookingAtMyAvatar(Avatar* avatar) {
}
void Application::updateLOD() {
// adjust it unless we were asked to disable this feature
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD)) {
// adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) {
Menu::getInstance()->autoAdjustLOD(_fps);
}
}

View file

@ -147,6 +147,7 @@ public:
glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel);
QGLWidget* getGLWidget() { return _glWidget; }
bool isThrottleRendering() const { return _glWidget->isThrottleRendering(); }
MyAvatar* getAvatar() { return _myAvatar; }
Audio* getAudio() { return &_audio; }
Camera* getCamera() { return &_myCamera; }
@ -339,7 +340,7 @@ private:
void displayRearMirrorTools();
QMainWindow* _window;
QGLWidget* _glWidget;
GLCanvas* _glWidget; // our GLCanvas has a couple extra features
bool _statsExpanded;
BandwidthMeter _bandwidthMeter;

View file

@ -10,6 +10,7 @@
#include "Util.h"
#include "world.h"
#include "devices/SixenseManager.h"
const int NUM_ELEMENTS = 3;
const float RANGE_BBALLS = 0.5f;

View file

@ -8,6 +8,7 @@
#include <HandData.h>
#include "Application.h"
#include "devices/SixenseManager.h"
#include "ControllerScriptingInterface.h"
ControllerScriptingInterface::ControllerScriptingInterface() :

View file

@ -13,23 +13,33 @@
#include <QUrl>
#include <QMainWindow>
GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer, QGL::NoStencilBuffer)),
const int MSECS_PER_FRAME_WHEN_THROTTLED = 66;
GLCanvas::GLCanvas() : QGLWidget(QGLFormat(QGL::NoDepthBuffer)),
_throttleRendering(false),
_idleRenderInterval(100)
_idleRenderInterval(MSECS_PER_FRAME_WHEN_THROTTLED)
{
}
bool GLCanvas::isThrottleRendering() const {
return _throttleRendering || Application::getInstance()->getWindow()->isMinimized();
}
void GLCanvas::initializeGL() {
Application::getInstance()->initializeGL();
setAttribute(Qt::WA_AcceptTouchEvents);
setAcceptDrops(true);
connect(Application::getInstance(), SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(activeChanged(Qt::ApplicationState)));
connect(&_frameTimer, SIGNAL(timeout()), this, SLOT(throttleRender()));
// Note, we *DO NOT* want Qt to automatically swap buffers for us. This results in the "ringing" bug mentioned in WL#19514 when we're throttling the framerate.
setAutoBufferSwap(false);
}
void GLCanvas::paintGL() {
if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) {
Application::getInstance()->paintGL();
swapBuffers();
}
}
@ -86,6 +96,7 @@ void GLCanvas::throttleRender() {
_frameTimer.start(_idleRenderInterval);
if (!Application::getInstance()->getWindow()->isMinimized()) {
Application::getInstance()->paintGL();
swapBuffers();
}
}

View file

@ -17,6 +17,7 @@ class GLCanvas : public QGLWidget {
Q_OBJECT
public:
GLCanvas();
bool isThrottleRendering() const;
protected:
QTimer _frameTimer;

View file

@ -1067,13 +1067,11 @@ void Menu::showMetavoxelEditor() {
void Menu::showChat() {
if (!_chatWindow) {
_chatWindow = new ChatWindow();
QMainWindow* mainWindow = Application::getInstance()->getWindow();
QBoxLayout* boxLayout = static_cast<QBoxLayout*>(mainWindow->centralWidget()->layout());
boxLayout->addWidget(_chatWindow, 0, Qt::AlignRight);
Application::getInstance()->getWindow()->addDockWidget(Qt::RightDockWidgetArea, _chatWindow = new ChatWindow());
} else {
if (!_chatWindow->isVisible()) {
_chatWindow->show();
if (!_chatWindow->toggleViewAction()->isChecked()) {
_chatWindow->toggleViewAction()->trigger();
}
}
}
@ -1081,8 +1079,8 @@ void Menu::showChat() {
void Menu::toggleChat() {
#ifdef HAVE_QXMPP
_chatAction->setEnabled(XmppClient::getInstance().getXMPPClient().isConnected());
if (!_chatAction->isEnabled() && _chatWindow) {
_chatWindow->hide();
if (!_chatAction->isEnabled() && _chatWindow && _chatWindow->toggleViewAction()->isChecked()) {
_chatWindow->toggleViewAction()->trigger();
}
#endif
}

View file

@ -206,8 +206,8 @@ void Hand::collideAgainstOurself() {
}
// ignoring everything below the parent of the parent of the last free joint
int skipIndex = skeletonModel.getParentJointIndex(skeletonModel.getParentJointIndex(
skeletonModel.getLastFreeJointIndex((i == leftPalmIndex) ? skeletonModel.getLeftHandJointIndex() :
(i == rightPalmIndex) ? skeletonModel.getRightHandJointIndex() : -1)));
skeletonModel.getLastFreeJointIndex(((int)i == leftPalmIndex) ? skeletonModel.getLeftHandJointIndex() :
((int)i == rightPalmIndex) ? skeletonModel.getRightHandJointIndex() : -1)));
handCollisions.clear();
if (_owningAvatar->findSphereCollisions(palm.getPosition(), scaledPalmRadius, handCollisions, skipIndex)) {

View file

@ -36,9 +36,9 @@ Head::Head(Avatar* owningAvatar) :
_leftEyeBlinkVelocity(0.0f),
_rightEyeBlinkVelocity(0.0f),
_timeWithoutTalking(0.0f),
_tweakedPitch(0.f),
_tweakedYaw(0.f),
_tweakedRoll(0.f),
_pitchTweak(0.f),
_yawTweak(0.f),
_rollTweak(0.f),
_isCameraMoving(false),
_faceModel(this)
{
@ -202,15 +202,15 @@ glm::vec3 Head::getScalePivot() const {
}
float Head::getTweakedYaw() const {
return glm::clamp(_yaw + _tweakedYaw, MIN_HEAD_YAW, MAX_HEAD_YAW);
return glm::clamp(_yaw + _yawTweak, MIN_HEAD_YAW, MAX_HEAD_YAW);
}
float Head::getTweakedPitch() const {
return glm::clamp(_pitch + _tweakedPitch, MIN_HEAD_PITCH, MAX_HEAD_PITCH);
return glm::clamp(_pitch + _pitchTweak, MIN_HEAD_PITCH, MAX_HEAD_PITCH);
}
float Head::getTweakedRoll() const {
return glm::clamp(_roll + _tweakedRoll, MIN_HEAD_ROLL, MAX_HEAD_ROLL);
return glm::clamp(_roll + _rollTweak, MIN_HEAD_ROLL, MAX_HEAD_ROLL);
}
void Head::applyCollision(CollisionInfo& collision) {

View file

@ -70,10 +70,15 @@ public:
/// Returns the point about which scaling occurs.
glm::vec3 getScalePivot() const;
void tweakPitch(float pitch) { _tweakedPitch = pitch; }
void tweakYaw(float yaw) { _tweakedYaw = yaw; }
void tweakRoll(float roll) { _tweakedRoll = roll; }
void setPitchTweak(float pitch) { _pitchTweak = pitch; }
float getPitchTweak() const { return _pitchTweak; }
void setYawTweak(float yaw) { _yawTweak = yaw; }
float getYawTweak() const { return _yawTweak; }
void setRollTweak(float roll) { _rollTweak = roll; }
float getRollTweak() const { return _rollTweak; }
virtual float getTweakedPitch() const;
virtual float getTweakedYaw() const;
virtual float getTweakedRoll() const;
@ -104,9 +109,9 @@ private:
float _timeWithoutTalking;
// tweaked angles affect the rendered head, but not the camera
float _tweakedPitch;
float _tweakedYaw;
float _tweakedRoll;
float _pitchTweak;
float _yawTweak;
float _rollTweak;
bool _isCameraMoving;
FaceModel _faceModel;

View file

@ -363,8 +363,9 @@ void MyAvatar::updateFromGyros(float deltaTime) {
// restore rotation, lean to neutral positions
const float RESTORE_PERIOD = 1.f; // seconds
float restorePercentage = glm::clamp(deltaTime/RESTORE_PERIOD, 0.f, 1.f);
head->setYaw(glm::mix(head->getYaw(), 0.0f, restorePercentage));
head->setRoll(glm::mix(head->getRoll(), 0.0f, restorePercentage));
head->setPitchTweak(glm::mix(head->getPitchTweak(), 0.0f, restorePercentage));
head->setYawTweak(glm::mix(head->getYawTweak(), 0.0f, restorePercentage));
head->setRollTweak(glm::mix(head->getRollTweak(), 0.0f, restorePercentage));
head->setLeanSideways(glm::mix(head->getLeanSideways(), 0.0f, restorePercentage));
head->setLeanForward(glm::mix(head->getLeanForward(), 0.0f, restorePercentage));
return;
@ -375,9 +376,9 @@ void MyAvatar::updateFromGyros(float deltaTime) {
const float AVATAR_HEAD_PITCH_MAGNIFY = 1.0f;
const float AVATAR_HEAD_YAW_MAGNIFY = 1.0f;
const float AVATAR_HEAD_ROLL_MAGNIFY = 1.0f;
head->tweakPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY);
head->tweakYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY);
head->tweakRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY);
head->setPitchTweak(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY);
head->setYawTweak(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY);
head->setRollTweak(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY);
// Update torso lean distance based on accelerometer data
const float TORSO_LENGTH = 0.5f;

View file

@ -123,6 +123,7 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector<int>& fingerJoin
return;
}
const FBXGeometry& geometry = _geometry->getFBXGeometry();
setJointPosition(jointIndex, palm.getPosition());
float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f;
glm::quat palmRotation;
getJointRotation(jointIndex, palmRotation, true);
@ -154,7 +155,6 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector<int>& fingerJoin
// no point in continuing if there are no fingers
if (palm.getNumFingers() == 0 || fingerJointIndices.isEmpty()) {
stretchArm(jointIndex, palm.getPosition());
return;
}
@ -172,8 +172,6 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector<int>& fingerJoin
setJointRotation(fingerJointIndex, rotationBetween(palmRotation * jointVector, fingerVector) * palmRotation, true);
}
stretchArm(jointIndex, palm.getPosition());
}
void SkeletonModel::updateJointState(int index) {
@ -200,41 +198,3 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const
glm::normalize(inverse * axes[0])) * joint.rotation;
}
void SkeletonModel::stretchArm(int jointIndex, const glm::vec3& position) {
// find out where the hand is pointing
glm::quat handRotation;
getJointRotation(jointIndex, handRotation, true);
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::vec3 forwardVector(jointIndex == geometry.rightHandJointIndex ? -1.0f : 1.0f, 0.0f, 0.0f);
glm::vec3 handVector = handRotation * forwardVector;
// align elbow with hand
const FBXJoint& joint = geometry.joints.at(jointIndex);
if (joint.parentIndex == -1) {
return;
}
glm::quat elbowRotation;
getJointRotation(joint.parentIndex, elbowRotation, true);
applyRotationDelta(joint.parentIndex, rotationBetween(elbowRotation * forwardVector, handVector), false);
// set position according to normal length
float scale = extractUniformScale(_scale);
glm::vec3 handPosition = position - _translation;
glm::vec3 elbowPosition = handPosition - handVector * joint.distanceToParent * scale;
// set shoulder orientation to point to elbow
const FBXJoint& parentJoint = geometry.joints.at(joint.parentIndex);
if (parentJoint.parentIndex == -1) {
return;
}
glm::quat shoulderRotation;
getJointRotation(parentJoint.parentIndex, shoulderRotation, true);
applyRotationDelta(parentJoint.parentIndex, rotationBetween(shoulderRotation * forwardVector,
elbowPosition - extractTranslation(_jointStates.at(parentJoint.parentIndex).transform)), false);
// update the shoulder state
updateJointState(parentJoint.parentIndex);
// adjust the elbow's local translation
setJointTranslation(joint.parentIndex, elbowPosition);
}

View file

@ -43,10 +43,6 @@ protected:
private:
/// Using the current position and rotation of the identified (hand) joint, computes a
/// reasonable stretched configuration for the connected arm.
void stretchArm(int jointIndex, const glm::vec3& position);
Avatar* _owningAvatar;
};

View file

@ -6,17 +6,33 @@
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
#ifdef HAVE_SIXENSE
#include "sixense.h"
#endif
#include <vector>
#include "Application.h"
#include "SixenseManager.h"
using namespace std;
SixenseManager::SixenseManager() : _lastMovement(0) {
#ifdef HAVE_SIXENSE
const int CALIBRATION_STATE_IDLE = 0;
const int CALIBRATION_STATE_X = 1;
const int CALIBRATION_STATE_Y = 2;
const int CALIBRATION_STATE_Z = 3;
const int CALIBRATION_STATE_COMPLETE = 4;
// default (expected) location of neck in sixense space
const float NECK_X = 250.f; // millimeters
const float NECK_Y = 300.f; // millimeters
const float NECK_Z = 300.f; // millimeters
#endif
SixenseManager::SixenseManager() {
#ifdef HAVE_SIXENSE
_lastMovement = 0;
_calibrationState = CALIBRATION_STATE_IDLE;
// By default we assume the _neckBase (in orb frame) is as high above the orb
// as the "torso" is below it.
_neckBase = glm::vec3(NECK_X, -NECK_Y, NECK_Z);
sixenseInit();
#endif
}
@ -48,12 +64,18 @@ void SixenseManager::update(float deltaTime) {
Hand* hand = avatar->getHand();
int maxControllers = sixenseGetMaxControllers();
for (int i = 0; i < maxControllers; i++) {
// we only support two controllers
sixenseControllerData controllers[2];
int numActiveControllers = 0;
for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) {
if (!sixenseIsControllerEnabled(i)) {
continue;
}
sixenseControllerData data;
sixenseGetNewestData(i, &data);
sixenseControllerData* data = controllers + numActiveControllers;
++numActiveControllers;
sixenseGetNewestData(i, data);
// Set palm position and normal based on Hydra position/orientation
@ -61,7 +83,7 @@ void SixenseManager::update(float deltaTime) {
PalmData* palm;
bool foundHand = false;
for (size_t j = 0; j < hand->getNumPalms(); j++) {
if (hand->getPalms()[j].getSixenseID() == data.controller_index) {
if (hand->getPalms()[j].getSixenseID() == data->controller_index) {
palm = &(hand->getPalms()[j]);
foundHand = true;
}
@ -70,26 +92,27 @@ void SixenseManager::update(float deltaTime) {
PalmData newPalm(hand);
hand->getPalms().push_back(newPalm);
palm = &(hand->getPalms()[hand->getNumPalms() - 1]);
palm->setSixenseID(data.controller_index);
printf("Found new Sixense controller, ID %i\n", data.controller_index);
palm->setSixenseID(data->controller_index);
printf("Found new Sixense controller, ID %i\n", data->controller_index);
}
palm->setActive(true);
// Read controller buttons and joystick into the hand
palm->setControllerButtons(data.buttons);
palm->setTrigger(data.trigger);
palm->setJoystick(data.joystick_x, data.joystick_y);
glm::vec3 position(data.pos[0], data.pos[1], data.pos[2]);
// Adjust for distance between acquisition 'orb' and the user's torso
// (distance to the right of body center, distance below torso, distance behind torso)
const glm::vec3 SPHERE_TO_TORSO(-250.f, -300.f, -300.f);
position = SPHERE_TO_TORSO + position;
palm->setControllerButtons(data->buttons);
palm->setTrigger(data->trigger);
palm->setJoystick(data->joystick_x, data->joystick_y);
glm::vec3 position(data->pos[0], data->pos[1], data->pos[2]);
// Transform the measured position into body frame.
glm::vec3 neck = _neckBase;
// Zeroing y component of the "neck" effectively raises the measured position a little bit.
neck.y = 0.f;
position = _orbRotation * (position - neck);
// Rotation of Palm
glm::quat rotation(data.rot_quat[3], -data.rot_quat[0], data.rot_quat[1], -data.rot_quat[2]);
rotation = glm::angleAxis(PI, glm::vec3(0.f, 1.f, 0.f)) * rotation;
glm::quat rotation(data->rot_quat[3], -data->rot_quat[0], data->rot_quat[1], -data->rot_quat[2]);
rotation = glm::angleAxis(PI, glm::vec3(0.f, 1.f, 0.f)) * _orbRotation * rotation;
const glm::vec3 PALM_VECTOR(0.0f, -1.0f, 0.0f);
glm::vec3 newNormal = rotation * PALM_VECTOR;
palm->setRawNormal(newNormal);
@ -126,14 +149,159 @@ void SixenseManager::update(float deltaTime) {
palm->getFingers().push_back(finger);
palm->getFingers().push_back(finger);
}
if (numActiveControllers == 2) {
updateCalibration(controllers);
}
// if the controllers haven't been moved in a while, disable
const unsigned int MOVEMENT_DISABLE_DURATION = 30 * 1000 * 1000;
if (usecTimestampNow() - _lastMovement > MOVEMENT_DISABLE_DURATION) {
for (vector<PalmData>::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) {
for (std::vector<PalmData>::iterator it = hand->getPalms().begin(); it != hand->getPalms().end(); it++) {
it->setActive(false);
}
}
#endif
#endif // HAVE_SIXENSE
}
#ifdef HAVE_SIXENSE
// the calibration sequence is:
// (1) press BUTTON_FWD on both hands
// (2) reach arm straight out to the side (X)
// (3) lift arms staight up above head (Y)
// (4) move arms a bit forward (Z)
// (5) release BUTTON_FWD on both hands
const float MINIMUM_ARM_REACH = 300.f; // millimeters
const float MAXIMUM_NOISE_LEVEL = 50.f; // millimeters
const quint64 LOCK_DURATION = USECS_PER_SECOND / 4; // time for lock to be acquired
void SixenseManager::updateCalibration(const sixenseControllerData* controllers) {
const sixenseControllerData* dataLeft = controllers;
const sixenseControllerData* dataRight = controllers + 1;
// calibration only happpens while both hands are holding BUTTON_FORWARD
if (dataLeft->buttons != BUTTON_FWD || dataRight->buttons != BUTTON_FWD) {
if (_calibrationState == CALIBRATION_STATE_IDLE) {
return;
}
switch (_calibrationState) {
case CALIBRATION_STATE_Y:
case CALIBRATION_STATE_Z:
case CALIBRATION_STATE_COMPLETE:
{
// compute calibration results
// ATM we only handle the case where the XAxis has been measured, and we assume the rest
// (i.e. that the orb is on a level surface)
// TODO: handle COMPLETE state where all three axes have been defined. This would allow us
// to also handle the case where left and right controllers have been reversed.
_neckBase = 0.5f * (_reachLeft + _reachRight); // neck is midway between right and left reaches
glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft);
glm::vec3 yAxis(0.f, 1.f, 0.f);
glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, yAxis));
xAxis = glm::normalize(glm::cross(yAxis, zAxis));
_orbRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis)));
qDebug("succeess: sixense calibration");
}
break;
default:
qDebug("failed: sixense calibration");
break;
}
_calibrationState = CALIBRATION_STATE_IDLE;
return;
}
const float* pos = dataLeft->pos;
glm::vec3 positionLeft(pos[0], pos[1], pos[2]);
pos = dataRight->pos;
glm::vec3 positionRight(pos[0], pos[1], pos[2]);
if (_calibrationState == CALIBRATION_STATE_IDLE) {
float reach = glm::distance(positionLeft, positionRight);
if (reach > 2.f * MINIMUM_ARM_REACH) {
qDebug("started: sixense calibration");
_averageLeft = positionLeft;
_averageRight = positionRight;
_reachLeft = _averageLeft;
_reachRight = _averageRight;
_lastDistance = reach;
_lockExpiry = usecTimestampNow() + LOCK_DURATION;
// move to next state
_calibrationState = CALIBRATION_STATE_X;
}
return;
}
quint64 now = usecTimestampNow() + LOCK_DURATION;
// these are weighted running averages
_averageLeft = 0.9f * _averageLeft + 0.1f * positionLeft;
_averageRight = 0.9f * _averageRight + 0.1f * positionRight;
if (_calibrationState == CALIBRATION_STATE_X) {
// compute new sliding average
float distance = glm::distance(_averageLeft, _averageRight);
if (fabs(distance - _lastDistance) > MAXIMUM_NOISE_LEVEL) {
// distance is increasing so acquire the data and push the expiry out
_reachLeft = _averageLeft;
_reachRight = _averageRight;
_lastDistance = distance;
_lockExpiry = now + LOCK_DURATION;
} else if (now > _lockExpiry) {
// lock has expired so clamp the data and move on
_lockExpiry = now + LOCK_DURATION;
_lastDistance = 0.f;
_reachUp = 0.5f * (_reachLeft + _reachRight);
_calibrationState = CALIBRATION_STATE_Y;
qDebug("success: sixense calibration: left");
}
}
else if (_calibrationState == CALIBRATION_STATE_Y) {
glm::vec3 torso = 0.5f * (_reachLeft + _reachRight);
glm::vec3 averagePosition = 0.5f * (_averageLeft + _averageRight);
float distance = (averagePosition - torso).y;
if (fabs(distance) > fabs(_lastDistance) + MAXIMUM_NOISE_LEVEL) {
// distance is increasing so acquire the data and push the expiry out
_reachUp = averagePosition;
_lastDistance = distance;
_lockExpiry = now + LOCK_DURATION;
} else if (now > _lockExpiry) {
if (_lastDistance > MINIMUM_ARM_REACH) {
// lock has expired so clamp the data and move on
_reachForward = _reachUp;
_lastDistance = 0.f;
_lockExpiry = now + LOCK_DURATION;
_calibrationState = CALIBRATION_STATE_Z;
qDebug("success: sixense calibration: up");
}
}
}
else if (_calibrationState == CALIBRATION_STATE_Z) {
glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft);
glm::vec3 torso = 0.5f * (_reachLeft + _reachRight);
//glm::vec3 yAxis = glm::normalize(_reachUp - torso);
glm::vec3 yAxis(0.f, 1.f, 0.f);
glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, yAxis));
glm::vec3 averagePosition = 0.5f * (_averageLeft + _averageRight);
float distance = glm::dot((averagePosition - torso), zAxis);
if (fabs(distance) > fabs(_lastDistance)) {
// distance is increasing so acquire the data and push the expiry out
_reachForward = averagePosition;
_lastDistance = distance;
_lockExpiry = now + LOCK_DURATION;
} else if (now > _lockExpiry) {
if (fabs(_lastDistance) > 0.05f * MINIMUM_ARM_REACH) {
// lock has expired so clamp the data and move on
_calibrationState = CALIBRATION_STATE_COMPLETE;
qDebug("success: sixense calibration: forward");
// TODO: it is theoretically possible to detect that the controllers have been
// accidentally switched (left hand is holding right controller) and to swap the order.
}
}
}
}
#endif // HAVE_SIXENSE

View file

@ -9,6 +9,21 @@
#ifndef __interface__SixenseManager__
#define __interface__SixenseManager__
#include <QObject>
#ifdef HAVE_SIXENSE
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include "sixense.h"
#endif
const unsigned int BUTTON_0 = 1U << 0; // the skinny button between 1 and 2
const unsigned int BUTTON_1 = 1U << 5;
const unsigned int BUTTON_2 = 1U << 6;
const unsigned int BUTTON_3 = 1U << 3;
const unsigned int BUTTON_4 = 1U << 4;
const unsigned int BUTTON_FWD = 1U << 7;
/// Handles interaction with the Sixense SDK (e.g., Razer Hydra).
class SixenseManager : public QObject {
Q_OBJECT
@ -24,7 +39,27 @@ public slots:
void setFilter(bool filter);
private:
#ifdef HAVE_SIXENSE
void updateCalibration(const sixenseControllerData* controllers);
int _calibrationState;
// these are calibration results
glm::vec3 _neckBase; // midpoint between controllers during X-axis calibration
glm::quat _orbRotation; // rotates from orb frame into body frame
float _armLength;
// these are measured values used to compute the calibration results
quint64 _lockExpiry;
glm::vec3 _averageLeft;
glm::vec3 _averageRight;
glm::vec3 _reachLeft;
glm::vec3 _reachRight;
glm::vec3 _reachUp;
glm::vec3 _reachForward;
float _lastDistance;
#endif
quint64 _lastMovement;
};

View file

@ -29,7 +29,7 @@ BandwidthDialog::BandwidthDialog(QWidget* parent, BandwidthMeter* model) :
this->QDialog::setLayout(form);
// Setup labels
for (int i = 0; i < BandwidthMeter::N_STREAMS; ++i) {
for (size_t i = 0; i < BandwidthMeter::N_STREAMS; ++i) {
bool input = i % 2 == 0;
BandwidthMeter::ChannelInfo& ch = _model->channelInfo(BandwidthMeter::ChannelIndex(i / 2));
QLabel* label = _labels[i] = new QLabel();
@ -48,7 +48,7 @@ BandwidthDialog::BandwidthDialog(QWidget* parent, BandwidthMeter* model) :
}
BandwidthDialog::~BandwidthDialog() {
for (int i = 0; i < BandwidthMeter::N_STREAMS; ++i) {
for (size_t i = 0; i < BandwidthMeter::N_STREAMS; ++i) {
delete _labels[i];
}
}
@ -57,7 +57,7 @@ void BandwidthDialog::paintEvent(QPaintEvent* event) {
// Update labels
char strBuf[64];
for (int i = 0; i < BandwidthMeter::N_STREAMS; ++i) {
for (size_t i = 0; i < BandwidthMeter::N_STREAMS; ++i) {
BandwidthMeter::ChannelIndex chIdx = BandwidthMeter::ChannelIndex(i / 2);
bool input = i % 2 == 0;
BandwidthMeter::ChannelInfo& ch = _model->channelInfo(chIdx);

View file

@ -28,17 +28,21 @@ const int NUM_MESSAGES_TO_TIME_STAMP = 20;
const QRegularExpression regexLinks("((?:(?:ftp)|(?:https?))://\\S+)");
ChatWindow::ChatWindow() :
QWidget(),
ui(new Ui::ChatWindow),
numMessagesAfterLastTimeStamp(0)
{
ui->setupUi(this);
QWidget* widget = new QWidget();
setWidget(widget);
ui->setupUi(widget);
FlowLayout* flowLayout = new FlowLayout(0, 4, 4);
ui->usersWidget->setLayout(flowLayout);
ui->messagePlainTextEdit->installEventFilter(this);
ui->closeButton->hide();
#ifdef HAVE_QXMPP
const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient();
if (xmppClient.isConnected()) {

View file

@ -10,8 +10,8 @@
#define __interface__ChatWindow__
#include <QDateTime>
#include <QDockWidget>
#include <QTimer>
#include <QWidget>
#include <Application.h>
@ -26,7 +26,7 @@ namespace Ui {
class ChatWindow;
}
class ChatWindow : public QWidget {
class ChatWindow : public QDockWidget {
Q_OBJECT
public:

View file

@ -41,7 +41,7 @@ void LocalVoxelsOverlay::update(float deltatime) {
}
_tree->lockForRead();
if (_visible && _voxelCount != _tree->getOctreeElementsCount()) {
if (_visible && _voxelCount != (int)_tree->getOctreeElementsCount()) {
_voxelCount = _tree->getOctreeElementsCount();
_voxelSystem->forceRedrawEntireTree();
}

View file

@ -25,10 +25,6 @@ HandData::HandData(AvatarData* owningAvatar) :
addNewPalm();
}
glm::vec3 HandData::worldPositionToLeapPosition(const glm::vec3& worldPosition) const {
return glm::inverse(getBaseOrientation()) * (worldPosition - getBasePosition()) / LEAP_UNIT_SCALE;
}
glm::vec3 HandData::worldVectorToLeapVector(const glm::vec3& worldVector) const {
return glm::inverse(getBaseOrientation()) * worldVector / LEAP_UNIT_SCALE;
}
@ -272,9 +268,7 @@ glm::quat HandData::getBaseOrientation() const {
}
glm::vec3 HandData::getBasePosition() const {
const glm::vec3 LEAP_HANDS_OFFSET_FROM_TORSO(0.0, 0.3, -0.3);
return _owningAvatarData->getPosition() + getBaseOrientation() * LEAP_HANDS_OFFSET_FROM_TORSO *
_owningAvatarData->getTargetScale();
return _owningAvatarData->getPosition();
}
void FingerData::setTrailLength(unsigned int length) {

View file

@ -28,13 +28,6 @@ const int NUM_FINGERS = NUM_HANDS * NUM_FINGERS_PER_HAND;
const int LEAPID_INVALID = -1;
const int SIXENSEID_INVALID = -1;
const int BUTTON_0 = 1; // the skinny button between 1 and 2
const int BUTTON_1 = 32;
const int BUTTON_2 = 64;
const int BUTTON_3 = 8;
const int BUTTON_4 = 16;
const int BUTTON_FWD = 128;
const float LEAP_UNIT_SCALE = 0.001f; ///< convert mm to meters
const int SIXENSE_CONTROLLER_ID_LEFT_HAND = 0;
@ -55,7 +48,6 @@ public:
glm::vec3 leapDirectionToWorldDirection(const glm::vec3& leapDirection) {
return getBaseOrientation() * leapDirection;
}
glm::vec3 worldPositionToLeapPosition(const glm::vec3& worldPosition) const;
glm::vec3 worldVectorToLeapVector(const glm::vec3& worldVector) const;
std::vector<PalmData>& getPalms() { return _palms; }
@ -182,11 +174,11 @@ public:
int getFramesWithoutData() const { return _numFramesWithoutData; }
// Controller buttons
void setControllerButtons(int controllerButtons) { _controllerButtons = controllerButtons; }
void setLastControllerButtons(int controllerButtons) { _lastControllerButtons = controllerButtons; }
void setControllerButtons(unsigned int controllerButtons) { _controllerButtons = controllerButtons; }
void setLastControllerButtons(unsigned int controllerButtons) { _lastControllerButtons = controllerButtons; }
int getControllerButtons() const { return _controllerButtons; }
int getLastControllerButtons() const { return _lastControllerButtons; }
unsigned int getControllerButtons() const { return _controllerButtons; }
unsigned int getLastControllerButtons() const { return _lastControllerButtons; }
void setTrigger(float trigger) { _trigger = trigger; }
float getTrigger() const { return _trigger; }
@ -217,8 +209,8 @@ private:
glm::vec3 _tipPosition;
glm::vec3 _tipVelocity;
int _controllerButtons;
int _lastControllerButtons;
unsigned int _controllerButtons;
unsigned int _lastControllerButtons;
float _trigger;
float _joystickX, _joystickY;

View file

@ -925,7 +925,7 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet,
qDebug() << "(_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE):"
<< (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE);
}
if (missingItem <= std::max(0, (_incomingLastSequence - MAX_MISSING_SEQUENCE_OLD_AGE))) {
if (missingItem <= (unsigned int)std::max(0, (int)_incomingLastSequence - (int)MAX_MISSING_SEQUENCE_OLD_AGE)) {
if (wantExtraDebugging) {
qDebug() << "pruning really old missing sequence:" << missingItem;
}

View file

@ -22,14 +22,22 @@ glm::quat Quat::multiply(const glm::quat& q1, const glm::quat& q2) {
return q1 * q2;
}
glm::quat Quat::fromVec3(const glm::vec3& eulerAngles) {
glm::quat Quat::fromVec3Degrees(const glm::vec3& eulerAngles) {
return glm::quat(glm::radians(eulerAngles));
}
glm::quat Quat::fromPitchYawRoll(float pitch, float yaw, float roll) {
glm::quat Quat::fromVec3Radians(const glm::vec3& eulerAngles) {
return glm::quat(eulerAngles);
}
glm::quat Quat::fromPitchYawRollDegrees(float pitch, float yaw, float roll) {
return glm::quat(glm::radians(glm::vec3(pitch, yaw, roll)));
}
glm::quat Quat::fromPitchYawRollRadians(float pitch, float yaw, float roll) {
return glm::quat(glm::vec3(pitch, yaw, roll));
}
glm::quat Quat::inverse(const glm::quat& q) {
return glm::inverse(q);
}

View file

@ -23,8 +23,10 @@ class Quat : public QObject {
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); // degrees
glm::quat fromVec3Degrees(const glm::vec3& vec3); // degrees
glm::quat fromVec3Radians(const glm::vec3& vec3); // radians
glm::quat fromPitchYawRollDegrees(float pitch, float yaw, float roll); // degrees
glm::quat fromPitchYawRollRadians(float pitch, float yaw, float roll); // radians
glm::quat inverse(const glm::quat& q);
glm::vec3 getFront(const glm::quat& orientation);
glm::vec3 getRight(const glm::quat& orientation);

View file

@ -57,10 +57,9 @@ static const float DEGREES_PER_RADIAN = 180.0f / PI;
static const float EPSILON = 0.000001f; //smallish positive number - used as margin of error for some computations
static const float SQUARE_ROOT_OF_2 = (float)sqrt(2.f);
static const float SQUARE_ROOT_OF_3 = (float)sqrt(3.f);
static const float METER = 1.0f;
static const float DECIMETER = 0.1f;
static const float CENTIMETER = 0.01f;
static const float MILLIIMETER = 0.001f;
static const float METERS_PER_DECIMETER = 0.1f;
static const float METERS_PER_CENTIMETER = 0.01f;
static const float METERS_PER_MILLIMETER = 0.001f;
static const quint64 USECS_PER_MSEC = 1000;
static const quint64 MSECS_PER_SECOND = 1000;
static const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND;

View file

@ -174,7 +174,7 @@ void ShapeColliderTests::sphereMissesCapsule() {
CapsuleShape capsuleB(radiusB, halfHeightB);
// give the capsule some arbirary transform
float angle = 37.8;
float angle = 37.8f;
glm::vec3 axis = glm::normalize( glm::vec3(-7.f, 2.8f, 9.3f) );
glm::quat rotation = glm::angleAxis(angle, axis);
glm::vec3 translation(15.1f, -27.1f, -38.6f);