From 8f25e54027bfaf9e858b4d131a546b839809189a Mon Sep 17 00:00:00 2001 From: James Pollack Date: Fri, 25 Sep 2015 18:34:34 -0700 Subject: [PATCH 01/36] Hoop, ball, ground --- examples/toys/basketball/createHoop.js | 101 +++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 examples/toys/basketball/createHoop.js diff --git a/examples/toys/basketball/createHoop.js b/examples/toys/basketball/createHoop.js new file mode 100644 index 0000000000..778c73915c --- /dev/null +++ b/examples/toys/basketball/createHoop.js @@ -0,0 +1,101 @@ +// +// createFlashlight.js +// examples/entityScripts +// +// Created by Sam Gateau on 9/9/15. +// Copyright 2015 High Fidelity, Inc. +// +// This is a toy script that create a flashlight entity that lit when grabbed +// This can be run from an interface and the flashlight will get deleted from the domain when quitting +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +/*global MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */ +Script.include("../../utilities.js"); +Script.include("../../libraries/utils.js"); + +var groundURL = "https://hifi-public.s3.amazonaws.com/eric/models/woodFloor.fbx"; +var basketballURL = "https://hifi-public.s3.amazonaws.com/models/content/basketball2.fbx"; +var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball/new_hoop_2.fbx"; +var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball/new_basketball_hoop_collision_hull.obj"; +var ballCollisionSound = "https://hifi-public.s3.amazonaws.com/sounds/basketball/basketball.wav"; + +var basePosition = { + x: 0, + y: 0, + z: 0 +}; + +var hoopStartPosition = { + x: 0, + y: 3.25, + z: 0 +}; + + +var ground = Entities.addEntity({ + type: "Model", + modelURL: groundURL, + dimensions: { + x: 100, + y: 2, + z: 100 + }, + position: basePosition, + shapeType: 'box' +}); + +var BALL_DIAMETER = 0.30; +var DISTANCE_IN_FRONT_OF_ME = 1.0; + +var ballPosition = Vec3.sum(MyAvatar.position, + Vec3.multiplyQbyV(MyAvatar.orientation, { + x: 0, + y: 0.0, + z: -DISTANCE_IN_FRONT_OF_ME + })); + +var ballRotation = Quat.multiply(MyAvatar.orientation, + Quat.fromPitchYawRollDegrees(0, -90, 0)); + +var basketball = Entities.addEntity({ + type: "Model", + position: ballPosition, + rotation: ballRotation, + dimensions: { + x: BALL_DIAMETER, + y: BALL_DIAMETER, + z: BALL_DIAMETER + }, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + collisionsWillMove: true, + collisionSoundURL: ballCollisionSound, + modelURL: basketballURL, + restitution: 1.0, + linearDamping: 0.00001, + shapeType: "sphere" +}); + + +var hoop = Entities.addEntity({ + type: "Model", + modelURL: hoopURL, + position: hoopStartPosition, + shapeType: 'compound', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 1.89, + y: 3.99, + z: 3.79 + }, + compoundShapeURL: hoopCollisionHullURL +}); \ No newline at end of file From ade78fda9ec9e739a2d00e2ee56ecc5add5dbb59 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Mon, 28 Sep 2015 12:24:21 -0700 Subject: [PATCH 02/36] balls --- examples/toys/basketball/createHoop.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/examples/toys/basketball/createHoop.js b/examples/toys/basketball/createHoop.js index 778c73915c..9a80ccaace 100644 --- a/examples/toys/basketball/createHoop.js +++ b/examples/toys/basketball/createHoop.js @@ -17,7 +17,7 @@ Script.include("../../libraries/utils.js"); var groundURL = "https://hifi-public.s3.amazonaws.com/eric/models/woodFloor.fbx"; var basketballURL = "https://hifi-public.s3.amazonaws.com/models/content/basketball2.fbx"; -var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball/new_hoop_2.fbx"; +var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball/new_hoop_3.fbx"; var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball/new_basketball_hoop_collision_hull.obj"; var ballCollisionSound = "https://hifi-public.s3.amazonaws.com/sounds/basketball/basketball.wav"; @@ -98,4 +98,13 @@ var hoop = Entities.addEntity({ z: 3.79 }, compoundShapeURL: hoopCollisionHullURL -}); \ No newline at end of file +}); + + + +function cleanup() { + Entities.deleteEntity(basketball); + Entities.deleteEntity(hoop); + Entities.deleteEntity(ground); +} +Script.scriptEnding.connect(cleanup); \ No newline at end of file From afa179b9c44d06b56782e18f8dd9d9f587e0aa12 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Mon, 28 Sep 2015 15:08:48 -0700 Subject: [PATCH 03/36] hoop --- examples/toys/basketball/createHoop.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/toys/basketball/createHoop.js b/examples/toys/basketball/createHoop.js index 9a80ccaace..a4044d4adf 100644 --- a/examples/toys/basketball/createHoop.js +++ b/examples/toys/basketball/createHoop.js @@ -17,7 +17,7 @@ Script.include("../../libraries/utils.js"); var groundURL = "https://hifi-public.s3.amazonaws.com/eric/models/woodFloor.fbx"; var basketballURL = "https://hifi-public.s3.amazonaws.com/models/content/basketball2.fbx"; -var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball/new_hoop_3.fbx"; +var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball/basketball_hoop_10.fbx"; var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball/new_basketball_hoop_collision_hull.obj"; var ballCollisionSound = "https://hifi-public.s3.amazonaws.com/sounds/basketball/basketball.wav"; From 8f02ffb76a839adf410bdf4742e2620ac14d96d5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 28 Sep 2015 15:32:53 -0700 Subject: [PATCH 04/36] git rid of if branch with same code in either branch --- libraries/fbx/src/FBXReader_Material.cpp | 15 +++++---------- libraries/fbx/src/OBJReader.cpp | 8 +++----- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index c29c64030e..959a13306a 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -134,19 +134,14 @@ void FBXReader::consolidateFBXMaterials() { // Finally create the true material representation material._material = std::make_shared(); material._material->setEmissive(material.emissiveColor); - if (glm::all(glm::equal(material.diffuseColor, glm::vec3(0.0f)))) { - material._material->setDiffuse(material.diffuseColor); - } else { - material._material->setDiffuse(material.diffuseColor); - } - material._material->setMetallic(glm::length(material.specularColor)); - material._material->setGloss(material.shininess); + material._material->setDiffuse(material.diffuseColor); + material._material->setMetallic(glm::length(material.specularColor)); + material._material->setGloss(material.shininess); if (material.opacity <= 0.0f) { - material._material->setOpacity(1.0f); + material._material->setOpacity(1.0f); } else { - material._material->setOpacity(material.opacity); + material._material->setOpacity(material.opacity); } } } - diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index ad30a38550..7147888d6b 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -537,8 +537,10 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, qCDebug(modelformat) << "OBJ reader fail: " << e.what(); } + qDebug() << "---------------------- -------------------------"; foreach (QString materialID, materials.keys()) { OBJMaterial& objMaterial = materials[materialID]; + qDebug() << "materialID =" << materialID << "diffuseColor =" << objMaterial.diffuseColor; geometry.materials[materialID] = FBXMaterial(objMaterial.diffuseColor, // glm::vec3(1.0f, 1.0f, 1.0f) objMaterial.specularColor, // glm::vec3(1.0f) glm::vec3(), // glm::vec3() @@ -555,11 +557,7 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, } material._material->setEmissive(material.emissiveColor); - if (glm::all(glm::equal(material.diffuseColor, glm::vec3(0.0f)))) { - material._material->setDiffuse(material.diffuseColor); - } else { - material._material->setDiffuse(material.diffuseColor); - } + material._material->setDiffuse(material.diffuseColor); material._material->setMetallic(glm::length(material.specularColor)); material._material->setGloss(material.shininess); From a8b135b5ca03e53900c2bd34fb332cb0362d5cef Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 28 Sep 2015 17:02:00 -0700 Subject: [PATCH 05/36] fix material colors for OBJ models --- libraries/fbx/src/OBJReader.cpp | 35 ++++++++++++++++----------------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 7147888d6b..a9275e2d4a 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -537,18 +537,18 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, qCDebug(modelformat) << "OBJ reader fail: " << e.what(); } - qDebug() << "---------------------- -------------------------"; foreach (QString materialID, materials.keys()) { OBJMaterial& objMaterial = materials[materialID]; - qDebug() << "materialID =" << materialID << "diffuseColor =" << objMaterial.diffuseColor; - geometry.materials[materialID] = FBXMaterial(objMaterial.diffuseColor, // glm::vec3(1.0f, 1.0f, 1.0f) - objMaterial.specularColor, // glm::vec3(1.0f) - glm::vec3(), // glm::vec3() - glm::vec2(0.f, 1.0f), // glm::vec2(0.f, 1.0f) - objMaterial.shininess, // 96.0f - objMaterial.opacity); // 1.0f - FBXMaterial& material = geometry.materials[materialID]; - material._material = std::make_shared(); + geometry.materials[materialID] = FBXMaterial(objMaterial.diffuseColor, + objMaterial.specularColor, + glm::vec3(0.0f), + glm::vec2(0.0f, 1.0f), + objMaterial.shininess, + objMaterial.opacity); + FBXMaterial& fbxMaterial = geometry.materials[materialID]; + fbxMaterial.materialID = materialID; + fbxMaterial._material = std::make_shared(); + model::MaterialPointer modelMaterial = fbxMaterial._material; if (!objMaterial.diffuseTextureFilename.isEmpty()) { FBXTexture texture; @@ -556,17 +556,16 @@ FBXGeometry* OBJReader::readOBJ(QByteArray& model, const QVariantHash& mapping, // TODO -- something to get textures working again } - material._material->setEmissive(material.emissiveColor); - material._material->setDiffuse(material.diffuseColor); - material._material->setMetallic(glm::length(material.specularColor)); - material._material->setGloss(material.shininess); + modelMaterial->setEmissive(fbxMaterial.emissiveColor); + modelMaterial->setDiffuse(fbxMaterial.diffuseColor); + modelMaterial->setMetallic(glm::length(fbxMaterial.specularColor)); + modelMaterial->setGloss(fbxMaterial.shininess); - if (material.opacity <= 0.0f) { - material._material->setOpacity(1.0f); + if (fbxMaterial.opacity <= 0.0f) { + modelMaterial->setOpacity(1.0f); } else { - material._material->setOpacity(material.opacity); + modelMaterial->setOpacity(fbxMaterial.opacity); } - } return geometryPtr; From 4c86b1ce03abf3dd92e4c887455f872a3f39ede4 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 28 Sep 2015 18:47:32 -0700 Subject: [PATCH 06/36] ballin --- examples/toys/basketball/createHoop.js | 59 ++++++++++++++------------ 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/examples/toys/basketball/createHoop.js b/examples/toys/basketball/createHoop.js index 778c73915c..bd3fc32411 100644 --- a/examples/toys/basketball/createHoop.js +++ b/examples/toys/basketball/createHoop.js @@ -15,40 +15,40 @@ Script.include("../../utilities.js"); Script.include("../../libraries/utils.js"); -var groundURL = "https://hifi-public.s3.amazonaws.com/eric/models/woodFloor.fbx"; +var courtURL = "https://hifi-public.s3.amazonaws.com/eric/models/woodFloor.fbx"; var basketballURL = "https://hifi-public.s3.amazonaws.com/models/content/basketball2.fbx"; -var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball/new_hoop_2.fbx"; -var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball/new_basketball_hoop_collision_hull.obj"; var ballCollisionSound = "https://hifi-public.s3.amazonaws.com/sounds/basketball/basketball.wav"; - -var basePosition = { - x: 0, - y: 0, - z: 0 -}; - -var hoopStartPosition = { - x: 0, - y: 3.25, - z: 0 -}; - - -var ground = Entities.addEntity({ - type: "Model", - modelURL: groundURL, - dimensions: { - x: 100, - y: 2, - z: 100 - }, - position: basePosition, - shapeType: 'box' -}); +var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; +var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; var BALL_DIAMETER = 0.30; var DISTANCE_IN_FRONT_OF_ME = 1.0; +var hoopStartPosition = + Vec3.sum(MyAvatar.position, + Vec3.multiplyQbyV(MyAvatar.orientation, { + x: 0, + y: 0.0, + z: -DISTANCE_IN_FRONT_OF_ME * 2 + })); + +// courtStartPosition.y = hoopStartPosition.y - 2 + + +// var court = Entities.addEntity({ +// type: "Model", +// modelURL: courtURL, +// dimensions: { +// x: 28.65, +// y: 0.02, +// z: 15.24 +// }, +// position: courtStartPosition, +// shapeType: 'box' +// }); + + + var ballPosition = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, @@ -56,6 +56,8 @@ var ballPosition = Vec3.sum(MyAvatar.position, z: -DISTANCE_IN_FRONT_OF_ME })); + + var ballRotation = Quat.multiply(MyAvatar.orientation, Quat.fromPitchYawRollDegrees(0, -90, 0)); @@ -92,6 +94,7 @@ var hoop = Entities.addEntity({ y: -9.8, z: 0 }, + // rotation: Quat.fromPitchYawRollDegrees(0, -90, 0)), dimensions: { x: 1.89, y: 3.99, From e615c62bd3893874600abf9d26906abfcd3eadd7 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Tue, 29 Sep 2015 13:11:39 -0700 Subject: [PATCH 07/36] Prevent mouse grab from grabbing ungrabbable objects --- examples/grab.js | 156 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 125 insertions(+), 31 deletions(-) diff --git a/examples/grab.js b/examples/grab.js index 05bcf128e2..70d0a56df5 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -9,11 +9,29 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +/*global print, MouseMyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt, pointInExtents, vec3equal, setEntityCustomData, getEntityCustomData */ -var MAX_SOLID_ANGLE = 0.01; // objects that appear smaller than this can't be grabbed -var ZERO_VEC3 = {x: 0, y: 0, z: 0}; -var IDENTITY_QUAT = {x: 0, y: 0, z: 0, w: 0}; +Script.include("libraries/utils.js"); +// objects that appear smaller than this can't be grabbed +var MAX_SOLID_ANGLE = 0.01; +var ZERO_VEC3 = { + x: 0, + y: 0, + z: 0 +}; +var IDENTITY_QUAT = { + x: 0, + y: 0, + z: 0, + w: 0 +}; +var GRABBABLE_DATA_KEY = "grabbableKey"; + + +var defaultGrabbableData = { + grabbable: true +}; // helper function function mouseIntersectionWithPlane(pointOnPlane, planeNormal, event, maxDistance) { @@ -59,36 +77,72 @@ function mouseIntersectionWithPlane(pointOnPlane, planeNormal, event, maxDistanc // Mouse class stores mouse click and drag info Mouse = function() { - this.current = {x: 0, y: 0 }; - this.previous = {x: 0, y: 0 }; - this.rotateStart = {x: 0, y: 0 }; - this.cursorRestore = {x: 0, y: 0}; + this.current = { + x: 0, + y: 0 + }; + this.previous = { + x: 0, + y: 0 + }; + this.rotateStart = { + x: 0, + y: 0 + }; + this.cursorRestore = { + x: 0, + y: 0 + }; } Mouse.prototype.startDrag = function(position) { - this.current = {x: position.x, y: position.y}; + this.current = { + x: position.x, + y: position.y + }; this.startRotateDrag(); } Mouse.prototype.updateDrag = function(position) { - this.current = {x: position.x, y: position.y }; + this.current = { + x: position.x, + y: position.y + }; } Mouse.prototype.startRotateDrag = function() { - this.previous = {x: this.current.x, y: this.current.y}; - this.rotateStart = {x: this.current.x, y: this.current.y}; - this.cursorRestore = { x: Window.getCursorPositionX(), y: Window.getCursorPositionY() }; + this.previous = { + x: this.current.x, + y: this.current.y + }; + this.rotateStart = { + x: this.current.x, + y: this.current.y + }; + this.cursorRestore = { + x: Window.getCursorPositionX(), + y: Window.getCursorPositionY() + }; } Mouse.prototype.getDrag = function() { - var delta = {x: this.current.x - this.previous.x, y: this.current.y - this.previous.y}; - this.previous = {x: this.current.x, y: this.current.y}; + var delta = { + x: this.current.x - this.previous.x, + y: this.current.y - this.previous.y + }; + this.previous = { + x: this.current.x, + y: this.current.y + }; return delta; } Mouse.prototype.restoreRotateCursor = function() { Window.setCursorPosition(this.cursorRestore.x, this.cursorRestore.y); - this.current = {x: this.rotateStart.x, y: this.rotateStart.y}; + this.current = { + x: this.rotateStart.x, + y: this.rotateStart.y + }; } var mouse = new Mouse(); @@ -98,19 +152,27 @@ var mouse = new Mouse(); Beacon = function() { this.height = 0.10; this.overlayID = Overlays.addOverlay("line3d", { - color: {red: 200, green: 200, blue: 200}, + color: { + red: 200, + green: 200, + blue: 200 + }, alpha: 1, visible: false, - lineWidth: 2 + lineWidth: 2 }); } Beacon.prototype.enable = function() { - Overlays.editOverlay(this.overlayID, { visible: true }); + Overlays.editOverlay(this.overlayID, { + visible: true + }); } Beacon.prototype.disable = function() { - Overlays.editOverlay(this.overlayID, { visible: false }); + Overlays.editOverlay(this.overlayID, { + visible: false + }); } Beacon.prototype.updatePosition = function(position) { @@ -158,13 +220,17 @@ Grabber = function() { // verticalCylinder (SHIFT) // rotate (CONTROL) this.mode = "xzplane"; - + // offset allows the user to grab an object off-center. It points from the object's center // to the point where the ray intersects the grab plane (at the moment the grab is initiated). // Future target positions of the ray intersection are on the same plane, and the offset is subtracted // to compute the target position of the object's center. - this.offset = {x: 0, y: 0, z: 0 }; - + this.offset = { + x: 0, + y: 0, + z: 0 + }; + this.targetPosition; this.targetRotation; @@ -179,7 +245,11 @@ Grabber.prototype.computeNewGrabPlane = function() { var modeWasRotate = (this.mode == "rotate"); this.mode = "xzPlane"; - this.planeNormal = {x: 0, y: 1, z: 0 }; + this.planeNormal = { + x: 0, + y: 1, + z: 0 + }; if (this.rotateKey) { this.mode = "rotate"; mouse.startRotateDrag(); @@ -192,7 +262,7 @@ Grabber.prototype.computeNewGrabPlane = function() { this.mode = "verticalCylinder"; // NOTE: during verticalCylinder mode a new planeNormal will be computed each move } - } + } this.pointOnPlane = Vec3.sum(this.currentPosition, this.offset); var xzOffset = Vec3.subtract(this.pointOnPlane, Camera.getPosition()); @@ -217,6 +287,12 @@ Grabber.prototype.pressEvent = function(event) { return; } + + var grabbableData = getEntityCustomData(GRABBABLE_DATA_KEY, pickResults.entityID, defaultGrabbableData); + if (grabbableData.grabbable === false) { + return; + } + mouse.startDrag(event); var clickedEntity = pickResults.entityID; @@ -233,13 +309,19 @@ Grabber.prototype.pressEvent = function(event) { return; } - Entities.editEntity(clickedEntity, { gravity: ZERO_VEC3 }); + Entities.editEntity(clickedEntity, { + gravity: ZERO_VEC3 + }); this.isGrabbing = true; this.entityID = clickedEntity; this.currentPosition = entityProperties.position; this.originalGravity = entityProperties.gravity; - this.targetPosition = {x: this.startPosition.x, y: this.startPosition.y, z: this.startPosition.z}; + this.targetPosition = { + x: this.startPosition.x, + y: this.startPosition.y, + z: this.startPosition.z + }; // compute the grab point var nearestPoint = Vec3.subtract(this.startPosition, cameraPosition); @@ -261,7 +343,9 @@ Grabber.prototype.pressEvent = function(event) { Grabber.prototype.releaseEvent = function() { if (this.isGrabbing) { if (Vec3.length(this.originalGravity) != 0) { - Entities.editEntity(this.entityID, { gravity: this.originalGravity}); + Entities.editEntity(this.entityID, { + gravity: this.originalGravity + }); } this.isGrabbing = false @@ -303,7 +387,10 @@ Grabber.prototype.moveEvent = function(event) { // var qZero = entityProperties.rotation; //var qZero = this.lastRotation; this.lastRotation = Quat.multiply(deltaQ, this.lastRotation); - actionArgs = {targetRotation: this.lastRotation, angularTimeScale: 0.1}; + actionArgs = { + targetRotation: this.lastRotation, + angularTimeScale: 0.1 + }; } else { var newPointOnPlane; if (this.mode === "verticalCylinder") { @@ -314,7 +401,11 @@ Grabber.prototype.moveEvent = function(event) { var pointOnCylinder = Vec3.multiply(planeNormal, this.xzDistanceToGrab); pointOnCylinder = Vec3.sum(Camera.getPosition(), pointOnCylinder); this.pointOnPlane = mouseIntersectionWithPlane(pointOnCylinder, planeNormal, mouse.current, this.maxDistance); - newPointOnPlane = {x: this.pointOnPlane.x, y: this.pointOnPlane.y, z: this.pointOnPlane.z}; + newPointOnPlane = { + x: this.pointOnPlane.x, + y: this.pointOnPlane.y, + z: this.pointOnPlane.z + }; } else { var cameraPosition = Camera.getPosition(); newPointOnPlane = mouseIntersectionWithPlane(this.pointOnPlane, this.planeNormal, mouse.current, this.maxDistance); @@ -327,7 +418,10 @@ Grabber.prototype.moveEvent = function(event) { } } this.targetPosition = Vec3.subtract(newPointOnPlane, this.offset); - actionArgs = {targetPosition: this.targetPosition, linearTimeScale: 0.1}; + actionArgs = { + targetPosition: this.targetPosition, + linearTimeScale: 0.1 + }; beacon.updatePosition(this.targetPosition); } @@ -385,4 +479,4 @@ Controller.mousePressEvent.connect(pressEvent); Controller.mouseMoveEvent.connect(moveEvent); Controller.mouseReleaseEvent.connect(releaseEvent); Controller.keyPressEvent.connect(keyPressEvent); -Controller.keyReleaseEvent.connect(keyReleaseEvent); +Controller.keyReleaseEvent.connect(keyReleaseEvent); \ No newline at end of file From 26554c5ac33aafe0dee1e20bce508039af26f8f9 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Tue, 29 Sep 2015 13:13:50 -0700 Subject: [PATCH 08/36] whitespace --- examples/grab.js | 1 - 1 file changed, 1 deletion(-) diff --git a/examples/grab.js b/examples/grab.js index 70d0a56df5..fd67287645 100644 --- a/examples/grab.js +++ b/examples/grab.js @@ -28,7 +28,6 @@ var IDENTITY_QUAT = { }; var GRABBABLE_DATA_KEY = "grabbableKey"; - var defaultGrabbableData = { grabbable: true }; From cbd55ddba62cfa4558df3459a9cb9834a55aea18 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Tue, 29 Sep 2015 13:24:49 -0700 Subject: [PATCH 09/36] Add the hoop --- examples/toys/basketball/createHoop.js | 113 -------------------- examples/toys/basketball_hoop/createHoop.js | 49 +++++++++ 2 files changed, 49 insertions(+), 113 deletions(-) delete mode 100644 examples/toys/basketball/createHoop.js create mode 100644 examples/toys/basketball_hoop/createHoop.js diff --git a/examples/toys/basketball/createHoop.js b/examples/toys/basketball/createHoop.js deleted file mode 100644 index 7af54767f3..0000000000 --- a/examples/toys/basketball/createHoop.js +++ /dev/null @@ -1,113 +0,0 @@ -// -// createFlashlight.js -// examples/entityScripts -// -// Created by Sam Gateau on 9/9/15. -// Copyright 2015 High Fidelity, Inc. -// -// This is a toy script that create a flashlight entity that lit when grabbed -// This can be run from an interface and the flashlight will get deleted from the domain when quitting -//a -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -/*global MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */ -Script.include("../../utilities.js"); -Script.include("../../libraries/utils.js"); - -var courtURL = "https://hifi-public.s3.amazonaws.com/eric/models/woodFloor.fbx"; -var basketballURL = "https://hifi-public.s3.amazonaws.com/models/content/basketball2.fbx"; -var ballCollisionSound = "https://hifi-public.s3.amazonaws.com/sounds/basketball/basketball.wav"; -var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; -var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; - -var BALL_DIAMETER = 0.30; -var DISTANCE_IN_FRONT_OF_ME = 1.0; - -var hoopStartPosition = - Vec3.sum(MyAvatar.position, - Vec3.multiplyQbyV(MyAvatar.orientation, { - x: 0, - y: 0.0, - z: -DISTANCE_IN_FRONT_OF_ME * 2 - })); - -// courtStartPosition.y = hoopStartPosition.y - 2 - - -// var court = Entities.addEntity({ -// type: "Model", -// modelURL: courtURL, -// dimensions: { -// x: 28.65, -// y: 0.02, -// z: 15.24 -// }, -// position: courtStartPosition, -// shapeType: 'box' -// }); - - - -var ballPosition = Vec3.sum(MyAvatar.position, - Vec3.multiplyQbyV(MyAvatar.orientation, { - x: 0, - y: 0.0, - z: -DISTANCE_IN_FRONT_OF_ME - })); - - - -var ballRotation = Quat.multiply(MyAvatar.orientation, - Quat.fromPitchYawRollDegrees(0, -90, 0)); - -var basketball = Entities.addEntity({ - type: "Model", - position: ballPosition, - rotation: ballRotation, - dimensions: { - x: BALL_DIAMETER, - y: BALL_DIAMETER, - z: BALL_DIAMETER - }, - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - collisionsWillMove: true, - collisionSoundURL: ballCollisionSound, - modelURL: basketballURL, - restitution: 1.0, - linearDamping: 0.00001, - shapeType: "sphere" -}); - - -var hoop = Entities.addEntity({ - type: "Model", - modelURL: hoopURL, - position: hoopStartPosition, - shapeType: 'compound', - gravity: { - x: 0, - y: -9.8, - z: 0 - }, - // rotation: Quat.fromPitchYawRollDegrees(0, -90, 0)), - dimensions: { - x: 1.89, - y: 3.99, - z: 3.79 - }, - compoundShapeURL: hoopCollisionHullURL -}); - - - -function cleanup() { - Entities.deleteEntity(basketball); - Entities.deleteEntity(hoop); - // Entities.deleteEntity(court); -} -Script.scriptEnding.connect(cleanup); \ No newline at end of file diff --git a/examples/toys/basketball_hoop/createHoop.js b/examples/toys/basketball_hoop/createHoop.js new file mode 100644 index 0000000000..26fb7347d1 --- /dev/null +++ b/examples/toys/basketball_hoop/createHoop.js @@ -0,0 +1,49 @@ +// +// createHoop.js +// examples/entityScripts +// +// Created by James B. Pollack on 9/29/2015 +// Copyright 2015 High Fidelity, Inc. +// +// This is a script that creates a persistent basketball hoop with a working collision hull. Feel free to move it. +// Run basketball.js to make a basketball. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +/*global MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */ +Script.include("../../utilities.js"); +Script.include("../../libraries/utils.js"); + +var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; +var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; + + +var DISTANCE_IN_FRONT_OF_ME = 1.0; + +var hoopStartPosition = + Vec3.sum(MyAvatar.position, + Vec3.multiplyQbyV(MyAvatar.orientation, { + x: 0, + y: 0.0, + z: -DISTANCE_IN_FRONT_OF_ME * 2 + })); + + +var hoop = Entities.addEntity({ + type: "Model", + modelURL: hoopURL, + position: hoopStartPosition, + shapeType: 'compound', + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + dimensions: { + x: 1.89, + y: 3.99, + z: 3.79 + }, + compoundShapeURL: hoopCollisionHullURL +}); \ No newline at end of file From f4bc3f8e388a6b38456f880dd7a3904150dae072 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Tue, 29 Sep 2015 16:35:24 -0400 Subject: [PATCH 10/36] fix a timer leak, line width in PacketList --- libraries/networking/src/ThreadedAssignment.cpp | 5 +++-- libraries/networking/src/udt/PacketList.h | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/networking/src/ThreadedAssignment.cpp b/libraries/networking/src/ThreadedAssignment.cpp index 5f0db9412c..0422c03297 100644 --- a/libraries/networking/src/ThreadedAssignment.cpp +++ b/libraries/networking/src/ThreadedAssignment.cpp @@ -49,7 +49,8 @@ void ThreadedAssignment::setFinished(bool isFinished) { } if (_statsTimer) { - _statsTimer->stop(); + _statsTimer->deleteLater(); + _statsTimer = nullptr; } // call our virtual aboutToFinish method - this gives the ThreadedAssignment subclass a chance to cleanup @@ -105,7 +106,7 @@ void ThreadedAssignment::sendStatsPacket() { void ThreadedAssignment::startSendingStats() { // send the stats packet every 1s if (!_statsTimer) { - _statsTimer = new QTimer(); + _statsTimer = new QTimer; connect(_statsTimer, &QTimer::timeout, this, &ThreadedAssignment::sendStatsPacket); } diff --git a/libraries/networking/src/udt/PacketList.h b/libraries/networking/src/udt/PacketList.h index ae783dabe3..7978e77ad7 100644 --- a/libraries/networking/src/udt/PacketList.h +++ b/libraries/networking/src/udt/PacketList.h @@ -28,7 +28,8 @@ class Packet; class PacketList : public QIODevice { Q_OBJECT public: - static std::unique_ptr create(PacketType packetType, QByteArray extendedHeader = QByteArray(), bool isReliable = false, bool isOrdered = false); + static std::unique_ptr create(PacketType packetType, QByteArray extendedHeader = QByteArray(), + bool isReliable = false, bool isOrdered = false); static std::unique_ptr fromReceivedPackets(std::list>&& packets); bool isReliable() const { return _isReliable; } From b9a83be4d33f8ddc1d1e4dacde414467acce0c2f Mon Sep 17 00:00:00 2001 From: James Pollack Date: Tue, 29 Sep 2015 14:31:13 -0700 Subject: [PATCH 11/36] cleanup --- examples/toys/basketball_hoop/createHoop.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/examples/toys/basketball_hoop/createHoop.js b/examples/toys/basketball_hoop/createHoop.js index 26fb7347d1..3887e0b421 100644 --- a/examples/toys/basketball_hoop/createHoop.js +++ b/examples/toys/basketball_hoop/createHoop.js @@ -10,26 +10,19 @@ // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// /*global MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */ -Script.include("../../utilities.js"); -Script.include("../../libraries/utils.js"); var hoopURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop.fbx"; var hoopCollisionHullURL = "http://hifi-public.s3.amazonaws.com/models/basketball_hoop/basketball_hoop_collision_hull.obj"; - -var DISTANCE_IN_FRONT_OF_ME = 1.0; - var hoopStartPosition = Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.0, - z: -DISTANCE_IN_FRONT_OF_ME * 2 + z: -2 })); - var hoop = Entities.addEntity({ type: "Model", modelURL: hoopURL, @@ -46,4 +39,5 @@ var hoop = Entities.addEntity({ z: 3.79 }, compoundShapeURL: hoopCollisionHullURL -}); \ No newline at end of file +}); + From cdae16e07bd2e8649d310b7c5e0e2a49e5075d20 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 29 Sep 2015 16:11:27 -0700 Subject: [PATCH 12/36] fix bug: IK attenuates fast underpose animations --- .../animation/src/AnimInverseKinematics.cpp | 61 ++++++++++++------- .../animation/src/AnimInverseKinematics.h | 2 +- 2 files changed, 39 insertions(+), 24 deletions(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index de226092f1..ff5d2a6a3f 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -89,7 +89,7 @@ static int findRootJointInSkeleton(AnimSkeleton::ConstPointer skeleton, int inde return rootIndex; } -void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::vector& targets) { +void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::vector& targets, const AnimPoseVec& underPoses) { // build a list of valid targets from _targetVarVec and animVars _maxTargetIndex = -1; bool removeUnfoundJoints = false; @@ -107,7 +107,7 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std:: } } else { IKTarget target; - AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, _relativePoses); + AnimPose defaultPose = _skeleton->getAbsolutePose(targetVar.jointIndex, underPoses); target.pose.trans = animVars.lookup(targetVar.positionVar, defaultPose.trans); target.pose.rot = animVars.lookup(targetVar.rotationVar, defaultPose.rot); target.setType(animVars.lookup(targetVar.typeVar, QString(""))); @@ -154,7 +154,6 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector& targets); + void computeTargets(const AnimVariantMap& animVars, std::vector& targets, const AnimPoseVec& underPoses); void solveWithCyclicCoordinateDescent(const std::vector& targets); virtual void setSkeletonInternal(AnimSkeleton::ConstPointer skeleton); From a052f5e125f7d75fb4d36929c05b2ba2cc6e28df Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 29 Sep 2015 16:21:08 -0700 Subject: [PATCH 13/36] remove commented out debug line --- libraries/animation/src/AnimInverseKinematics.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/animation/src/AnimInverseKinematics.cpp b/libraries/animation/src/AnimInverseKinematics.cpp index ff5d2a6a3f..c0adba0ad6 100644 --- a/libraries/animation/src/AnimInverseKinematics.cpp +++ b/libraries/animation/src/AnimInverseKinematics.cpp @@ -371,7 +371,6 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars } } return _relativePoses; - //return underPoses; } RotationConstraint* AnimInverseKinematics::getConstraint(int index) { From b192d0a9cdfdada443fc3957804287cfff0d08ab Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 29 Sep 2015 17:39:17 -0700 Subject: [PATCH 14/36] make neck IK target type same as head --- .../meshes/defaultAvatar_full/avatar-animation.json | 5 +++-- libraries/animation/src/Rig.cpp | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json index 72eefaf7e8..dceecddfe0 100644 --- a/interface/resources/meshes/defaultAvatar_full/avatar-animation.json +++ b/interface/resources/meshes/defaultAvatar_full/avatar-animation.json @@ -26,13 +26,14 @@ { "jointName": "Neck", "positionVar": "neckPosition", - "rotationVar": "neckRotation" + "rotationVar": "neckRotation", + "typeVar": "headAndNeckType" }, { "jointName": "Head", "positionVar": "headPosition", "rotationVar": "headRotation", - "typeVar": "headType" + "typeVar": "headAndNeckType" } ] }, diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 0022749d51..ceef68f85b 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -1079,7 +1079,7 @@ void Rig::updateNeckJoint(int index, const HeadParameters& params) { _animVars.set("headPosition", headPos); _animVars.set("headRotation", headRot); - _animVars.set("headType", QString("RotationAndPosition")); + _animVars.set("headAndNeckType", QString("RotationAndPosition")); _animVars.set("neckPosition", neckPos); _animVars.set("neckRotation", neckRot); @@ -1092,7 +1092,7 @@ void Rig::updateNeckJoint(int index, const HeadParameters& params) { _animVars.unset("headPosition"); _animVars.set("headRotation", realLocalHeadOrientation); - _animVars.set("headType", QString("RotationOnly")); + _animVars.set("headAndNeckType", QString("RotationOnly")); _animVars.unset("neckPosition"); _animVars.unset("neckRotation"); } From c3dfea47122abd200dcbd257af5003e603c61033 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Wed, 30 Sep 2015 10:26:24 -0700 Subject: [PATCH 15/36] initial files --- .../toys/ping_pong_gun/createPingPongGun.js | 43 +++++ examples/toys/ping_pong_gun/pingPongGun.js | 154 ++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 examples/toys/ping_pong_gun/createPingPongGun.js create mode 100644 examples/toys/ping_pong_gun/pingPongGun.js diff --git a/examples/toys/ping_pong_gun/createPingPongGun.js b/examples/toys/ping_pong_gun/createPingPongGun.js new file mode 100644 index 0000000000..350fe63d02 --- /dev/null +++ b/examples/toys/ping_pong_gun/createPingPongGun.js @@ -0,0 +1,43 @@ +// createPingPongGun.js +// +// Script Type: Entity Spawner +// Created by James B. Pollack on 9/30/2015 +// Copyright 2015 High Fidelity, Inc. +// +// This script creates a gun that shoots ping pong balls when you pull the trigger on a hand controller. +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +/*global MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */ +Script.include("https://hifi-public.s3.amazonaws.com/scripts/utilities.js"); + + +var scriptURL = Script.resolvePath('pingPongGun.js'); + +var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx' +var COLLISION_HULL_URL = ''; +var center = Vec3.sum(Vec3.sum(MyAvatar.position, { + x: 0, + y: 0.5, + z: 0 +}), Vec3.multiply(0.5, Quat.getFront(Camera.getOrientation()))); + +var pingPongGun = Entities.addEntity({ + type: "Model", + modelURL: MODEL_URL, + position: center, + dimensions: { + x: 0.1, + y: 0.06, + z: 0.03 + }, + collisionsWillMove: true, + shapeType: 'compound', + compoundShapeURL: COLLISION_HULL_URL, + script: scriptURL +}); + +function cleanUp() { + +} +Script.scriptEnding.connect(cleanup) \ No newline at end of file diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js new file mode 100644 index 0000000000..48c0347d98 --- /dev/null +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -0,0 +1,154 @@ +// pingPongGun.js +// +// Script Type: Entity +// Created by James B. Pollack @imgntn on 9/21/2015 +// Copyright 2015 High Fidelity, Inc. +// +// This script shoots a ping pong ball. +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +/*global print, MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, Audio, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */ +(function() { + + Script.include("../../libraries/utils.js"); + + var SHOOTING_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/flashlight_on.wav'; + var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx' + + // this is the "constructor" for the entity as a JS object we don't do much here, but we do want to remember + // our this object, so we can access it in cases where we're called without a this (like in the case of various global signals) + function PingPongGun() { + return; + } + + //if the trigger value goes below this value, reload the gun. + var RELOAD_THRESHOLD = 0.7; + + var GUN_TIP_OFFSET = 0.095; + // Evaluate the world light entity positions and orientations from the model ones + function evalLightWorldTransform(modelPos, modelRot) { + + return { + p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)), + q: Quat.multiply(modelRot, MODEL_LIGHT_ROTATION) + }; + } + + PingPongGun.prototype = { + hand: null, + whichHand: null, + gunTipPosition: null, + setRightHand: function() { + this.hand = 'RIGHT'; + }, + + setLeftHand: function() { + this.hand = 'LEFT'; + }, + + startNearGrab: function() { + setWhichHand(); + }, + + setWhichHand: function() { + this.whichHand = this.hand; + }, + + continueNearGrab: function() { + if (this.whichHand === null) { + //only set the active hand once -- if we always read the current hand, our 'holding' hand will get overwritten + this.setWhichHand(); + } else { + this.checkTriggerPressure(this.whichHand); + } + }, + + releaseGrab: function() { + + }, + + checkTriggerPressure: function(gunHand) { + var handClickString = gunHand + "_HAND_CLICK"; + + var handClick = Controller.findAction(handClickString); + + this.triggerValue = Controller.getActionValue(handClick); + + if (this.triggerValue < RELOAD_THRESHOLD) { + this.canShoot = true; + } else if (this.triggerValue >= RELOAD_THRESHOLD && this.canShoot === true) { + var gunProperties = Entities.getEntityProperties(this.entityID,["position","rotation"]) + this.shootBall(gunProperties); + this.canShoot = false; + } + return; + }, + + shootBall: function(gunProperties,triggerValue) { + var forwardVec = Quat.getFront(Quat.multiply(gunProperties.rotation , Quat.fromPitchYawRollDegrees(0, 90, 0))); + //forwardVec = Vec3.normalize(forwardVec); + + var properties = { + type: 'Sphere' + color: { + red: 0, + green: 0, + blue: 255 + }, + dimensions: { + x: 0.04, + y: 0.04, + z: 0.04 + }, + linearDamping: 0.2, + gravity: { + x: 0, + y: -9.8, + z: 0 + }, + rotation:gunProperties.rotation, + position: this.gunTipPosition, + velocity: velocity, + lifetime: 10 + }; + var pingPongBall = Entities.addEntity(properties); + }, + + playSoundAtCurrentPosition: function(playOnSound) { + var position = Entities.getEntityProperties(this.entityID, "position").position; + + var audioProperties = { + volume: 0.25, + position: position + }; + + if (playOnSound) { + Audio.playSound(this.ON_SOUND, audioProperties); + } else { + Audio.playSound(this.OFF_SOUND, audioProperties); + } + }, + + getGunTipPosition: function(properties) { + //the tip of the gun is going to be in a different place than the center, so we move in space relative to the model to find that position + var upVector = Quat.getUp(properties.rotation); + var upOffset = Vec3.multiply(upVector, GUN_TIP_OFFSET); + var wandTipPosition = Vec3.sum(properties.position, upOffset); + return wandTipPosition; + }, + preload: function(entityID) { + this.entityID = entityID; + this.ON_SOUND = SoundCache.getSound(SHOOT_SOUND_URL); + + }, + + unload: function() { + + }, + + }; + + // entity scripts always need to return a newly constructed object of our type + return new Flashlight(); +}); \ No newline at end of file From 99fbed6143c17d9061b65889538808fe6ba15272 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Wed, 30 Sep 2015 10:49:47 -0700 Subject: [PATCH 16/36] mostly working --- .../toys/ping_pong_gun/createPingPongGun.js | 11 +-- examples/toys/ping_pong_gun/pingPongGun.js | 69 ++++++++++--------- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/examples/toys/ping_pong_gun/createPingPongGun.js b/examples/toys/ping_pong_gun/createPingPongGun.js index 350fe63d02..d045516fc4 100644 --- a/examples/toys/ping_pong_gun/createPingPongGun.js +++ b/examples/toys/ping_pong_gun/createPingPongGun.js @@ -15,7 +15,8 @@ Script.include("https://hifi-public.s3.amazonaws.com/scripts/utilities.js"); var scriptURL = Script.resolvePath('pingPongGun.js'); var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx' -var COLLISION_HULL_URL = ''; +var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj'; + var center = Vec3.sum(Vec3.sum(MyAvatar.position, { x: 0, y: 0.5, @@ -25,6 +26,9 @@ var center = Vec3.sum(Vec3.sum(MyAvatar.position, { var pingPongGun = Entities.addEntity({ type: "Model", modelURL: MODEL_URL, + shapeType: 'compound', + compoundShapeURL: COLLISION_HULL_URL, + script: scriptURL, position: center, dimensions: { x: 0.1, @@ -32,12 +36,9 @@ var pingPongGun = Entities.addEntity({ z: 0.03 }, collisionsWillMove: true, - shapeType: 'compound', - compoundShapeURL: COLLISION_HULL_URL, - script: scriptURL }); function cleanUp() { - +Entities.deleteEntity(pingPongGun); } Script.scriptEnding.connect(cleanup) \ No newline at end of file diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js index 48c0347d98..415b62c71e 100644 --- a/examples/toys/ping_pong_gun/pingPongGun.js +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -14,7 +14,6 @@ Script.include("../../libraries/utils.js"); var SHOOTING_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/flashlight_on.wav'; - var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx' // this is the "constructor" for the entity as a JS object we don't do much here, but we do want to remember // our this object, so we can access it in cases where we're called without a this (like in the case of various global signals) @@ -24,21 +23,21 @@ //if the trigger value goes below this value, reload the gun. var RELOAD_THRESHOLD = 0.7; - var GUN_TIP_OFFSET = 0.095; - // Evaluate the world light entity positions and orientations from the model ones - function evalLightWorldTransform(modelPos, modelRot) { + // // Evaluate the world light entity positions and orientations from the model ones + // function evalLightWorldTransform(modelPos, modelRot) { - return { - p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)), - q: Quat.multiply(modelRot, MODEL_LIGHT_ROTATION) - }; - } + // return { + // p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)), + // q: Quat.multiply(modelRot, MODEL_LIGHT_ROTATION) + // }; + // } PingPongGun.prototype = { hand: null, whichHand: null, gunTipPosition: null, + canShoot: false, setRightHand: function() { this.hand = 'RIGHT'; }, @@ -48,7 +47,7 @@ }, startNearGrab: function() { - setWhichHand(); + this.setWhichHand(); }, setWhichHand: function() { @@ -76,21 +75,23 @@ this.triggerValue = Controller.getActionValue(handClick); if (this.triggerValue < RELOAD_THRESHOLD) { + print('RELOAD'); this.canShoot = true; } else if (this.triggerValue >= RELOAD_THRESHOLD && this.canShoot === true) { - var gunProperties = Entities.getEntityProperties(this.entityID,["position","rotation"]) + var gunProperties = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); this.shootBall(gunProperties); this.canShoot = false; } return; }, - shootBall: function(gunProperties,triggerValue) { - var forwardVec = Quat.getFront(Quat.multiply(gunProperties.rotation , Quat.fromPitchYawRollDegrees(0, 90, 0))); - //forwardVec = Vec3.normalize(forwardVec); + shootBall: function(gunProperties, triggerValue) { + print('SHOOT BALL'); + var forwardVec = Quat.getFront(Quat.multiply(gunProperties.rotation, Quat.fromPitchYawRollDegrees(0, 90, 0))); + forwardVec = Vec3.normalize(forwardVec); var properties = { - type: 'Sphere' + type: 'Sphere', color: { red: 0, green: 0, @@ -104,42 +105,46 @@ linearDamping: 0.2, gravity: { x: 0, - y: -9.8, + y: -0.05, z: 0 }, - rotation:gunProperties.rotation, - position: this.gunTipPosition, - velocity: velocity, + collisionsWillMove: true, + collisionSoundURL: SHOOTING_SOUND_URL, + rotation: gunProperties.rotation, + position: this.getGunTipPosition(gunProperties), + velocity: forwardVec, lifetime: 10 }; var pingPongBall = Entities.addEntity(properties); + var audioOptions = { + position: gunProperties.position + } + this.playSoundAtCurrentPosition(gunProperties.position); }, - playSoundAtCurrentPosition: function(playOnSound) { - var position = Entities.getEntityProperties(this.entityID, "position").position; + playSoundAtCurrentPosition: function(position) { var audioProperties = { volume: 0.25, position: position }; - if (playOnSound) { - Audio.playSound(this.ON_SOUND, audioProperties); - } else { - Audio.playSound(this.OFF_SOUND, audioProperties); - } + + Audio.playSound(this.SHOOTING_SOUND, audioProperties); + }, getGunTipPosition: function(properties) { //the tip of the gun is going to be in a different place than the center, so we move in space relative to the model to find that position - var upVector = Quat.getUp(properties.rotation); - var upOffset = Vec3.multiply(upVector, GUN_TIP_OFFSET); - var wandTipPosition = Vec3.sum(properties.position, upOffset); - return wandTipPosition; + var frontVector = Quat.getFront(properties.rotation); + var frontOffset = Vec3.multiply(frontVector, GUN_TIP_OFFSET); + var gunTipPosition = Vec3.sum(properties.position, frontOffset); + return gunTipPosition; }, preload: function(entityID) { + print('PRELOAD PING PONG GUN'); this.entityID = entityID; - this.ON_SOUND = SoundCache.getSound(SHOOT_SOUND_URL); + this.SHOOTING_SOUND = SoundCache.getSound(SHOOTING_SOUND_URL); }, @@ -150,5 +155,5 @@ }; // entity scripts always need to return a newly constructed object of our type - return new Flashlight(); + return new PingPongGun(); }); \ No newline at end of file From ecad7f34f6afd1417e2f2a10863c90a47ded3821 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Wed, 30 Sep 2015 10:58:21 -0700 Subject: [PATCH 17/36] moar --- examples/toys/ping_pong_gun/pingPongGun.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js index 415b62c71e..c3d10e7198 100644 --- a/examples/toys/ping_pong_gun/pingPongGun.js +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -86,21 +86,20 @@ }, shootBall: function(gunProperties, triggerValue) { - print('SHOOT BALL'); var forwardVec = Quat.getFront(Quat.multiply(gunProperties.rotation, Quat.fromPitchYawRollDegrees(0, 90, 0))); - forwardVec = Vec3.normalize(forwardVec); + // forwardVec = Vec3.normalize(forwardVec); var properties = { type: 'Sphere', color: { - red: 0, - green: 0, + red: 255, + green: 255, blue: 255 }, dimensions: { - x: 0.04, - y: 0.04, - z: 0.04 + x: 0.02, + y: 0.02, + z: 0.02 }, linearDamping: 0.2, gravity: { From 8bdf428f41663a74afc125a9c038e2dd3403f59e Mon Sep 17 00:00:00 2001 From: James Pollack Date: Wed, 30 Sep 2015 11:21:51 -0700 Subject: [PATCH 18/36] First version of ping pong gun --- .../toys/ping_pong_gun/createPingPongGun.js | 4 +- examples/toys/ping_pong_gun/pingPongGun.js | 51 +++++++------------ 2 files changed, 20 insertions(+), 35 deletions(-) diff --git a/examples/toys/ping_pong_gun/createPingPongGun.js b/examples/toys/ping_pong_gun/createPingPongGun.js index d045516fc4..1bf0415ebd 100644 --- a/examples/toys/ping_pong_gun/createPingPongGun.js +++ b/examples/toys/ping_pong_gun/createPingPongGun.js @@ -39,6 +39,6 @@ var pingPongGun = Entities.addEntity({ }); function cleanUp() { -Entities.deleteEntity(pingPongGun); + Entities.deleteEntity(pingPongGun); } -Script.scriptEnding.connect(cleanup) \ No newline at end of file +Script.scriptEnding.connect(cleanUp); \ No newline at end of file diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js index c3d10e7198..31681bc2d8 100644 --- a/examples/toys/ping_pong_gun/pingPongGun.js +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -15,23 +15,14 @@ var SHOOTING_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/flashlight_on.wav'; - // this is the "constructor" for the entity as a JS object we don't do much here, but we do want to remember - // our this object, so we can access it in cases where we're called without a this (like in the case of various global signals) function PingPongGun() { return; } //if the trigger value goes below this value, reload the gun. - var RELOAD_THRESHOLD = 0.7; - var GUN_TIP_OFFSET = 0.095; - // // Evaluate the world light entity positions and orientations from the model ones - // function evalLightWorldTransform(modelPos, modelRot) { - - // return { - // p: Vec3.sum(modelPos, Vec3.multiplyQbyV(modelRot, MODEL_LIGHT_POSITION)), - // q: Quat.multiply(modelRot, MODEL_LIGHT_ROTATION) - // }; - // } + var RELOAD_THRESHOLD = 0.95; + var GUN_TIP_FWD_OFFSET = -0.056; + var GUN_TIP_UP_OFFSET = 0.001; PingPongGun.prototype = { hand: null, @@ -64,7 +55,7 @@ }, releaseGrab: function() { - + this.canShoot = false; }, checkTriggerPressure: function(gunHand) { @@ -75,7 +66,7 @@ this.triggerValue = Controller.getActionValue(handClick); if (this.triggerValue < RELOAD_THRESHOLD) { - print('RELOAD'); + // print('RELOAD'); this.canShoot = true; } else if (this.triggerValue >= RELOAD_THRESHOLD && this.canShoot === true) { var gunProperties = Entities.getEntityProperties(this.entityID, ["position", "rotation"]); @@ -85,10 +76,10 @@ return; }, - shootBall: function(gunProperties, triggerValue) { + shootBall: function(gunProperties) { var forwardVec = Quat.getFront(Quat.multiply(gunProperties.rotation, Quat.fromPitchYawRollDegrees(0, 90, 0))); - // forwardVec = Vec3.normalize(forwardVec); - + forwardVec = Vec3.normalize(forwardVec); + forwardVec = Vec3.multiply(forwardVec, 2); var properties = { type: 'Sphere', color: { @@ -114,42 +105,36 @@ velocity: forwardVec, lifetime: 10 }; - var pingPongBall = Entities.addEntity(properties); - var audioOptions = { - position: gunProperties.position - } + + Entities.addEntity(properties); + this.playSoundAtCurrentPosition(gunProperties.position); }, playSoundAtCurrentPosition: function(position) { - var audioProperties = { volume: 0.25, position: position }; - Audio.playSound(this.SHOOTING_SOUND, audioProperties); - }, getGunTipPosition: function(properties) { //the tip of the gun is going to be in a different place than the center, so we move in space relative to the model to find that position - var frontVector = Quat.getFront(properties.rotation); - var frontOffset = Vec3.multiply(frontVector, GUN_TIP_OFFSET); + var frontVector = Quat.getRight(properties.rotation); + var frontOffset = Vec3.multiply(frontVector, GUN_TIP_FWD_OFFSET); + var upVector = Quat.getRight(properties.rotation); + var upOffset = Vec3.multiply(upVector, GUN_TIP_UP_OFFSET); var gunTipPosition = Vec3.sum(properties.position, frontOffset); + gunTipPosition = Vec3.sum(gunTipPosition, upOffset); return gunTipPosition; }, + preload: function(entityID) { - print('PRELOAD PING PONG GUN'); this.entityID = entityID; this.SHOOTING_SOUND = SoundCache.getSound(SHOOTING_SOUND_URL); - - }, - - unload: function() { - - }, + } }; From 0865f94106111e1483fad157cb3ef8e6e8de37ef Mon Sep 17 00:00:00 2001 From: James Pollack Date: Wed, 30 Sep 2015 11:31:33 -0700 Subject: [PATCH 19/36] magic numbers --- examples/toys/ping_pong_gun/pingPongGun.js | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js index 31681bc2d8..da7a4a6d28 100644 --- a/examples/toys/ping_pong_gun/pingPongGun.js +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -15,14 +15,21 @@ var SHOOTING_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/flashlight_on.wav'; + function PingPongGun() { return; } //if the trigger value goes below this value, reload the gun. var RELOAD_THRESHOLD = 0.95; - var GUN_TIP_FWD_OFFSET = -0.056; - var GUN_TIP_UP_OFFSET = 0.001; + var GUN_TIP_FWD_OFFSET = -0.08; + var GUN_TIP_UP_OFFSET = 0.020; + var GUN_FORCE = 5; + var BALL_GRAVITY = { + x: 0, + y: -1, + z: 0 + }; PingPongGun.prototype = { hand: null, @@ -79,7 +86,7 @@ shootBall: function(gunProperties) { var forwardVec = Quat.getFront(Quat.multiply(gunProperties.rotation, Quat.fromPitchYawRollDegrees(0, 90, 0))); forwardVec = Vec3.normalize(forwardVec); - forwardVec = Vec3.multiply(forwardVec, 2); + forwardVec = Vec3.multiply(forwardVec, GUN_FORCE); var properties = { type: 'Sphere', color: { @@ -93,11 +100,7 @@ z: 0.02 }, linearDamping: 0.2, - gravity: { - x: 0, - y: -0.05, - z: 0 - }, + gravity: BALL_GRAVITY, collisionsWillMove: true, collisionSoundURL: SHOOTING_SOUND_URL, rotation: gunProperties.rotation, From c56ac246024162970e3cd63db2dc7f02eb0bb57b Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 30 Sep 2015 11:36:28 -0700 Subject: [PATCH 20/36] Improve particle property interpolation Use Bezier interpolation instead of cubic so that values don't overshoot. --- .../entities/src/ParticleEffectEntityItem.cpp | 21 +++---- libraries/shared/src/Interpolate.cpp | 59 ++++++++++--------- libraries/shared/src/Interpolate.h | 10 ++-- 3 files changed, 47 insertions(+), 43 deletions(-) diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 9d11dff55a..40d3853c39 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -594,25 +594,22 @@ QString ParticleEffectEntityItem::getAnimationSettings() const { } void ParticleEffectEntityItem::updateRadius(quint32 index, float age) { - _particleRadiuses[index] = Interpolate::cubicInterpolate3Points(_radiusStarts[index], _radiusMiddles[index], + _particleRadiuses[index] = Interpolate::interpolate3Points(_radiusStarts[index], _radiusMiddles[index], _radiusFinishes[index], age); } void ParticleEffectEntityItem::updateColor(quint32 index, float age) { - _particleColors[index].red = - (int)glm::clamp(Interpolate::cubicInterpolate3Points(_colorStarts[index].red, _colorMiddles[index].red, - _colorFinishes[index].red, age), 0.0f, 255.0f); - _particleColors[index].green = - (int)glm::clamp(Interpolate::cubicInterpolate3Points(_colorStarts[index].green, _colorMiddles[index].green, - _colorFinishes[index].green, age), 0.0f, 255.0f); - _particleColors[index].blue = - (int)glm::clamp(Interpolate::cubicInterpolate3Points(_colorStarts[index].blue, _colorMiddles[index].blue, - _colorFinishes[index].blue, age), 0.0f, 255.0f); + _particleColors[index].red = (int)Interpolate::interpolate3Points(_colorStarts[index].red, _colorMiddles[index].red, + _colorFinishes[index].red, age); + _particleColors[index].green = (int)Interpolate::interpolate3Points(_colorStarts[index].green, _colorMiddles[index].green, + _colorFinishes[index].green, age); + _particleColors[index].blue = (int)Interpolate::interpolate3Points(_colorStarts[index].blue, _colorMiddles[index].blue, + _colorFinishes[index].blue, age); } void ParticleEffectEntityItem::updateAlpha(quint32 index, float age) { - _particleAlphas[index] = glm::clamp(Interpolate::cubicInterpolate3Points(_alphaStarts[index], _alphaMiddles[index], - _alphaFinishes[index], age), 0.0f, 1.0f); + _particleAlphas[index] = Interpolate::interpolate3Points(_alphaStarts[index], _alphaMiddles[index], + _alphaFinishes[index], age); } void ParticleEffectEntityItem::extendBounds(const glm::vec3& point) { diff --git a/libraries/shared/src/Interpolate.cpp b/libraries/shared/src/Interpolate.cpp index 7c18236bd0..bc18c087ad 100644 --- a/libraries/shared/src/Interpolate.cpp +++ b/libraries/shared/src/Interpolate.cpp @@ -11,41 +11,46 @@ #include "Interpolate.h" -float Interpolate::cubicInterpolate2Points(float y0, float y1, float y2, float y3, float u) { - float a0, a1, a2, a3, uu, uuu; +#include - a0 = y3 - y2 - y0 + y1; - a1 = y0 - y1 - a0; - a2 = y2 - y0; - a3 = y1; - - uu = u * u; - uuu = uu * u; - - return (a0 * uuu + a1 * uu + a2 * u + a3); +float Interpolate::bezierInterpolate(float y1, float y2, float y3, float u) { + // https://en.wikipedia.org/wiki/Bezier_curve + return (1.0f - u) * (1.0f - u) * y1 + 2.0f * (1.0f - u) * u * y2 + u * u * y3; } -float Interpolate::cubicInterpolate3Points(float y1, float y2, float y3, float u) { - float y0, y4; +float Interpolate::interpolate3Points(float y1, float y2, float y3, float u) { + if (u <= 0.5f && y1 == y2 || u >= 0.5f && y2 == y3) { + // Flat line. + return y2; + } - if (u <= 0.5f) { - if (y1 == y2) { - return y2; + if (y2 >= y1 && y2 >= y3 || y2 <= y1 && y2 <= y3) { + // U or inverted-U shape. + // Make the slope at y2 = 0, which means that the control points half way between the value points have the value y2. + if (u <= 0.5f) { + return bezierInterpolate(y1, y2, y2, 2.0f * u); + } else { + return bezierInterpolate(y2, y2, y3, 2.0f * u - 1.0f); } - y0 = 2.0f * y1 - y2; // y0 is linear extension of line from y2 to y1. - u = 2.0f * u; - - return Interpolate::cubicInterpolate2Points(y0, y1, y2, y3, u); - } else { - if (y2 == y3) { - return y2; + // L or inverted and/or mirrored L shape. + // Make the slope at y2 be the slope between y1 and y3, up to a maximum of double the minimum of the slopes between y1 + // and y2, and y2 and y3. Use this slope to calculate the control points half way between the value points. + // Note: The maximum ensures that the control points and therefore the interpolated values stay between y1 and y3. + float slope = y3 - y1; + float slope12 = y2 - y1; + float slope23 = y3 - y2; + if (fabsf(slope) > fabsf(2.0f * slope12)) { + slope = 2.0f * slope12; + } else if (fabsf(slope) > fabsf(2.0f * slope23)) { + slope = 2.0f * slope23; } - y4 = 2.0f * y3 - y2; // y4 is linear extension of line from y2 to y3. - u = 2.0f * u - 1.0f; - - return Interpolate::cubicInterpolate2Points(y1, y2, y3, y4, u); + if (u <= 0.5f) { + return bezierInterpolate(y1, y2 - slope / 2.0f, y2, 2.0f * u); + } else { + return bezierInterpolate(y2, y2 + slope / 2.0f, y3, 2.0f * u - 1.0f); + } } } diff --git a/libraries/shared/src/Interpolate.h b/libraries/shared/src/Interpolate.h index 919d075b15..316bee1339 100644 --- a/libraries/shared/src/Interpolate.h +++ b/libraries/shared/src/Interpolate.h @@ -15,11 +15,13 @@ class Interpolate { public: - // Cubic interpolation at position u [0.0 - 1.0] between values y1 and y2 with equidistant values y0 and y3 either side. - static float cubicInterpolate2Points(float y0, float y1, float y2, float y3, float u); + // Bezier interpolate at position u [0.0 - 1.0] between y values equally spaced along the x-axis. The interpolated values + // pass through y1 and y3 but not y2; y2 is the Bezier control point. + static float bezierInterpolate(float y1, float y2, float y3, float u); - // Cubic interpolation at position u [0.0 - 1.0] between values y1 and y3 with midpoint value y2. - static float cubicInterpolate3Points(float y1, float y2, float y3, float u); + // Interpolate at position u [0.0 - 1.0] between y values equally spaced along the x-axis such that the interpolated values + // pass through all three y values. Return value lies wholly within the range of y values passed in. + static float interpolate3Points(float y1, float y2, float y3, float u); }; #endif // hifi_Interpolate_h From c55d627e9bd33f302d4e33a1c323dfb07d2343ad Mon Sep 17 00:00:00 2001 From: James Pollack Date: Wed, 30 Sep 2015 16:12:27 -0700 Subject: [PATCH 21/36] Different model, different sounds, release interval --- .../toys/ping_pong_gun/createPingPongGun.js | 6 +-- examples/toys/ping_pong_gun/pingPongGun.js | 54 ++++++++++++------- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/examples/toys/ping_pong_gun/createPingPongGun.js b/examples/toys/ping_pong_gun/createPingPongGun.js index 1bf0415ebd..d8509d8a63 100644 --- a/examples/toys/ping_pong_gun/createPingPongGun.js +++ b/examples/toys/ping_pong_gun/createPingPongGun.js @@ -31,9 +31,9 @@ var pingPongGun = Entities.addEntity({ script: scriptURL, position: center, dimensions: { - x: 0.1, - y: 0.06, - z: 0.03 + x:0.67, + y: 0.14, + z: 0.09 }, collisionsWillMove: true, }); diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js index da7a4a6d28..0a589fb3fb 100644 --- a/examples/toys/ping_pong_gun/pingPongGun.js +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -13,8 +13,7 @@ Script.include("../../libraries/utils.js"); - var SHOOTING_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/flashlight_on.wav'; - + var SHOOTING_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/ping_pong_gun/pong_sound.wav'; function PingPongGun() { return; @@ -22,20 +21,36 @@ //if the trigger value goes below this value, reload the gun. var RELOAD_THRESHOLD = 0.95; - var GUN_TIP_FWD_OFFSET = -0.08; - var GUN_TIP_UP_OFFSET = 0.020; - var GUN_FORCE = 5; + var GUN_TIP_FWD_OFFSET = -0.55; + var GUN_TIP_UP_OFFSET = 0.040; + var GUN_FORCE = 15; + var BALL_RESTITUTION = 0.6; + var BALL_LINEAR_DAMPING = 0.4; var BALL_GRAVITY = { x: 0, - y: -1, + y: -9.8, z: 0 }; + var BALL_DIMENSIONS = { + x: 0.04, + y: 0.04, + z: 0.04 + } + + + var BALL_COLOR = { + red: 255, + green: 255, + blue: 255 + } + PingPongGun.prototype = { hand: null, whichHand: null, gunTipPosition: null, canShoot: false, + canShootTimeout: null, setRightHand: function() { this.hand = 'RIGHT'; }, @@ -53,16 +68,23 @@ }, continueNearGrab: function() { + if (this.whichHand === null) { //only set the active hand once -- if we always read the current hand, our 'holding' hand will get overwritten this.setWhichHand(); } else { + if (this.canShootTimeout !== null) { + Script.clearTimeout(this.canShootTimeout); + } this.checkTriggerPressure(this.whichHand); } }, releaseGrab: function() { - this.canShoot = false; + var _t = this; + this.canShootTimeout = Script.setTimeout(function() { + _t.canShoot = false; + }, 250) }, checkTriggerPressure: function(gunHand) { @@ -89,20 +111,12 @@ forwardVec = Vec3.multiply(forwardVec, GUN_FORCE); var properties = { type: 'Sphere', - color: { - red: 255, - green: 255, - blue: 255 - }, - dimensions: { - x: 0.02, - y: 0.02, - z: 0.02 - }, - linearDamping: 0.2, + color: BALL_COLOR, + dimensions: BALL_DIMENSIONS, + linearDamping: BALL_LINEAR_DAMPING, gravity: BALL_GRAVITY, + restitution: BALL_RESTITUTION, collisionsWillMove: true, - collisionSoundURL: SHOOTING_SOUND_URL, rotation: gunProperties.rotation, position: this.getGunTipPosition(gunProperties), velocity: forwardVec, @@ -116,7 +130,7 @@ playSoundAtCurrentPosition: function(position) { var audioProperties = { - volume: 0.25, + volume: 0.1, position: position }; From c01077a0d7c425ceadac7f9f3f1335c5107b44ca Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Wed, 30 Sep 2015 17:30:34 -0700 Subject: [PATCH 22/36] real fix --- assignment-client/src/Agent.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 4438782ae5..d9109703cb 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -233,8 +233,8 @@ void Agent::setIsAvatar(bool isAvatar) { } if (_avatarBillboardTimer) { - _avatarIdentityTimer->stop(); - delete _avatarIdentityTimer; + _avatarBillboardTimer->stop(); + delete _avatarBillboardTimer; _avatarBillboardTimer = nullptr; } } From 5da5bd47af36c83eb5d19bdb7f494c93b509abb9 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 30 Sep 2015 21:45:22 -0400 Subject: [PATCH 23/36] add a missing rename for socket Q_ASSERT_X --- libraries/networking/src/udt/Connection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/networking/src/udt/Connection.cpp b/libraries/networking/src/udt/Connection.cpp index 1bda840a6c..e8b22f6ab8 100644 --- a/libraries/networking/src/udt/Connection.cpp +++ b/libraries/networking/src/udt/Connection.cpp @@ -32,7 +32,7 @@ Connection::Connection(Socket* parentSocket, HifiSockAddr destination, std::uniq _destination(destination), _congestionControl(move(congestionControl)) { - Q_ASSERT_X(socket, "Connection::Connection", "Must be called with a valid Socket*"); + Q_ASSERT_X(parentSocket, "Connection::Connection", "Must be called with a valid Socket*"); Q_ASSERT_X(_congestionControl, "Connection::Connection", "Must be called with a valid CongestionControl object"); _congestionControl->init(); From d4f954a0e2ee1c5c27bcd161bb6fd1a8be880923 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Oct 2015 10:25:30 -0700 Subject: [PATCH 24/36] allow more than one near-grab on an object --- examples/controllers/handControllerGrab.js | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index e756866b1c..4dd9dca7a2 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -242,8 +242,7 @@ function MyController(hand, triggerAction) { var intersection = Entities.findRayIntersection(pickRay, true); if (intersection.intersects && intersection.properties.collisionsWillMove === 1 && - intersection.properties.locked === 0 && - !entityIsGrabbedByOther(intersection.entityID)) { + intersection.properties.locked === 0) { // the ray is intersecting something we can move. var handControllerPosition = Controller.getSpatialControlPosition(this.palm); var intersectionDistance = Vec3.distance(handControllerPosition, intersection.intersection); @@ -258,6 +257,10 @@ function MyController(hand, triggerAction) { this.state = STATE_NEAR_GRABBING; } else { + if (entityIsGrabbedByOther(intersection.entityID)) { + // don't allow two people to distance grab the same object + return; + } // the hand is far from the intersected object. go into distance-holding mode this.state = STATE_DISTANCE_HOLDING; this.lineOn(pickRay.origin, Vec3.multiply(pickRay.direction, LINE_LENGTH), NO_INTERSECT_COLOR); @@ -441,16 +444,13 @@ function MyController(hand, triggerAction) { var offsetPosition = Vec3.multiplyQbyV(Quat.inverse(Quat.multiply(handRotation, offsetRotation)), offset); this.actionID = NULL_ACTION_ID; - if (!entityIsGrabbedByOther(this.grabbedEntity)) { - this.actionID = Entities.addAction("hold", this.grabbedEntity, { - hand: this.hand === RIGHT_HAND ? "right" : "left", - timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, - relativePosition: offsetPosition, - relativeRotation: offsetRotation, - tag: getTag(), - lifetime: ACTION_LIFETIME - }); - } + this.actionID = Entities.addAction("hold", this.grabbedEntity, { + hand: this.hand === RIGHT_HAND ? "right" : "left", + timeScale: NEAR_GRABBING_ACTION_TIMEFRAME, + relativePosition: offsetPosition, + relativeRotation: offsetRotation, + lifetime: ACTION_LIFETIME + }); if (this.actionID === NULL_ACTION_ID) { this.actionID = null; } else { From 2700529b33921a9c2fc1f526256faca759a42c47 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Thu, 1 Oct 2015 10:41:43 -0700 Subject: [PATCH 25/36] lower action lifetime --- examples/controllers/handControllerGrab.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index 4dd9dca7a2..5705bd4498 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -66,7 +66,7 @@ var MSEC_PER_SEC = 1000.0; // these control how long an abandoned pointer line will hang around var startTime = Date.now(); var LIFETIME = 10; -var ACTION_LIFETIME = 120; // 2 minutes +var ACTION_LIFETIME = 10; // seconds // states for the state machine var STATE_OFF = 0; From 335d87134b73d80adaf14ad40984dbfab7a0f0c0 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 1 Oct 2015 10:58:31 -0700 Subject: [PATCH 26/36] Squash compiler warning in AnimVariant. --- libraries/animation/src/AnimVariant.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libraries/animation/src/AnimVariant.h b/libraries/animation/src/AnimVariant.h index 700a8b4121..cb886cd369 100644 --- a/libraries/animation/src/AnimVariant.h +++ b/libraries/animation/src/AnimVariant.h @@ -184,6 +184,8 @@ public: case AnimVariant::Type::String: qCDebug(animation) << " " << pair.first << "=" << pair.second.getString(); break; + default: + assert("AnimVariant::Type" == "valid"); } } } From d0bec38603a9de2b97852ca5e96797826aec53e8 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 1 Oct 2015 11:30:50 -0700 Subject: [PATCH 27/36] Fix currentAPI.js --- examples/utilities/tools/currentAPI.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/utilities/tools/currentAPI.js b/examples/utilities/tools/currentAPI.js index 30b24910f9..cb9f152794 100644 --- a/examples/utilities/tools/currentAPI.js +++ b/examples/utilities/tools/currentAPI.js @@ -10,22 +10,21 @@ // var array = []; -var buffer = "\n\n\n\n\n======= JS API list ======="; function listKeys(string, object) { - if (string == "listKeys" || string == "array" || string == "buffer" || string == "i") { + if (string === "listKeys" || string === "array" || string === "buffer" || string === "i") { return; } - if (typeof(object) != "object") { + if (typeof(object) !== "object" || object === null) { array.push(string + " " + typeof(object)); return; } var keys = Object.keys(object); for (var i = 0; i < keys.length; ++i) { - if (string == "") { + if (string === "") { listKeys(keys[i], object[keys[i]]); - } else { + } else if (keys[i] !== "parent") { listKeys(string + "." + keys[i], object[keys[i]]); } } @@ -34,9 +33,10 @@ function listKeys(string, object) { listKeys("", this); array.sort(); +var buffer = "\n======= JS API list ======="; for (var i = 0; i < array.length; ++i) { - buffer = buffer + "\n" + array[i]; + buffer += "\n" + array[i]; } -buffer = buffer + "\n========= API END =========\n\n\n\n\n"; +buffer += "\n========= API END =========\n"; print(buffer); From 861aa91572d6c56c1f9357b641be9149a283eb47 Mon Sep 17 00:00:00 2001 From: James Pollack Date: Thu, 1 Oct 2015 12:27:45 -0700 Subject: [PATCH 28/36] shoot out of the right end of the gun --- examples/toys/ping_pong_gun/pingPongGun.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/toys/ping_pong_gun/pingPongGun.js b/examples/toys/ping_pong_gun/pingPongGun.js index 0a589fb3fb..a980fc1bd3 100644 --- a/examples/toys/ping_pong_gun/pingPongGun.js +++ b/examples/toys/ping_pong_gun/pingPongGun.js @@ -21,7 +21,7 @@ //if the trigger value goes below this value, reload the gun. var RELOAD_THRESHOLD = 0.95; - var GUN_TIP_FWD_OFFSET = -0.55; + var GUN_TIP_FWD_OFFSET = 0.45; var GUN_TIP_UP_OFFSET = 0.040; var GUN_FORCE = 15; var BALL_RESTITUTION = 0.6; @@ -106,7 +106,7 @@ }, shootBall: function(gunProperties) { - var forwardVec = Quat.getFront(Quat.multiply(gunProperties.rotation, Quat.fromPitchYawRollDegrees(0, 90, 0))); + var forwardVec = Quat.getFront(Quat.multiply(gunProperties.rotation, Quat.fromPitchYawRollDegrees(0, -90, 0))); forwardVec = Vec3.normalize(forwardVec); forwardVec = Vec3.multiply(forwardVec, GUN_FORCE); var properties = { From b37bf2b1b68cb191bc8e01760b107a5f0cb22300 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 1 Oct 2015 13:18:22 -0700 Subject: [PATCH 29/36] Remove extra debug --- interface/resources/qml/VrMenu.qml | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/resources/qml/VrMenu.qml b/interface/resources/qml/VrMenu.qml index ef7ae852d4..14a4a449fd 100644 --- a/interface/resources/qml/VrMenu.qml +++ b/interface/resources/qml/VrMenu.qml @@ -196,7 +196,6 @@ Hifi.VrMenu { function insertItem(menu, beforeItem, newMenuItem) { for (var i = 0; i < menu.items.length; ++i) { - console.log(menu.items[i]); if (menu.items[i] === beforeItem) { return menu.insertItem(i, newMenuItem); } From 09ac01a5e78684fc5ca46d2ae666bdea4b935101 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 1 Oct 2015 13:42:20 -0700 Subject: [PATCH 30/36] remove cruft from old verlet avatar simulation --- interface/src/avatar/SkeletonModel.cpp | 2 +- libraries/animation/src/AnimationHandle.cpp | 1 - libraries/animation/src/JointState.cpp | 89 +-------- libraries/animation/src/JointState.h | 30 +-- libraries/animation/src/Rig.cpp | 80 ++------ libraries/animation/src/Rig.h | 6 +- libraries/physics/src/Constraint.h | 25 --- libraries/render-utils/src/Model.cpp | 54 +----- libraries/render-utils/src/Model.h | 11 -- libraries/shared/src/AngularConstraint.cpp | 202 -------------------- libraries/shared/src/AngularConstraint.h | 54 ------ 11 files changed, 32 insertions(+), 522 deletions(-) delete mode 100644 libraries/physics/src/Constraint.h delete mode 100644 libraries/shared/src/AngularConstraint.cpp delete mode 100644 libraries/shared/src/AngularConstraint.h diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index b1f6e6d8d1..7c2cf43c07 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -320,7 +320,7 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; _rig->applyJointRotationDelta(jointIndex, rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector), - true, PALM_PRIORITY); + PALM_PRIORITY); } void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) { diff --git a/libraries/animation/src/AnimationHandle.cpp b/libraries/animation/src/AnimationHandle.cpp index f2d12b398e..93dd965e02 100644 --- a/libraries/animation/src/AnimationHandle.cpp +++ b/libraries/animation/src/AnimationHandle.cpp @@ -181,7 +181,6 @@ void AnimationHandle::applyFrame(float frameIndex) { ceilFrame.rotations.at(i), frameFraction), _priority, - false, _mix); } } diff --git a/libraries/animation/src/JointState.cpp b/libraries/animation/src/JointState.cpp index 9597a46726..0746f65e84 100644 --- a/libraries/animation/src/JointState.cpp +++ b/libraries/animation/src/JointState.cpp @@ -13,16 +13,11 @@ #include -#include #include #include "JointState.h" JointState::~JointState() { - if (_constraint) { - delete _constraint; - _constraint = NULL; - } } void JointState::copyState(const JointState& other) { @@ -35,18 +30,12 @@ void JointState::copyState(const JointState& other) { _distanceToParent = other._distanceToParent; _animationPriority = other._animationPriority; - _visibleTransform = other._visibleTransform; - _visibleRotation = extractRotation(_visibleTransform); - _visibleRotationInConstrainedFrame = other._visibleRotationInConstrainedFrame; - // DO NOT copy _constraint _name = other._name; _isFree = other._isFree; _parentIndex = other._parentIndex; _defaultRotation = other._defaultRotation; _inverseDefaultRotation = other._inverseDefaultRotation; _translation = other._translation; - _rotationMin = other._rotationMin; - _rotationMax = other._rotationMax; _preRotation = other._preRotation; _postRotation = other._postRotation; _preTransform = other._preTransform; @@ -61,8 +50,6 @@ JointState::JointState(const FBXJoint& joint) { _translation = joint.translation; _defaultRotation = joint.rotation; _inverseDefaultRotation = joint.inverseDefaultRotation; - _rotationMin = joint.rotationMin; - _rotationMax = joint.rotationMax; _preRotation = joint.preRotation; _postRotation = joint.postRotation; _preTransform = joint.preTransform; @@ -71,15 +58,6 @@ JointState::JointState(const FBXJoint& joint) { } void JointState::buildConstraint() { - if (_constraint) { - delete _constraint; - _constraint = NULL; - } - if (glm::distance2(glm::vec3(-PI), _rotationMin) > EPSILON || - glm::distance2(glm::vec3(PI), _rotationMax) > EPSILON ) { - // this joint has rotation constraints - _constraint = AngularConstraint::newAngularConstraint(_rotationMin, _rotationMax); - } } glm::quat JointState::getRotation() const { @@ -113,13 +91,6 @@ void JointState::computeTransform(const glm::mat4& parentTransform, bool parentT } } -void JointState::computeVisibleTransform(const glm::mat4& parentTransform) { - glm::quat rotationInParentFrame = _preRotation * _visibleRotationInConstrainedFrame * _postRotation; - glm::mat4 transformInParentFrame = _preTransform * glm::mat4_cast(rotationInParentFrame) * _postTransform; - _visibleTransform = parentTransform * glm::translate(_translation) * transformInParentFrame; - _visibleRotation = extractRotation(_visibleTransform); -} - glm::quat JointState::getRotationInBindFrame() const { return getRotation() * _inverseBindRotation; } @@ -128,10 +99,6 @@ glm::quat JointState::getRotationInParentFrame() const { return _preRotation * _rotationInConstrainedFrame * _postRotation; } -glm::quat JointState::getVisibleRotationInParentFrame() const { - return _preRotation * _visibleRotationInConstrainedFrame * _postRotation; -} - void JointState::restoreRotation(float fraction, float priority) { if (priority == _animationPriority || _animationPriority == 0.0f) { setRotationInConstrainedFrameInternal(safeMix(_rotationInConstrainedFrame, _defaultRotation, fraction)); @@ -139,19 +106,16 @@ void JointState::restoreRotation(float fraction, float priority) { } } -void JointState::setRotationInBindFrame(const glm::quat& rotation, float priority, bool constrain) { +void JointState::setRotationInBindFrame(const glm::quat& rotation, float priority) { // rotation is from bind- to model-frame if (priority >= _animationPriority) { glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * rotation * glm::inverse(_inverseBindRotation); - if (constrain && _constraint) { - _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); - } setRotationInConstrainedFrameInternal(targetRotation); _animationPriority = priority; } } -void JointState::setRotationInModelFrame(const glm::quat& rotationInModelFrame, float priority, bool constrain) { +void JointState::setRotationInModelFrame(const glm::quat& rotationInModelFrame, float priority) { // rotation is from bind- to model-frame if (priority >= _animationPriority) { glm::quat parentRotation = computeParentRotation(); @@ -160,9 +124,6 @@ void JointState::setRotationInModelFrame(const glm::quat& rotationInModelFrame, // R' = Rp * Rpre * r' * Rpost // r' = (Rp * Rpre)^ * R' * Rpost^ glm::quat targetRotation = glm::inverse(parentRotation * _preRotation) * rotationInModelFrame * glm::inverse(_postRotation); - if (constrain && _constraint) { - _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); - } _rotationInConstrainedFrame = glm::normalize(targetRotation); _transformChanged = true; _animationPriority = priority; @@ -174,26 +135,15 @@ void JointState::clearTransformTranslation() { _transform[3][1] = 0.0f; _transform[3][2] = 0.0f; _transformChanged = true; - _visibleTransform[3][0] = 0.0f; - _visibleTransform[3][1] = 0.0f; - _visibleTransform[3][2] = 0.0f; } -void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) { +void JointState::applyRotationDelta(const glm::quat& delta, float priority) { // NOTE: delta is in model-frame if (priority < _animationPriority || delta == glm::quat()) { return; } _animationPriority = priority; glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(getRotation()) * delta * getRotation(); - if (!constrain || _constraint == NULL) { - // no constraints - _rotationInConstrainedFrame = targetRotation; - _transformChanged = true; - - _rotation = delta * getRotation(); - return; - } setRotationInConstrainedFrameInternal(targetRotation); } @@ -209,36 +159,17 @@ void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float if (mixFactor > 0.0f && mixFactor <= 1.0f) { targetRotation = safeMix(targetRotation, _defaultRotation, mixFactor); } - if (_constraint) { - _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); - } setRotationInConstrainedFrameInternal(targetRotation); } -void JointState::mixVisibleRotationDelta(const glm::quat& delta, float mixFactor) { - // NOTE: delta is in model-frame - glm::quat targetRotation = _visibleRotationInConstrainedFrame * glm::inverse(_visibleRotation) * delta * _visibleRotation; - if (mixFactor > 0.0f && mixFactor <= 1.0f) { - targetRotation = safeMix(targetRotation, _rotationInConstrainedFrame, mixFactor); - } - setVisibleRotationInConstrainedFrame(targetRotation); -} - glm::quat JointState::computeParentRotation() const { // R = Rp * Rpre * r * Rpost // Rp = R * (Rpre * r * Rpost)^ return getRotation() * glm::inverse(_preRotation * _rotationInConstrainedFrame * _postRotation); } -glm::quat JointState::computeVisibleParentRotation() const { - return _visibleRotation * glm::inverse(_preRotation * _visibleRotationInConstrainedFrame * _postRotation); -} - -void JointState::setRotationInConstrainedFrame(glm::quat targetRotation, float priority, bool constrain, float mix) { +void JointState::setRotationInConstrainedFrame(glm::quat targetRotation, float priority, float mix) { if (priority >= _animationPriority || _animationPriority == 0.0f) { - if (constrain && _constraint) { - _constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f); - } auto rotation = (mix == 1.0f) ? targetRotation : safeMix(getRotationInConstrainedFrame(), targetRotation, mix); setRotationInConstrainedFrameInternal(rotation); _animationPriority = priority; @@ -255,12 +186,6 @@ void JointState::setRotationInConstrainedFrameInternal(const glm::quat& targetRo } } -void JointState::setVisibleRotationInConstrainedFrame(const glm::quat& targetRotation) { - glm::quat parentRotation = computeVisibleParentRotation(); - _visibleRotationInConstrainedFrame = targetRotation; - _visibleRotation = parentRotation * _preRotation * _visibleRotationInConstrainedFrame * _postRotation; -} - bool JointState::rotationIsDefault(const glm::quat& rotation, float tolerance) const { glm::quat defaultRotation = _defaultRotation; return glm::abs(rotation.x - defaultRotation.x) < tolerance && @@ -277,9 +202,3 @@ glm::quat JointState::getDefaultRotationInParentFrame() const { const glm::vec3& JointState::getDefaultTranslationInConstrainedFrame() const { return _translation; } - -void JointState::slaveVisibleTransform() { - _visibleTransform = _transform; - _visibleRotation = getRotation(); - _visibleRotationInConstrainedFrame = _rotationInConstrainedFrame; -} diff --git a/libraries/animation/src/JointState.h b/libraries/animation/src/JointState.h index 07ed010104..eee8863e6f 100644 --- a/libraries/animation/src/JointState.h +++ b/libraries/animation/src/JointState.h @@ -22,8 +22,6 @@ const float DEFAULT_PRIORITY = 3.0f; -class AngularConstraint; - class JointState { public: JointState() {} @@ -39,11 +37,6 @@ public: // but _rotation will be asynchronously extracted void computeTransform(const glm::mat4& parentTransform, bool parentTransformChanged = true, bool synchronousRotationCompute = false); - void computeVisibleTransform(const glm::mat4& parentTransform); - const glm::mat4& getVisibleTransform() const { return _visibleTransform; } - glm::quat getVisibleRotation() const { return _visibleRotation; } - glm::vec3 getVisiblePosition() const { return extractTranslation(_visibleTransform); } - const glm::mat4& getTransform() const { return _transform; } void resetTransformChanged() { _transformChanged = false; } bool getTransformChanged() const { return _transformChanged; } @@ -55,14 +48,13 @@ public: glm::quat getRotationInBindFrame() const; glm::quat getRotationInParentFrame() const; - glm::quat getVisibleRotationInParentFrame() const; const glm::vec3& getPositionInParentFrame() const { return _positionInParentFrame; } float getDistanceToParent() const { return _distanceToParent; } int getParentIndex() const { return _parentIndex; } /// \param delta is in the model-frame - void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f); + void applyRotationDelta(const glm::quat& delta, float priority = 1.0f); /// Applies delta rotation to joint but mixes a little bit of the default pose as well. /// This helps keep an IK solution stable. @@ -70,7 +62,6 @@ public: /// \param mixFactor fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all) /// \param priority priority level of this animation blend void mixRotationDelta(const glm::quat& delta, float mixFactor, float priority = 1.0f); - void mixVisibleRotationDelta(const glm::quat& delta, float mixFactor); /// Blends a fraciton of default pose into joint rotation. /// \param fraction fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all) @@ -80,17 +71,15 @@ public: /// \param rotation is from bind- to model-frame /// computes and sets new _rotationInConstrainedFrame /// NOTE: the JointState's model-frame transform/rotation are NOT updated! - void setRotationInBindFrame(const glm::quat& rotation, float priority, bool constrain = false); + void setRotationInBindFrame(const glm::quat& rotation, float priority); /// \param rotationInModelRame is in model-frame /// computes and sets new _rotationInConstrainedFrame to match rotationInModelFrame /// NOTE: the JointState's model-frame transform/rotation are NOT updated! - void setRotationInModelFrame(const glm::quat& rotationInModelFrame, float priority, bool constrain); + void setRotationInModelFrame(const glm::quat& rotationInModelFrame, float priority); - void setRotationInConstrainedFrame(glm::quat targetRotation, float priority, bool constrain = false, float mix = 1.0f); - void setVisibleRotationInConstrainedFrame(const glm::quat& targetRotation); + void setRotationInConstrainedFrame(glm::quat targetRotation, float priority, float mix = 1.0f); const glm::quat& getRotationInConstrainedFrame() const { return _rotationInConstrainedFrame; } - const glm::quat& getVisibleRotationInConstrainedFrame() const { return _visibleRotationInConstrainedFrame; } bool rotationIsDefault(const glm::quat& rotation, float tolerance = EPSILON) const; @@ -100,15 +89,11 @@ public: void clearTransformTranslation(); - void slaveVisibleTransform(); - /// \return parent model-frame rotation // (used to keep _rotation consistent when modifying _rotationInWorldFrame directly) glm::quat computeParentRotation() const; - glm::quat computeVisibleParentRotation() const; void setTransform(const glm::mat4& transform) { _transform = transform; } - void setVisibleTransform(const glm::mat4& transform) { _visibleTransform = transform; } const glm::vec3& getTranslation() const { return _translation; } const glm::mat4& getPreTransform() const { return _preTransform; } @@ -132,24 +117,17 @@ private: glm::vec3 _positionInParentFrame {0.0f}; // only changes when the Model is scaled float _animationPriority {0.0f}; // the priority of the animation affecting this joint float _distanceToParent {0.0f}; - AngularConstraint* _constraint{nullptr}; // JointState owns its AngularConstraint glm::mat4 _transform; // joint- to model-frame glm::quat _rotation; // joint- to model-frame glm::quat _rotationInConstrainedFrame; // rotation in frame where angular constraints would be applied - glm::mat4 _visibleTransform; - glm::quat _visibleRotation; - glm::quat _visibleRotationInConstrainedFrame; - glm::quat _defaultRotation; // Not necessarilly bind rotation. See FBXJoint transform/bindTransform glm::quat _inverseDefaultRotation; glm::vec3 _translation; QString _name; int _parentIndex; bool _isFree; - glm::vec3 _rotationMin; - glm::vec3 _rotationMax; glm::quat _preRotation; glm::quat _postRotation; glm::mat4 _preTransform; diff --git a/libraries/animation/src/Rig.cpp b/libraries/animation/src/Rig.cpp index 1e512ee767..7866060cf3 100644 --- a/libraries/animation/src/Rig.cpp +++ b/libraries/animation/src/Rig.cpp @@ -224,14 +224,6 @@ void Rig::initJointStates(QVector states, glm::mat4 rootTransform, _rightShoulderJointIndex = rightShoulderJointIndex; initJointTransforms(rootTransform); - - int numStates = _jointStates.size(); - for (int i = 0; i < numStates; ++i) { - _jointStates[i].buildConstraint(); - } - for (int i = 0; i < _jointStates.size(); i++) { - _jointStates[i].slaveVisibleTransform(); - } } // We could build and cache a dictionary, too.... @@ -293,15 +285,6 @@ bool Rig::getJointStateRotation(int index, glm::quat& rotation) const { return !state.rotationIsDefault(rotation); } -bool Rig::getVisibleJointState(int index, glm::quat& rotation) const { - if (index == -1 || index >= _jointStates.size()) { - return false; - } - const JointState& state = _jointStates.at(index); - rotation = state.getVisibleRotationInConstrainedFrame(); - return !state.rotationIsDefault(rotation); -} - void Rig::clearJointState(int index) { if (index != -1 && index < _jointStates.size()) { JointState& state = _jointStates[index]; @@ -392,25 +375,6 @@ bool Rig::getJointCombinedRotation(int jointIndex, glm::quat& result, const glm: return true; } - -bool Rig::getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position, - glm::vec3 translation, glm::quat rotation) const { - if (jointIndex == -1 || jointIndex >= _jointStates.size()) { - return false; - } - // position is in world-frame - position = translation + rotation * _jointStates[jointIndex].getVisiblePosition(); - return true; -} - -bool Rig::getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& result, glm::quat rotation) const { - if (jointIndex == -1 || jointIndex >= _jointStates.size()) { - return false; - } - result = rotation * _jointStates[jointIndex].getVisibleRotation(); - return true; -} - glm::mat4 Rig::getJointTransform(int jointIndex) const { if (jointIndex == -1 || jointIndex >= _jointStates.size()) { return glm::mat4(); @@ -418,13 +382,6 @@ glm::mat4 Rig::getJointTransform(int jointIndex) const { return _jointStates[jointIndex].getTransform(); } -glm::mat4 Rig::getJointVisibleTransform(int jointIndex) const { - if (jointIndex == -1 || jointIndex >= _jointStates.size()) { - return glm::mat4(); - } - return _jointStates[jointIndex].getVisibleTransform(); -} - void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPosition, const glm::vec3& worldVelocity, const glm::quat& worldRotation) { glm::vec3 front = worldRotation * IDENTITY_FRONT; @@ -596,7 +553,7 @@ void Rig::updateAnimations(float deltaTime, glm::mat4 rootTransform) { // copy poses into jointStates const float PRIORITY = 1.0f; for (size_t i = 0; i < poses.size(); i++) { - setJointRotationInConstrainedFrame((int)i, glm::inverse(_animSkeleton->getRelativeBindPose(i).rot) * poses[i].rot, PRIORITY, false, 1.0f); + setJointRotationInConstrainedFrame((int)i, glm::inverse(_animSkeleton->getRelativeBindPose(i).rot) * poses[i].rot, PRIORITY, 1.0f); } } else { @@ -719,7 +676,7 @@ bool Rig::setJointPosition(int jointIndex, const glm::vec3& position, const glm: 1.0f / (combinedWeight + 1.0f)); } } - state.applyRotationDelta(combinedDelta, true, priority); + state.applyRotationDelta(combinedDelta, priority); glm::quat actualDelta = state.getRotation() * glm::inverse(oldCombinedRotation); endPosition = actualDelta * jointVector + jointPosition; if (useRotation) { @@ -838,11 +795,9 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q // Apply the rotation delta. glm::quat oldNextRotation = nextState.getRotation(); - float mixFactor = 0.05f; - nextState.applyRotationDelta(deltaRotation, mixFactor, priority); + nextState.applyRotationDelta(deltaRotation, priority); - // measure the result of the rotation which may have been modified by - // blending and constraints + // measure the result of the rotation which may have been modified by blending glm::quat actualDelta = nextState.getRotation() * glm::inverse(oldNextRotation); endPosition = pivot + actualDelta * leverArm; } @@ -861,7 +816,7 @@ void Rig::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::q } while (numIterations < MAX_ITERATION_COUNT && distanceToGo > ACCEPTABLE_IK_ERROR); // set final rotation of the end joint - endState.setRotationInModelFrame(targetRotation, priority, true); + endState.setRotationInModelFrame(targetRotation, priority); } bool Rig::restoreJointPosition(int jointIndex, float fraction, float priority, const QVector& freeLineage) { @@ -889,13 +844,13 @@ float Rig::getLimbLength(int jointIndex, const QVector& freeLineage, return length; } -glm::quat Rig::setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority, bool constrain) { +glm::quat Rig::setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority) { glm::quat endRotation; if (jointIndex == -1 || _jointStates.isEmpty()) { return endRotation; } JointState& state = _jointStates[jointIndex]; - state.setRotationInBindFrame(rotation, priority, constrain); + state.setRotationInBindFrame(rotation, priority); endRotation = state.getRotationInBindFrame(); return endRotation; } @@ -907,13 +862,13 @@ glm::vec3 Rig::getJointDefaultTranslationInConstrainedFrame(int jointIndex) { return _jointStates[jointIndex].getDefaultTranslationInConstrainedFrame(); } -glm::quat Rig::setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation, float priority, bool constrain, float mix) { +glm::quat Rig::setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation, float priority, float mix) { glm::quat endRotation; if (jointIndex == -1 || _jointStates.isEmpty()) { return endRotation; } JointState& state = _jointStates[jointIndex]; - state.setRotationInConstrainedFrame(targetRotation, priority, constrain, mix); + state.setRotationInConstrainedFrame(targetRotation, priority, mix); endRotation = state.getRotationInConstrainedFrame(); return endRotation; } @@ -926,30 +881,17 @@ bool Rig::getJointRotationInConstrainedFrame(int jointIndex, glm::quat& quatOut) return true; } -void Rig::updateVisibleJointStates() { - for (int i = 0; i < _jointStates.size(); i++) { - _jointStates[i].slaveVisibleTransform(); - } -} - void Rig::clearJointStatePriorities() { for (int i = 0; i < _jointStates.size(); i++) { _jointStates[i].setAnimationPriority(0.0f); } } -void Rig::setJointVisibleTransform(int jointIndex, glm::mat4 newTransform) { - if (jointIndex == -1 || jointIndex >= _jointStates.size()) { - return; - } - _jointStates[jointIndex].setVisibleTransform(newTransform); -} - -void Rig::applyJointRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, float priority) { +void Rig::applyJointRotationDelta(int jointIndex, const glm::quat& delta, float priority) { if (jointIndex == -1 || _jointStates.isEmpty()) { return; } - _jointStates[jointIndex].applyRotationDelta(delta, constrain, priority); + _jointStates[jointIndex].applyRotationDelta(delta, priority); } glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) { diff --git a/libraries/animation/src/Rig.h b/libraries/animation/src/Rig.h index 6dad58db87..8ddc0c9f6d 100644 --- a/libraries/animation/src/Rig.h +++ b/libraries/animation/src/Rig.h @@ -129,7 +129,7 @@ public: void clearJointTransformTranslation(int jointIndex); void reset(const QVector& fbxJoints); bool getJointStateRotation(int index, glm::quat& rotation) const; - void applyJointRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, float priority); + void applyJointRotationDelta(int jointIndex, const glm::quat& delta, float priority); JointState getJointState(int jointIndex) const; // XXX bool getVisibleJointState(int index, glm::quat& rotation) const; void clearJointState(int index); @@ -165,10 +165,10 @@ public: float getLimbLength(int jointIndex, const QVector& freeLineage, const glm::vec3 scale, const QVector& fbxJoints) const; - glm::quat setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority, bool constrain = false); + glm::quat setJointRotationInBindFrame(int jointIndex, const glm::quat& rotation, float priority); glm::vec3 getJointDefaultTranslationInConstrainedFrame(int jointIndex); glm::quat setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation, - float priority, bool constrain = false, float mix = 1.0f); + float priority, float mix = 1.0f); bool getJointRotationInConstrainedFrame(int jointIndex, glm::quat& rotOut) const; glm::quat getJointDefaultRotationInParentFrame(int jointIndex); void updateVisibleJointStates(); diff --git a/libraries/physics/src/Constraint.h b/libraries/physics/src/Constraint.h deleted file mode 100644 index ed97d6cc73..0000000000 --- a/libraries/physics/src/Constraint.h +++ /dev/null @@ -1,25 +0,0 @@ -// -// Constraint.h -// libraries/physics/src -// -// Created by Andrew Meadows 2014.07.24 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Constraint_h -#define hifi_Constraint_h - -class Constraint { -public: - Constraint() {} - virtual ~Constraint() {} - - /// Enforce contraint by moving relevant points. - /// \return max distance of point movement - virtual float enforce() = 0; -}; - -#endif // hifi_Constraint_h diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 2f16259f89..90dbe6524c 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -68,7 +68,6 @@ Model::Model(RigPointer rig, QObject* parent) : _scaledToFit(false), _snapModelToRegistrationPoint(false), _snappedToRegistrationPoint(false), - _showTrueJointTransforms(true), _cauterizeBones(false), _pupilDilation(0.0f), _url(HTTP_INVALID_COM), @@ -998,10 +997,6 @@ bool Model::getJointState(int index, glm::quat& rotation) const { return _rig->getJointStateRotation(index, rotation); } -bool Model::getVisibleJointState(int index, glm::quat& rotation) const { - return _rig->getVisibleJointState(index, rotation); -} - void Model::clearJointState(int index) { _rig->clearJointState(index); } @@ -1083,14 +1078,6 @@ bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const return _rig->getJointCombinedRotation(jointIndex, rotation, _rotation); } -bool Model::getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const { - return _rig->getVisibleJointPositionInWorldFrame(jointIndex, position, _translation, _rotation); -} - -bool Model::getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const { - return _rig->getVisibleJointRotationInWorldFrame(jointIndex, rotation, _rotation); -} - QStringList Model::getJointNames() const { if (QThread::currentThread() != thread()) { QStringList result; @@ -1294,33 +1281,17 @@ void Model::updateClusterMatrices() { for (int i = 0; i < _meshStates.size(); i++) { MeshState& state = _meshStates[i]; const FBXMesh& mesh = geometry.meshes.at(i); - if (_showTrueJointTransforms) { - for (int j = 0; j < mesh.clusters.size(); j++) { - const FBXCluster& cluster = mesh.clusters.at(j); - auto jointMatrix = _rig->getJointTransform(cluster.jointIndex); - state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix; + for (int j = 0; j < mesh.clusters.size(); j++) { + const FBXCluster& cluster = mesh.clusters.at(j); + auto jointMatrix = _rig->getJointTransform(cluster.jointIndex); + state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix; - // as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty. - if (!_cauterizeBoneSet.empty()) { - if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) { - jointMatrix = cauterizeMatrix; - } - state.cauterizedClusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix; - } - } - } else { - for (int j = 0; j < mesh.clusters.size(); j++) { - const FBXCluster& cluster = mesh.clusters.at(j); - auto jointMatrix = _rig->getJointVisibleTransform(cluster.jointIndex); // differs from above only in using get...VisibleTransform - state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix; - - // as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty. - if (!_cauterizeBoneSet.empty()) { - if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) { - jointMatrix = cauterizeMatrix; - } - state.cauterizedClusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix; + // as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty. + if (!_cauterizeBoneSet.empty()) { + if (_cauterizeBoneSet.find(cluster.jointIndex) != _cauterizeBoneSet.end()) { + jointMatrix = cauterizeMatrix; } + state.cauterizedClusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix; } } } @@ -1533,13 +1504,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, int shape pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, args, locations); - { - if (!_showTrueJointTransforms) { - PerformanceTimer perfTimer("_rig->updateVisibleJointStates()"); - _rig->updateVisibleJointStates(); - } // else no need to update visible transforms - } - // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown // to false to rebuild out mesh groups. if (meshIndex < 0 || meshIndex >= (int)networkMeshes.size() || meshIndex > geometry.meshes.size()) { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index e069b10954..2620310857 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -221,26 +221,17 @@ protected: /// \return whether or not the joint state is "valid" (that is, non-default) bool getJointState(int index, glm::quat& rotation) const; - /// Fetches the visible joint state at the specified index. - /// \return whether or not the joint state is "valid" (that is, non-default) - bool getVisibleJointState(int index, glm::quat& rotation) const; - /// Clear the joint states void clearJointState(int index); /// Returns the index of the last free ancestor of the indexed joint, or -1 if not found. int getLastFreeJointIndex(int jointIndex) const; - bool getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const; - bool getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const; - /// \param jointIndex index of joint in model structure /// \param position[out] position of joint in model-frame /// \return true if joint exists bool getJointPosition(int jointIndex, glm::vec3& position) const; - void setShowTrueJointTransforms(bool show) { _showTrueJointTransforms = show; } - QSharedPointer _geometry; void setGeometry(const QSharedPointer& newGeometry); @@ -259,8 +250,6 @@ protected: bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point glm::vec3 _registrationPoint = glm::vec3(0.5f); /// the point in model space our center is snapped to - bool _showTrueJointTransforms; - class MeshState { public: QVector clusterMatrices; diff --git a/libraries/shared/src/AngularConstraint.cpp b/libraries/shared/src/AngularConstraint.cpp deleted file mode 100644 index 62cdca67fd..0000000000 --- a/libraries/shared/src/AngularConstraint.cpp +++ /dev/null @@ -1,202 +0,0 @@ -// -// AngularConstraint.cpp -// interface/src/renderer -// -// Created by Andrew Meadows on 2014.05.30 -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include - -#include "AngularConstraint.h" -#include "GLMHelpers.h" -#include "NumericalConstants.h" - -// helper function -/// \param angle radian angle to be clamped within angleMin and angleMax -/// \param angleMin minimum value -/// \param angleMax maximum value -/// \return value between minAngle and maxAngle closest to angle -float clampAngle(float angle, float angleMin, float angleMax) { - float minDistance = angle - angleMin; - float maxDistance = angle - angleMax; - if (maxDistance > 0.0f) { - minDistance = glm::min(minDistance, angleMin + TWO_PI - angle); - angle = (minDistance < maxDistance) ? angleMin : angleMax; - } else if (minDistance < 0.0f) { - maxDistance = glm::max(maxDistance, angleMax - TWO_PI - angle); - angle = (minDistance > maxDistance) ? angleMin : angleMax; - } - return angle; -} - -// static -AngularConstraint* AngularConstraint::newAngularConstraint(const glm::vec3& minAngles, const glm::vec3& maxAngles) { - float minDistance2 = glm::distance2(minAngles, glm::vec3(-PI, -PI, -PI)); - float maxDistance2 = glm::distance2(maxAngles, glm::vec3(PI, PI, PI)); - if (minDistance2 < EPSILON && maxDistance2 < EPSILON) { - // no constraint - return NULL; - } - // count the zero length elements - glm::vec3 rangeAngles = maxAngles - minAngles; - int pivotIndex = -1; - int numZeroes = 0; - for (int i = 0; i < 3; ++i) { - if (rangeAngles[i] < EPSILON) { - ++numZeroes; - } else { - pivotIndex = i; - } - } - if (numZeroes == 2) { - // this is a hinge - int forwardIndex = (pivotIndex + 1) % 3; - glm::vec3 forwardAxis(0.0f); - forwardAxis[forwardIndex] = 1.0f; - glm::vec3 rotationAxis(0.0f); - rotationAxis[pivotIndex] = 1.0f; - return new HingeConstraint(forwardAxis, rotationAxis, minAngles[pivotIndex], maxAngles[pivotIndex]); - } else if (numZeroes == 0) { - // approximate the angular limits with a cone roller - // we assume the roll is about z - glm::vec3 middleAngles = 0.5f * (maxAngles + minAngles); - glm::quat yaw = glm::angleAxis(middleAngles[1], glm::vec3(0.0f, 1.0f, 0.0f)); - glm::quat pitch = glm::angleAxis(middleAngles[0], glm::vec3(1.0f, 0.0f, 0.0f)); - glm::vec3 coneAxis = pitch * yaw * glm::vec3(0.0f, 0.0f, 1.0f); - // the coneAngle is half the average range of the two non-roll rotations - glm::vec3 range = maxAngles - minAngles; - float coneAngle = 0.25f * (range[0] + range[1]); - return new ConeRollerConstraint(coneAngle, coneAxis, minAngles.z, maxAngles.z); - } - return NULL; -} - -bool AngularConstraint::softClamp(glm::quat& targetRotation, const glm::quat& oldRotation, float mixFraction) { - glm::quat clampedTarget = targetRotation; - bool clamped = clamp(clampedTarget); - if (clamped) { - // check if oldRotation is also clamped - glm::quat clampedOld = oldRotation; - bool clamped2 = clamp(clampedOld); - if (clamped2) { - // oldRotation is already beyond the constraint - // we clamp again midway between targetRotation and clamped oldPosition - clampedTarget = glm::shortMix(clampedOld, targetRotation, mixFraction); - // and then clamp that - clamp(clampedTarget); - } - // finally we mix targetRotation with the clampedTarget - targetRotation = glm::shortMix(clampedTarget, targetRotation, mixFraction); - } - return clamped; -} - -HingeConstraint::HingeConstraint(const glm::vec3& forwardAxis, const glm::vec3& rotationAxis, float minAngle, float maxAngle) - : _minAngle(minAngle), _maxAngle(maxAngle) { - assert(_minAngle < _maxAngle); - // we accept the rotationAxis direction - assert(glm::length(rotationAxis) > EPSILON); - _rotationAxis = glm::normalize(rotationAxis); - // but we compute the final _forwardAxis - glm::vec3 otherAxis = glm::cross(_rotationAxis, forwardAxis); - assert(glm::length(otherAxis) > EPSILON); - _forwardAxis = glm::normalize(glm::cross(otherAxis, _rotationAxis)); -} - -// virtual -bool HingeConstraint::clamp(glm::quat& rotation) const { - glm::vec3 forward = rotation * _forwardAxis; - forward -= glm::dot(forward, _rotationAxis) * _rotationAxis; - float length = glm::length(forward); - if (length < EPSILON) { - // infinite number of solutions ==> choose the middle of the contrained range - rotation = glm::angleAxis(0.5f * (_minAngle + _maxAngle), _rotationAxis); - return true; - } - forward /= length; - float sign = (glm::dot(glm::cross(_forwardAxis, forward), _rotationAxis) > 0.0f ? 1.0f : -1.0f); - //float angle = sign * acos(glm::dot(forward, _forwardAxis) / length); - float angle = sign * acosf(glm::dot(forward, _forwardAxis)); - glm::quat newRotation = glm::angleAxis(clampAngle(angle, _minAngle, _maxAngle), _rotationAxis); - if (fabsf(1.0f - glm::dot(newRotation, rotation)) > EPSILON * EPSILON) { - rotation = newRotation; - return true; - } - return false; -} - -bool HingeConstraint::softClamp(glm::quat& targetRotation, const glm::quat& oldRotation, float mixFraction) { - // the hinge works best without a soft clamp - return clamp(targetRotation); -} - -ConeRollerConstraint::ConeRollerConstraint(float coneAngle, const glm::vec3& coneAxis, float minRoll, float maxRoll) - : _coneAngle(coneAngle), _minRoll(minRoll), _maxRoll(maxRoll) { - assert(_maxRoll >= _minRoll); - float axisLength = glm::length(coneAxis); - assert(axisLength > EPSILON); - _coneAxis = coneAxis / axisLength; -} - -// virtual -bool ConeRollerConstraint::clamp(glm::quat& rotation) const { - bool applied = false; - glm::vec3 rotatedAxis = rotation * _coneAxis; - glm::vec3 perpAxis = glm::cross(rotatedAxis, _coneAxis); - float perpAxisLength = glm::length(perpAxis); - if (perpAxisLength > EPSILON) { - perpAxis /= perpAxisLength; - // enforce the cone - float angle = acosf(glm::dot(rotatedAxis, _coneAxis)); - if (angle > _coneAngle) { - rotation = glm::angleAxis(angle - _coneAngle, perpAxis) * rotation; - rotatedAxis = rotation * _coneAxis; - applied = true; - } - } else { - // the rotation is 100% roll - // there is no obvious perp axis so we must pick one - perpAxis = rotatedAxis; - // find the first non-zero element: - float iValue = 0.0f; - int i = 0; - for (i = 0; i < 3; ++i) { - if (fabsf(perpAxis[i]) > EPSILON) { - iValue = perpAxis[i]; - break; - } - } - assert(i != 3); - // swap or negate the next element - int j = (i + 1) % 3; - float jValue = perpAxis[j]; - if (fabsf(jValue - iValue) > EPSILON) { - perpAxis[i] = jValue; - perpAxis[j] = iValue; - } else { - perpAxis[i] = -iValue; - } - perpAxis = glm::cross(perpAxis, rotatedAxis); - perpAxisLength = glm::length(perpAxis); - assert(perpAxisLength > EPSILON); - perpAxis /= perpAxisLength; - } - // measure the roll - // NOTE: perpAxis is perpendicular to both _coneAxis and rotatedConeAxis, so we can - // rotate it again and we'll end up with an something that has only been rolled. - glm::vec3 rolledPerpAxis = rotation * perpAxis; - float sign = glm::dot(rotatedAxis, glm::cross(perpAxis, rolledPerpAxis)) > 0.0f ? 1.0f : -1.0f; - float roll = sign * angleBetween(rolledPerpAxis, perpAxis); - if (roll < _minRoll || roll > _maxRoll) { - float clampedRoll = clampAngle(roll, _minRoll, _maxRoll); - rotation = glm::normalize(glm::angleAxis(clampedRoll - roll, rotatedAxis) * rotation); - applied = true; - } - return applied; -} - - diff --git a/libraries/shared/src/AngularConstraint.h b/libraries/shared/src/AngularConstraint.h deleted file mode 100644 index 74d3fdb82b..0000000000 --- a/libraries/shared/src/AngularConstraint.h +++ /dev/null @@ -1,54 +0,0 @@ -// -// AngularConstraint.h -// interface/src/renderer -// -// Created by Andrew Meadows on 2014.05.30 -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_AngularConstraint_h -#define hifi_AngularConstraint_h - -#include - -class AngularConstraint { -public: - /// \param minAngles minumum euler angles for the constraint - /// \param maxAngles minumum euler angles for the constraint - /// \return pointer to new AngularConstraint of the right type or NULL if none could be made - static AngularConstraint* newAngularConstraint(const glm::vec3& minAngles, const glm::vec3& maxAngles); - - AngularConstraint() {} - virtual ~AngularConstraint() {} - virtual bool clamp(glm::quat& rotation) const = 0; - virtual bool softClamp(glm::quat& targetRotation, const glm::quat& oldRotation, float mixFraction); -protected: -}; - -class HingeConstraint : public AngularConstraint { -public: - HingeConstraint(const glm::vec3& forwardAxis, const glm::vec3& rotationAxis, float minAngle, float maxAngle); - virtual bool clamp(glm::quat& rotation) const; - virtual bool softClamp(glm::quat& targetRotation, const glm::quat& oldRotation, float mixFraction); -protected: - glm::vec3 _forwardAxis; - glm::vec3 _rotationAxis; - float _minAngle; - float _maxAngle; -}; - -class ConeRollerConstraint : public AngularConstraint { -public: - ConeRollerConstraint(float coneAngle, const glm::vec3& coneAxis, float minRoll, float maxRoll); - virtual bool clamp(glm::quat& rotation) const; -private: - float _coneAngle; - glm::vec3 _coneAxis; - float _minRoll; - float _maxRoll; -}; - -#endif // hifi_AngularConstraint_h From 4a7e3c66bd80eb1dbe2b6dc6ad7b2151d0276e9f Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Thu, 1 Oct 2015 15:05:25 -0700 Subject: [PATCH 31/36] Update createPingPongGun.js use relative paths --- examples/toys/ping_pong_gun/createPingPongGun.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/toys/ping_pong_gun/createPingPongGun.js b/examples/toys/ping_pong_gun/createPingPongGun.js index d8509d8a63..4b7ed27643 100644 --- a/examples/toys/ping_pong_gun/createPingPongGun.js +++ b/examples/toys/ping_pong_gun/createPingPongGun.js @@ -9,8 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // /*global MyAvatar, Entities, AnimationCache, SoundCache, Scene, Camera, Overlays, HMD, AvatarList, AvatarManager, Controller, UndoStack, Window, Account, GlobalServices, Script, ScriptDiscoveryService, LODManager, Menu, Vec3, Quat, AudioDevice, Paths, Clipboard, Settings, XMLHttpRequest, randFloat, randInt */ -Script.include("https://hifi-public.s3.amazonaws.com/scripts/utilities.js"); - +Script.include("../../utilities.js"); var scriptURL = Script.resolvePath('pingPongGun.js'); @@ -41,4 +40,4 @@ var pingPongGun = Entities.addEntity({ function cleanUp() { Entities.deleteEntity(pingPongGun); } -Script.scriptEnding.connect(cleanUp); \ No newline at end of file +Script.scriptEnding.connect(cleanUp); From e56d2d9b434622a63e1485ea5e16b945202d2ba6 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 1 Oct 2015 15:48:37 -0700 Subject: [PATCH 32/36] Add asserts --- libraries/shared/src/Interpolate.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/shared/src/Interpolate.cpp b/libraries/shared/src/Interpolate.cpp index bc18c087ad..7acc0c8cbd 100644 --- a/libraries/shared/src/Interpolate.cpp +++ b/libraries/shared/src/Interpolate.cpp @@ -11,14 +11,18 @@ #include "Interpolate.h" +#include #include float Interpolate::bezierInterpolate(float y1, float y2, float y3, float u) { // https://en.wikipedia.org/wiki/Bezier_curve + assert(0.0f <= u && u <= 1.0f); return (1.0f - u) * (1.0f - u) * y1 + 2.0f * (1.0f - u) * u * y2 + u * u * y3; } float Interpolate::interpolate3Points(float y1, float y2, float y3, float u) { + assert(0.0f <= u && u <= 1.0f); + if (u <= 0.5f && y1 == y2 || u >= 0.5f && y2 == y3) { // Flat line. return y2; From 98fe06be578b5c29c72654bab8369457dee1c944 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 2 Oct 2015 09:30:18 -0700 Subject: [PATCH 33/36] cleanup sixense/hydra calibration --- .../src/input-plugins/SixenseManager.cpp | 114 +++++------------- .../src/input-plugins/SixenseManager.h | 4 +- 2 files changed, 32 insertions(+), 86 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index 9bc3a71fd5..dbacc23f26 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -13,11 +13,12 @@ #include -#include +#include #include +#include +#include #include "NumericalConstants.h" -#include #include "SixenseManager.h" #include "UserActivityLogger.h" @@ -38,14 +39,12 @@ const unsigned int RIGHT_MASK = 1U << 1; 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; +const int CALIBRATION_STATE_COMPLETE = 2; -// default (expected) location of neck in sixense space -const float NECK_X = 0.25f; // meters -const float NECK_Y = 0.3f; // meters -const float NECK_Z = 0.3f; // meters +// default (expected) location of neck in sixense space when sitting +const float NECK_X = -0.25f; // meters +const float NECK_Y = -0.35f; // meters +const float NECK_Z = -0.3f; // meters const float CONTROLLER_THRESHOLD = 0.35f; @@ -92,9 +91,9 @@ bool SixenseManager::isSupported() const { void SixenseManager::activate() { #ifdef HAVE_SIXENSE _calibrationState = CALIBRATION_STATE_IDLE; - // By default we assume the _neckBase (in orb frame) is as high above the orb + // By default we assume the _avatarPosition (in orb frame) is as high above the orb // as the "torso" is below it. - _neckBase = glm::vec3(NECK_X, -NECK_Y, NECK_Z); + _avatarPosition = glm::vec3(NECK_X, NECK_Y, NECK_Z); CONTAINER->addMenu(MENU_PATH); CONTAINER->addMenuItem(MENU_PATH, TOGGLE_SMOOTH, @@ -258,11 +257,13 @@ void SixenseManager::update(float deltaTime, bool jointsCaptured) { #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 +// (1) reach arm straight out to the sides (xAxis is to the left) +// (2) press BUTTON_FWD on both hands and hold for one second +// (3) release both BUTTON_FWDs +// +// The code will: +// (4) assume that the orb is on a flat surface (yAxis is UP) +// (5) compute the forward direction (zAxis = xAxis cross yAxis) const float MINIMUM_ARM_REACH = 0.3f; // meters const float MAXIMUM_NOISE_LEVEL = 0.05f; // meters @@ -279,21 +280,16 @@ void SixenseManager::updateCalibration(void* controllersX) { 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 + _avatarPosition = - 0.5f * (_reachLeft + _reachRight); // neck is midway between right and left hands glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft); - glm::vec3 yAxis(0.0f, 1.0f, 0.0f); - 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))); + glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, Vectors::UNIT_Y)); + xAxis = glm::normalize(glm::cross(Vectors::UNIT_Y, zAxis)); + _avatarRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, Vectors::UNIT_Y, zAxis))); + const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f; + _avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR; qCDebug(inputplugins, "succeess: sixense calibration"); } break; @@ -349,54 +345,10 @@ void SixenseManager::updateCalibration(void* controllersX) { _lockExpiry = now + LOCK_DURATION; _lastDistance = 0.0f; _reachUp = 0.5f * (_reachLeft + _reachRight); - _calibrationState = CALIBRATION_STATE_Y; + _calibrationState = CALIBRATION_STATE_COMPLETE; qCDebug(inputplugins, "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 (fabsf(distance) > fabsf(_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.0f; - _lockExpiry = now + LOCK_DURATION; - _calibrationState = CALIBRATION_STATE_Z; - qCDebug(inputplugins, "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.0f, 1.0f, 0.0f); - 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 (fabsf(_lastDistance) > 0.05f * MINIMUM_ARM_REACH) { - // lock has expired so clamp the data and move on - _calibrationState = CALIBRATION_STATE_COMPLETE; - qCDebug(inputplugins, "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 @@ -456,12 +408,9 @@ void SixenseManager::handlePoseEvent(glm::vec3 position, glm::quat rotation, int // z // Transform the measured position into body frame. - glm::vec3 neck = _neckBase; - // Set y component of the "neck" to raise the measured position a little bit. - neck.y = 0.5f; - position = _orbRotation * (position - neck); + position = _avatarRotation * (position + _avatarPosition); - // From ABOVE the hand canonical axes looks like this: + // From ABOVE the hand canonical axes look like this: // // | | | | y | | | | // | | | | | | | | | @@ -480,28 +429,25 @@ void SixenseManager::handlePoseEvent(glm::vec3 position, glm::quat rotation, int // // Qsh = angleAxis(PI, zAxis) * angleAxis(-PI/2, xAxis) // - const glm::vec3 xAxis = glm::vec3(1.0f, 0.0f, 0.0f); - const glm::vec3 yAxis = glm::vec3(0.0f, 1.0f, 0.0f); - const glm::vec3 zAxis = glm::vec3(0.0f, 0.0f, 1.0f); - const glm::quat sixenseToHand = glm::angleAxis(PI, zAxis) * glm::angleAxis(-PI/2.0f, xAxis); + const glm::quat sixenseToHand = glm::angleAxis(PI, Vectors::UNIT_Z) * glm::angleAxis(-PI/2.0f, Vectors::UNIT_X); // In addition to Qsh each hand has pre-offset introduced by the shape of the sixense controllers // and how they fit into the hand in their relaxed state. This offset is a quarter turn about // the sixense's z-axis, with its direction different for the two hands: float sign = (index == 0) ? 1.0f : -1.0f; - const glm::quat preOffset = glm::angleAxis(sign * PI / 2.0f, zAxis); + const glm::quat preOffset = glm::angleAxis(sign * PI / 2.0f, Vectors::UNIT_Z); // Finally, there is a post-offset (same for both hands) to get the hand's rest orientation // (fingers forward, palm down) aligned properly in the avatar's model-frame, // and then a flip about the yAxis to get into model-frame. - const glm::quat postOffset = glm::angleAxis(PI, yAxis) * glm::angleAxis(PI / 2.0f, xAxis); + const glm::quat postOffset = glm::angleAxis(PI, Vectors::UNIT_Y) * glm::angleAxis(PI / 2.0f, Vectors::UNIT_X); // The total rotation of the hand uses the formula: // // rotation = postOffset * Qsh^ * (measuredRotation * preOffset) * Qsh // // TODO: find a shortcut with fewer rotations. - rotation = postOffset * glm::inverse(sixenseToHand) * rotation * preOffset * sixenseToHand; + rotation = _avatarRotation * postOffset * glm::inverse(sixenseToHand) * rotation * preOffset * sixenseToHand; _poseStateMap[makeInput(JointChannel(index)).getChannel()] = UserInputMapper::PoseValue(position, rotation); #endif // HAVE_SIXENSE diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index 03482287d9..c1cc7049af 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -97,8 +97,8 @@ private: 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 + glm::vec3 _avatarPosition; // in hydra-frame + glm::quat _avatarRotation; // rotation of avatar in orb-frame float _armLength; // these are measured values used to compute the calibration results From 940b8eb529c0c7fa4f9713579bd23e2776add657 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 2 Oct 2015 09:39:13 -0700 Subject: [PATCH 34/36] improve some variable names --- .../input-plugins/src/input-plugins/SixenseManager.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index dbacc23f26..403eee2d87 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -41,10 +41,7 @@ const int CALIBRATION_STATE_IDLE = 0; const int CALIBRATION_STATE_X = 1; const int CALIBRATION_STATE_COMPLETE = 2; -// default (expected) location of neck in sixense space when sitting -const float NECK_X = -0.25f; // meters -const float NECK_Y = -0.35f; // meters -const float NECK_Z = -0.3f; // meters +const glm::vec3 DEFAULT_AVATAR_POSITION(-0.25f, -0.35f, -0.3f); // in hydra frame const float CONTROLLER_THRESHOLD = 0.35f; @@ -93,7 +90,7 @@ void SixenseManager::activate() { _calibrationState = CALIBRATION_STATE_IDLE; // By default we assume the _avatarPosition (in orb frame) is as high above the orb // as the "torso" is below it. - _avatarPosition = glm::vec3(NECK_X, NECK_Y, NECK_Z); + _avatarPosition = DEFAULT_AVATAR_POSITION; CONTAINER->addMenu(MENU_PATH); CONTAINER->addMenuItem(MENU_PATH, TOGGLE_SMOOTH, From 50b2c8ae3796282ed80ab9924d8501e7539d084f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 2 Oct 2015 09:39:34 -0700 Subject: [PATCH 35/36] remove warnings in linux --- libraries/shared/src/Interpolate.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/Interpolate.cpp b/libraries/shared/src/Interpolate.cpp index 7acc0c8cbd..bef69c9a33 100644 --- a/libraries/shared/src/Interpolate.cpp +++ b/libraries/shared/src/Interpolate.cpp @@ -23,12 +23,12 @@ float Interpolate::bezierInterpolate(float y1, float y2, float y3, float u) { float Interpolate::interpolate3Points(float y1, float y2, float y3, float u) { assert(0.0f <= u && u <= 1.0f); - if (u <= 0.5f && y1 == y2 || u >= 0.5f && y2 == y3) { + if ((u <= 0.5f && y1 == y2) || (u >= 0.5f && y2 == y3)) { // Flat line. return y2; } - if (y2 >= y1 && y2 >= y3 || y2 <= y1 && y2 <= y3) { + if ((y2 >= y1 && y2 >= y3) || (y2 <= y1 && y2 <= y3)) { // U or inverted-U shape. // Make the slope at y2 = 0, which means that the control points half way between the value points have the value y2. if (u <= 0.5f) { From e9c71f38677cb4ba08d917d5e3bb5687b0d67812 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 2 Oct 2015 10:02:12 -0700 Subject: [PATCH 36/36] cleanup comments --- libraries/input-plugins/src/input-plugins/SixenseManager.cpp | 2 -- libraries/input-plugins/src/input-plugins/SixenseManager.h | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp index 403eee2d87..aa04c49adb 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.cpp +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.cpp @@ -88,8 +88,6 @@ bool SixenseManager::isSupported() const { void SixenseManager::activate() { #ifdef HAVE_SIXENSE _calibrationState = CALIBRATION_STATE_IDLE; - // By default we assume the _avatarPosition (in orb frame) is as high above the orb - // as the "torso" is below it. _avatarPosition = DEFAULT_AVATAR_POSITION; CONTAINER->addMenu(MENU_PATH); diff --git a/libraries/input-plugins/src/input-plugins/SixenseManager.h b/libraries/input-plugins/src/input-plugins/SixenseManager.h index c1cc7049af..22340cfc95 100644 --- a/libraries/input-plugins/src/input-plugins/SixenseManager.h +++ b/libraries/input-plugins/src/input-plugins/SixenseManager.h @@ -97,8 +97,8 @@ private: int _calibrationState; // these are calibration results - glm::vec3 _avatarPosition; // in hydra-frame - glm::quat _avatarRotation; // rotation of avatar in orb-frame + glm::vec3 _avatarPosition; // in hydra-frame + glm::quat _avatarRotation; // in hydra-frame float _armLength; // these are measured values used to compute the calibration results