mirror of
https://github.com/lubosz/overte.git
synced 2025-08-27 15:46:39 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into controllers
This commit is contained in:
commit
25d67656e9
21 changed files with 1171 additions and 79 deletions
|
@ -73,24 +73,20 @@ void ScriptableAvatar::update(float deltatime) {
|
|||
const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(currentFrame) % frameCount);
|
||||
const float frameFraction = glm::fract(currentFrame);
|
||||
|
||||
for (int i = 0; i < modelJoints.size(); i++) {
|
||||
int mapping = animationJoints.indexOf(modelJoints[i]);
|
||||
if (mapping != -1 && !_maskedJoints.contains(modelJoints[i])) {
|
||||
JointData& data = _jointData[i];
|
||||
for (int i = 0; i < animationJoints.size(); i++) {
|
||||
const QString& name = animationJoints[i];
|
||||
int mapping = getJointIndex(name);
|
||||
if (mapping != -1 && !_maskedJoints.contains(name)) {
|
||||
JointData& data = _jointData[mapping];
|
||||
|
||||
auto newRotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);
|
||||
auto newTranslation = floorFrame.translations.at(i) * (1.0f - frameFraction) +
|
||||
ceilFrame.translations.at(i) * frameFraction;
|
||||
|
||||
// We could probably do translations as in interpolation in model space (rather than the parent space that each frame is in),
|
||||
// but we don't do so for MyAvatar yet, so let's not be different here.
|
||||
if (data.rotation != newRotation) {
|
||||
data.rotation = newRotation;
|
||||
data.rotationSet = true;
|
||||
}
|
||||
if (data.translation != newTranslation) {
|
||||
data.translation = newTranslation;
|
||||
data.translationSet = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_animation.clear();
|
||||
|
|
29
examples/acScripts/animatedAvatarAgent.js
Normal file
29
examples/acScripts/animatedAvatarAgent.js
Normal file
|
@ -0,0 +1,29 @@
|
|||
"use strict";
|
||||
/*jslint vars: true, plusplus: true*/
|
||||
/*global Agent, Avatar, Script, Entities, Vec3, print*/
|
||||
//
|
||||
// animatedAvatar.js
|
||||
// examples/acScripts
|
||||
//
|
||||
// Created by Howard Stearns 11/6/15
|
||||
// Copyright 2015 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
|
||||
//
|
||||
// An assignment client script that animates one avatar at random location within 'spread' meters of 'origin'.
|
||||
// In Domain Server Settings, go to scripts and give the url of this script. Press '+', and then 'Save and restart'.
|
||||
|
||||
var origin = {x: 500, y: 502, z: 500};
|
||||
var spread = 10; // meters
|
||||
var animationData = {url: "https://hifi-public.s3.amazonaws.com/ozan/anim/standard_anims/walk_fwd.fbx", lastFrame: 35};
|
||||
Avatar.skeletonModelURL = "https://hifi-public.s3.amazonaws.com/marketplace/contents/dd03b8e3-52fb-4ab3-9ac9-3b17e00cd85d/98baa90b3b66803c5d7bd4537fca6993.fst"; //lovejoy
|
||||
Avatar.displayName = "'Bot";
|
||||
var millisecondsToWaitBeforeStarting = 10 * 1000; // To give the various servers a chance to start.
|
||||
|
||||
Agent.isAvatar = true;
|
||||
Script.setTimeout(function () {
|
||||
Avatar.position = Vec3.sum(origin, {x: Math.random() * spread, y: 0, z: Math.random() * spread});
|
||||
print("Starting at", JSON.stringify(Avatar.position));
|
||||
Avatar.startAnimation(animationData.url, animationData.fps || 30, 1, true, false, animationData.firstFrame || 0, animationData.lastFrame);
|
||||
}, millisecondsToWaitBeforeStarting);
|
|
@ -1,39 +1,36 @@
|
|||
|
||||
|
||||
|
||||
if (typeof String.prototype.fileName !== "function") {
|
||||
String.prototype.fileName = function () {
|
||||
String.prototype.fileName = function() {
|
||||
return this.replace(/^(.*[\/\\])*/, "");
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof String.prototype.fileBase !== "function") {
|
||||
String.prototype.fileBase = function () {
|
||||
String.prototype.fileBase = function() {
|
||||
var filename = this.fileName();
|
||||
return filename.slice(0, filename.indexOf("."));
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof String.prototype.fileType !== "function") {
|
||||
String.prototype.fileType = function () {
|
||||
String.prototype.fileType = function() {
|
||||
return this.slice(this.lastIndexOf(".") + 1);
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof String.prototype.path !== "function") {
|
||||
String.prototype.path = function () {
|
||||
String.prototype.path = function() {
|
||||
return this.replace(/[\\\/][^\\\/]*$/, "");
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof String.prototype.regExpEscape !== "function") {
|
||||
String.prototype.regExpEscape = function () {
|
||||
String.prototype.regExpEscape = function() {
|
||||
return this.replace(/([$\^.+*?|\\\/{}()\[\]])/g, '\\$1');
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof String.prototype.toArrayBuffer !== "function") {
|
||||
String.prototype.toArrayBuffer = function () {
|
||||
String.prototype.toArrayBuffer = function() {
|
||||
var length,
|
||||
buffer,
|
||||
view,
|
||||
|
@ -64,3 +61,416 @@ if (typeof String.prototype.toArrayBuffer !== "function") {
|
|||
return buffer;
|
||||
};
|
||||
}
|
||||
// Copyright Mathias Bynens <https://mathiasbynens.be/>
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining
|
||||
// a copy of this software and associated documentation files (the
|
||||
// "Software"), to deal in the Software without restriction, including
|
||||
// without limitation the rights to use, copy, modify, merge, publish,
|
||||
// distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to
|
||||
// the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be
|
||||
// included in all copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
/*! https://mths.be/includes v1.0.0 by @mathias */
|
||||
if (!String.prototype.includes) {
|
||||
(function() {
|
||||
'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
|
||||
var toString = {}.toString;
|
||||
var defineProperty = (function() {
|
||||
// IE 8 only supports `Object.defineProperty` on DOM elements
|
||||
try {
|
||||
var object = {};
|
||||
var $defineProperty = Object.defineProperty;
|
||||
var result = $defineProperty(object, object, object) && $defineProperty;
|
||||
} catch (error) {}
|
||||
return result;
|
||||
}());
|
||||
var indexOf = ''.indexOf;
|
||||
var includes = function(search) {
|
||||
if (this == null) {
|
||||
throw TypeError();
|
||||
}
|
||||
var string = String(this);
|
||||
if (search && toString.call(search) == '[object RegExp]') {
|
||||
throw TypeError();
|
||||
}
|
||||
var stringLength = string.length;
|
||||
var searchString = String(search);
|
||||
var searchLength = searchString.length;
|
||||
var position = arguments.length > 1 ? arguments[1] : undefined;
|
||||
// `ToInteger`
|
||||
var pos = position ? Number(position) : 0;
|
||||
if (pos != pos) { // better `isNaN`
|
||||
pos = 0;
|
||||
}
|
||||
var start = Math.min(Math.max(pos, 0), stringLength);
|
||||
// Avoid the `indexOf` call if no match is possible
|
||||
if (searchLength + start > stringLength) {
|
||||
return false;
|
||||
}
|
||||
return indexOf.call(string, searchString, pos) != -1;
|
||||
};
|
||||
if (defineProperty) {
|
||||
defineProperty(String.prototype, 'includes', {
|
||||
'value': includes,
|
||||
'configurable': true,
|
||||
'writable': true
|
||||
});
|
||||
} else {
|
||||
String.prototype.includes = includes;
|
||||
}
|
||||
}());
|
||||
}
|
||||
|
||||
/*! https://mths.be/startswith v0.2.0 by @mathias */
|
||||
if (!String.prototype.startsWith) {
|
||||
(function() {
|
||||
'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
|
||||
var defineProperty = (function() {
|
||||
// IE 8 only supports `Object.defineProperty` on DOM elements
|
||||
try {
|
||||
var object = {};
|
||||
var $defineProperty = Object.defineProperty;
|
||||
var result = $defineProperty(object, object, object) && $defineProperty;
|
||||
} catch (error) {}
|
||||
return result;
|
||||
}());
|
||||
var toString = {}.toString;
|
||||
var startsWith = function(search) {
|
||||
if (this == null) {
|
||||
throw TypeError();
|
||||
}
|
||||
var string = String(this);
|
||||
if (search && toString.call(search) == '[object RegExp]') {
|
||||
throw TypeError();
|
||||
}
|
||||
var stringLength = string.length;
|
||||
var searchString = String(search);
|
||||
var searchLength = searchString.length;
|
||||
var position = arguments.length > 1 ? arguments[1] : undefined;
|
||||
// `ToInteger`
|
||||
var pos = position ? Number(position) : 0;
|
||||
if (pos != pos) { // better `isNaN`
|
||||
pos = 0;
|
||||
}
|
||||
var start = Math.min(Math.max(pos, 0), stringLength);
|
||||
// Avoid the `indexOf` call if no match is possible
|
||||
if (searchLength + start > stringLength) {
|
||||
return false;
|
||||
}
|
||||
var index = -1;
|
||||
while (++index < searchLength) {
|
||||
if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (defineProperty) {
|
||||
defineProperty(String.prototype, 'startsWith', {
|
||||
'value': startsWith,
|
||||
'configurable': true,
|
||||
'writable': true
|
||||
});
|
||||
} else {
|
||||
String.prototype.startsWith = startsWith;
|
||||
}
|
||||
}());
|
||||
}
|
||||
if (!String.prototype.endsWith) {
|
||||
(function() {
|
||||
'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
|
||||
var defineProperty = (function() {
|
||||
// IE 8 only supports `Object.defineProperty` on DOM elements
|
||||
try {
|
||||
var object = {};
|
||||
var $defineProperty = Object.defineProperty;
|
||||
var result = $defineProperty(object, object, object) && $defineProperty;
|
||||
} catch (error) {}
|
||||
return result;
|
||||
}());
|
||||
var toString = {}.toString;
|
||||
var endsWith = function(search) {
|
||||
if (this == null) {
|
||||
throw TypeError();
|
||||
}
|
||||
var string = String(this);
|
||||
if (search && toString.call(search) == '[object RegExp]') {
|
||||
throw TypeError();
|
||||
}
|
||||
var stringLength = string.length;
|
||||
var searchString = String(search);
|
||||
var searchLength = searchString.length;
|
||||
var pos = stringLength;
|
||||
if (arguments.length > 1) {
|
||||
var position = arguments[1];
|
||||
if (position !== undefined) {
|
||||
// `ToInteger`
|
||||
pos = position ? Number(position) : 0;
|
||||
if (pos != pos) { // better `isNaN`
|
||||
pos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
var end = Math.min(Math.max(pos, 0), stringLength);
|
||||
var start = end - searchLength;
|
||||
if (start < 0) {
|
||||
return false;
|
||||
}
|
||||
var index = -1;
|
||||
while (++index < searchLength) {
|
||||
if (string.charCodeAt(start + index) != searchString.charCodeAt(index)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (defineProperty) {
|
||||
defineProperty(String.prototype, 'endsWith', {
|
||||
'value': endsWith,
|
||||
'configurable': true,
|
||||
'writable': true
|
||||
});
|
||||
} else {
|
||||
String.prototype.endsWith = endsWith;
|
||||
}
|
||||
}());
|
||||
}
|
||||
|
||||
/*! https://mths.be/repeat v0.2.0 by @mathias */
|
||||
if (!String.prototype.repeat) {
|
||||
(function() {
|
||||
'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
|
||||
var defineProperty = (function() {
|
||||
// IE 8 only supports `Object.defineProperty` on DOM elements
|
||||
try {
|
||||
var object = {};
|
||||
var $defineProperty = Object.defineProperty;
|
||||
var result = $defineProperty(object, object, object) && $defineProperty;
|
||||
} catch (error) {}
|
||||
return result;
|
||||
}());
|
||||
var repeat = function(count) {
|
||||
if (this == null) {
|
||||
throw TypeError();
|
||||
}
|
||||
var string = String(this);
|
||||
// `ToInteger`
|
||||
var n = count ? Number(count) : 0;
|
||||
if (n != n) { // better `isNaN`
|
||||
n = 0;
|
||||
}
|
||||
// Account for out-of-bounds indices
|
||||
if (n < 0 || n == Infinity) {
|
||||
throw RangeError();
|
||||
}
|
||||
var result = '';
|
||||
while (n) {
|
||||
if (n % 2 == 1) {
|
||||
result += string;
|
||||
}
|
||||
if (n > 1) {
|
||||
string += string;
|
||||
}
|
||||
n >>= 1;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
if (defineProperty) {
|
||||
defineProperty(String.prototype, 'repeat', {
|
||||
'value': repeat,
|
||||
'configurable': true,
|
||||
'writable': true
|
||||
});
|
||||
} else {
|
||||
String.prototype.repeat = repeat;
|
||||
}
|
||||
}());
|
||||
}
|
||||
|
||||
if (!String.prototype.at) {
|
||||
(function() {
|
||||
'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
|
||||
var defineProperty = (function() {
|
||||
// IE 8 only supports `Object.defineProperty` on DOM elements.
|
||||
try {
|
||||
var object = {};
|
||||
var $defineProperty = Object.defineProperty;
|
||||
var result = $defineProperty(object, object, object) && $defineProperty;
|
||||
} catch (exception) {}
|
||||
return result;
|
||||
}());
|
||||
var at = function(position) {
|
||||
if (this == null) {
|
||||
throw TypeError();
|
||||
}
|
||||
var string = String(this);
|
||||
var size = string.length;
|
||||
// `ToInteger`
|
||||
var index = position ? Number(position) : 0;
|
||||
if (index != index) { // better `isNaN`
|
||||
index = 0;
|
||||
}
|
||||
// Account for out-of-bounds indices
|
||||
// The odd lower bound is because the ToInteger operation is
|
||||
// going to round `n` to `0` for `-1 < n <= 0`.
|
||||
if (index <= -1 || index >= size) {
|
||||
return '';
|
||||
}
|
||||
// Second half of `ToInteger`
|
||||
index = index | 0;
|
||||
// Get the first code unit and code unit value
|
||||
var cuFirst = string.charCodeAt(index);
|
||||
var cuSecond;
|
||||
var nextIndex = index + 1;
|
||||
var len = 1;
|
||||
if ( // Check if it’s the start of a surrogate pair.
|
||||
cuFirst >= 0xD800 && cuFirst <= 0xDBFF && // high surrogate
|
||||
size > nextIndex // there is a next code unit
|
||||
) {
|
||||
cuSecond = string.charCodeAt(nextIndex);
|
||||
if (cuSecond >= 0xDC00 && cuSecond <= 0xDFFF) { // low surrogate
|
||||
len = 2;
|
||||
}
|
||||
}
|
||||
return string.slice(index, index + len);
|
||||
};
|
||||
if (defineProperty) {
|
||||
defineProperty(String.prototype, 'at', {
|
||||
'value': at,
|
||||
'configurable': true,
|
||||
'writable': true
|
||||
});
|
||||
} else {
|
||||
String.prototype.at = at;
|
||||
}
|
||||
}());
|
||||
}
|
||||
|
||||
/*! https://mths.be/codepointat v0.2.0 by @mathias */
|
||||
if (!String.prototype.codePointAt) {
|
||||
(function() {
|
||||
'use strict'; // needed to support `apply`/`call` with `undefined`/`null`
|
||||
var defineProperty = (function() {
|
||||
// IE 8 only supports `Object.defineProperty` on DOM elements
|
||||
try {
|
||||
var object = {};
|
||||
var $defineProperty = Object.defineProperty;
|
||||
var result = $defineProperty(object, object, object) && $defineProperty;
|
||||
} catch (error) {}
|
||||
return result;
|
||||
}());
|
||||
var codePointAt = function(position) {
|
||||
if (this == null) {
|
||||
throw TypeError();
|
||||
}
|
||||
var string = String(this);
|
||||
var size = string.length;
|
||||
// `ToInteger`
|
||||
var index = position ? Number(position) : 0;
|
||||
if (index != index) { // better `isNaN`
|
||||
index = 0;
|
||||
}
|
||||
// Account for out-of-bounds indices:
|
||||
if (index < 0 || index >= size) {
|
||||
return undefined;
|
||||
}
|
||||
// Get the first code unit
|
||||
var first = string.charCodeAt(index);
|
||||
var second;
|
||||
if ( // check if it’s the start of a surrogate pair
|
||||
first >= 0xD800 && first <= 0xDBFF && // high surrogate
|
||||
size > index + 1 // there is a next code unit
|
||||
) {
|
||||
second = string.charCodeAt(index + 1);
|
||||
if (second >= 0xDC00 && second <= 0xDFFF) { // low surrogate
|
||||
// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
|
||||
return (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
};
|
||||
if (defineProperty) {
|
||||
defineProperty(String.prototype, 'codePointAt', {
|
||||
'value': codePointAt,
|
||||
'configurable': true,
|
||||
'writable': true
|
||||
});
|
||||
} else {
|
||||
String.prototype.codePointAt = codePointAt;
|
||||
}
|
||||
}());
|
||||
}
|
||||
|
||||
/*! https://mths.be/fromcodepoint v0.2.1 by @mathias */
|
||||
if (!String.fromCodePoint) {
|
||||
(function() {
|
||||
var defineProperty = (function() {
|
||||
// IE 8 only supports `Object.defineProperty` on DOM elements
|
||||
try {
|
||||
var object = {};
|
||||
var $defineProperty = Object.defineProperty;
|
||||
var result = $defineProperty(object, object, object) && $defineProperty;
|
||||
} catch (error) {}
|
||||
return result;
|
||||
}());
|
||||
var stringFromCharCode = String.fromCharCode;
|
||||
var floor = Math.floor;
|
||||
var fromCodePoint = function(_) {
|
||||
var MAX_SIZE = 0x4000;
|
||||
var codeUnits = [];
|
||||
var highSurrogate;
|
||||
var lowSurrogate;
|
||||
var index = -1;
|
||||
var length = arguments.length;
|
||||
if (!length) {
|
||||
return '';
|
||||
}
|
||||
var result = '';
|
||||
while (++index < length) {
|
||||
var codePoint = Number(arguments[index]);
|
||||
if (!isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
|
||||
codePoint < 0 || // not a valid Unicode code point
|
||||
codePoint > 0x10FFFF || // not a valid Unicode code point
|
||||
floor(codePoint) != codePoint // not an integer
|
||||
) {
|
||||
throw RangeError('Invalid code point: ' + codePoint);
|
||||
}
|
||||
if (codePoint <= 0xFFFF) { // BMP code point
|
||||
codeUnits.push(codePoint);
|
||||
} else { // Astral code point; split in surrogate halves
|
||||
// https://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
|
||||
codePoint -= 0x10000;
|
||||
highSurrogate = (codePoint >> 10) + 0xD800;
|
||||
lowSurrogate = (codePoint % 0x400) + 0xDC00;
|
||||
codeUnits.push(highSurrogate, lowSurrogate);
|
||||
}
|
||||
if (index + 1 == length || codeUnits.length > MAX_SIZE) {
|
||||
result += stringFromCharCode.apply(null, codeUnits);
|
||||
codeUnits.length = 0;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
if (defineProperty) {
|
||||
defineProperty(String, 'fromCodePoint', {
|
||||
'value': fromCodePoint,
|
||||
'configurable': true,
|
||||
'writable': true
|
||||
});
|
||||
} else {
|
||||
String.fromCodePoint = fromCodePoint;
|
||||
}
|
||||
}());
|
||||
}
|
547
examples/libraries/usertiming.js
Normal file
547
examples/libraries/usertiming.js
Normal file
|
@ -0,0 +1,547 @@
|
|||
//
|
||||
// usertiming.js
|
||||
//
|
||||
// A polyfill for UserTiming (http://www.w3.org/TR/user-timing/)
|
||||
//
|
||||
// Copyright 2013 Nic Jansma
|
||||
// http://nicj.net
|
||||
//
|
||||
// https://github.com/nicjansma/usertiming.js
|
||||
//
|
||||
// Licensed under the MIT license
|
||||
//
|
||||
// Adapted for High Fidelity by James B. Pollack @imgntn on 11/6/2015
|
||||
|
||||
function userTiming() {
|
||||
"use strict";
|
||||
|
||||
// allow running in Node.js environment
|
||||
if (typeof window === "undefined") {
|
||||
window = {};
|
||||
}
|
||||
|
||||
// prepare base perf object
|
||||
if (typeof window.performance === "undefined") {
|
||||
window.performance = {};
|
||||
}
|
||||
|
||||
// We need to keep a global reference to the window.performance object to
|
||||
// prevent any added properties from being garbage-collected in Safari 8.
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=137407
|
||||
window._perfRefForUserTimingPolyfill = window.performance;
|
||||
|
||||
//
|
||||
// Note what we shimmed
|
||||
//
|
||||
window.performance.userTimingJsNow = false;
|
||||
window.performance.userTimingJsNowPrefixed = false;
|
||||
window.performance.userTimingJsUserTiming = false;
|
||||
window.performance.userTimingJsUserTimingPrefixed = false;
|
||||
window.performance.userTimingJsPerformanceTimeline = false;
|
||||
window.performance.userTimingJsPerformanceTimelinePrefixed = false;
|
||||
|
||||
// for prefixed support
|
||||
var prefixes = [];
|
||||
var methods = [];
|
||||
var methodTest = null;
|
||||
var i, j;
|
||||
|
||||
//
|
||||
// window.performance.now() shim
|
||||
// http://www.w3.org/TR/hr-time/
|
||||
//
|
||||
if (typeof window.performance.now !== "function") {
|
||||
window.performance.userTimingJsNow = true;
|
||||
|
||||
// copy prefixed version over if it exists
|
||||
methods = ["webkitNow", "msNow", "mozNow"];
|
||||
|
||||
for (i = 0; i < methods.length; i++) {
|
||||
if (typeof window.performance[methods[i]] === "function") {
|
||||
window.performance.now = window.performance[methods[i]];
|
||||
|
||||
window.performance.userTimingJsNowPrefixed = true;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// now() should be a DOMHighResTimeStamp, which is defined as being a time relative
|
||||
// to navigationStart of the PerformanceTiming (PT) interface. If this browser supports
|
||||
// PT, use that as our relative start. Otherwise, use "now" as the start and all other
|
||||
// now() calls will be relative to our initialization.
|
||||
//
|
||||
|
||||
var nowOffset = +(new Date());
|
||||
if (window.performance.timing && window.performance.timing.navigationStart) {
|
||||
nowOffset = window.performance.timing.navigationStart;
|
||||
}
|
||||
|
||||
if (typeof window.performance.now !== "function") {
|
||||
// No browser support, fall back to Date.now
|
||||
if (Date.now) {
|
||||
window.performance.now = function() {
|
||||
return Date.now() - nowOffset;
|
||||
};
|
||||
} else {
|
||||
// no Date.now support, get the time from new Date()
|
||||
window.performance.now = function() {
|
||||
return +(new Date()) - nowOffset;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// PerformanceTimeline (PT) shims
|
||||
// http://www.w3.org/TR/performance-timeline/
|
||||
//
|
||||
|
||||
/**
|
||||
* Adds an object to our internal Performance Timeline array.
|
||||
*
|
||||
* Will be blank if the environment supports PT.
|
||||
*/
|
||||
var addToPerformanceTimeline = function() {};
|
||||
|
||||
/**
|
||||
* Clears the specified entry types from our timeline array.
|
||||
*
|
||||
* Will be blank if the environment supports PT.
|
||||
*/
|
||||
var clearEntriesFromPerformanceTimeline = function() {};
|
||||
|
||||
// performance timeline array
|
||||
var performanceTimeline = [];
|
||||
|
||||
// whether or not the timeline will require sort on getEntries()
|
||||
var performanceTimelineRequiresSort = false;
|
||||
|
||||
// whether or not ResourceTiming is natively supported but UserTiming is
|
||||
// not (eg Firefox 35)
|
||||
var hasNativeGetEntriesButNotUserTiming = false;
|
||||
|
||||
//
|
||||
// If getEntries() and mark() aren't defined, we'll assume
|
||||
// we have to shim at least some PT functions.
|
||||
//
|
||||
if (typeof window.performance.getEntries !== "function" ||
|
||||
typeof window.performance.mark !== "function") {
|
||||
|
||||
if (typeof window.performance.getEntries === "function" &&
|
||||
typeof window.performance.mark !== "function") {
|
||||
hasNativeGetEntriesButNotUserTiming = true;
|
||||
}
|
||||
|
||||
window.performance.userTimingJsPerformanceTimeline = true;
|
||||
|
||||
// copy prefixed version over if it exists
|
||||
prefixes = ["webkit", "moz"];
|
||||
methods = ["getEntries", "getEntriesByName", "getEntriesByType"];
|
||||
|
||||
for (i = 0; i < methods.length; i++) {
|
||||
for (j = 0; j < prefixes.length; j++) {
|
||||
// prefixed method will likely have an upper-case first letter
|
||||
methodTest = prefixes[j] + methods[i].substr(0, 1).toUpperCase() + methods[i].substr(1);
|
||||
|
||||
if (typeof window.performance[methodTest] === "function") {
|
||||
window.performance[methods[i]] = window.performance[methodTest];
|
||||
|
||||
window.performance.userTimingJsPerformanceTimelinePrefixed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an object to our internal Performance Timeline array.
|
||||
*
|
||||
* @param {Object} obj PerformanceEntry
|
||||
*/
|
||||
addToPerformanceTimeline = function(obj) {
|
||||
performanceTimeline.push(obj);
|
||||
|
||||
//
|
||||
// If we insert a measure, its startTime may be out of order
|
||||
// from the rest of the entries because the use can use any
|
||||
// mark as the start time. If so, note we have to sort it before
|
||||
// returning getEntries();
|
||||
//
|
||||
if (obj.entryType === "measure") {
|
||||
performanceTimelineRequiresSort = true;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Ensures our PT array is in the correct sorted order (by startTime)
|
||||
*/
|
||||
var ensurePerformanceTimelineOrder = function() {
|
||||
if (!performanceTimelineRequiresSort) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Measures, which may be in this list, may enter the list in
|
||||
// an unsorted order. For example:
|
||||
//
|
||||
// 1. measure("a")
|
||||
// 2. mark("start_mark")
|
||||
// 3. measure("b", "start_mark")
|
||||
// 4. measure("c")
|
||||
// 5. getEntries()
|
||||
//
|
||||
// When calling #5, we should return [a,c,b] because technically the start time
|
||||
// of c is "0" (navigationStart), which will occur before b's start time due to the mark.
|
||||
//
|
||||
performanceTimeline.sort(function(a, b) {
|
||||
return a.startTime - b.startTime;
|
||||
});
|
||||
|
||||
performanceTimelineRequiresSort = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Clears the specified entry types from our timeline array.
|
||||
*
|
||||
* @param {string} entryType Entry type (eg "mark" or "measure")
|
||||
* @param {string} [name] Entry name (optional)
|
||||
*/
|
||||
clearEntriesFromPerformanceTimeline = function(entryType, name) {
|
||||
// clear all entries from the perf timeline
|
||||
i = 0;
|
||||
while (i < performanceTimeline.length) {
|
||||
if (performanceTimeline[i].entryType !== entryType) {
|
||||
// unmatched entry type
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (typeof name !== "undefined" && performanceTimeline[i].name !== name) {
|
||||
// unmatched name
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// this entry matches our criteria, remove just it
|
||||
performanceTimeline.splice(i, 1);
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof window.performance.getEntries !== "function" || hasNativeGetEntriesButNotUserTiming) {
|
||||
var origGetEntries = window.performance.getEntries;
|
||||
|
||||
/**
|
||||
* Gets all entries from the Performance Timeline.
|
||||
* http://www.w3.org/TR/performance-timeline/#dom-performance-getentries
|
||||
*
|
||||
* NOTE: This will only ever return marks and measures.
|
||||
*
|
||||
* @returns {PerformanceEntry[]} Array of PerformanceEntrys
|
||||
*/
|
||||
window.performance.getEntries = function() {
|
||||
ensurePerformanceTimelineOrder();
|
||||
|
||||
// get a copy of all of our entries
|
||||
var entries = performanceTimeline.slice(0);
|
||||
|
||||
// if there was a native version of getEntries, add that
|
||||
if (hasNativeGetEntriesButNotUserTiming && origGetEntries) {
|
||||
// merge in native
|
||||
Array.prototype.push.apply(entries, origGetEntries.call(window.performance));
|
||||
|
||||
// sort by startTime
|
||||
entries.sort(function(a, b) {
|
||||
return a.startTime - b.startTime;
|
||||
});
|
||||
}
|
||||
|
||||
return entries;
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof window.performance.getEntriesByType !== "function" || hasNativeGetEntriesButNotUserTiming) {
|
||||
var origGetEntriesByType = window.performance.getEntriesByType;
|
||||
|
||||
/**
|
||||
* Gets all entries from the Performance Timeline of the specified type.
|
||||
* http://www.w3.org/TR/performance-timeline/#dom-performance-getentriesbytype
|
||||
*
|
||||
* NOTE: This will only work for marks and measures.
|
||||
*
|
||||
* @param {string} entryType Entry type (eg "mark" or "measure")
|
||||
*
|
||||
* @returns {PerformanceEntry[]} Array of PerformanceEntrys
|
||||
*/
|
||||
window.performance.getEntriesByType = function(entryType) {
|
||||
// we only support marks/measures
|
||||
if (typeof entryType === "undefined" ||
|
||||
(entryType !== "mark" && entryType !== "measure")) {
|
||||
|
||||
if (hasNativeGetEntriesButNotUserTiming && origGetEntriesByType) {
|
||||
// native version exists, forward
|
||||
return origGetEntriesByType.call(window.performance, entryType);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
// see note in ensurePerformanceTimelineOrder() on why this is required
|
||||
if (entryType === "measure") {
|
||||
ensurePerformanceTimelineOrder();
|
||||
}
|
||||
|
||||
// find all entries of entryType
|
||||
var entries = [];
|
||||
for (i = 0; i < performanceTimeline.length; i++) {
|
||||
if (performanceTimeline[i].entryType === entryType) {
|
||||
entries.push(performanceTimeline[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return entries;
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof window.performance.getEntriesByName !== "function" || hasNativeGetEntriesButNotUserTiming) {
|
||||
var origGetEntriesByName = window.performance.getEntriesByName;
|
||||
|
||||
/**
|
||||
* Gets all entries from the Performance Timeline of the specified
|
||||
* name, and optionally, type.
|
||||
* http://www.w3.org/TR/performance-timeline/#dom-performance-getentriesbyname
|
||||
*
|
||||
* NOTE: This will only work for marks and measures.
|
||||
*
|
||||
* @param {string} name Entry name
|
||||
* @param {string} [entryType] Entry type (eg "mark" or "measure")
|
||||
*
|
||||
* @returns {PerformanceEntry[]} Array of PerformanceEntrys
|
||||
*/
|
||||
window.performance.getEntriesByName = function(name, entryType) {
|
||||
if (entryType && entryType !== "mark" && entryType !== "measure") {
|
||||
if (hasNativeGetEntriesButNotUserTiming && origGetEntriesByName) {
|
||||
// native version exists, forward
|
||||
return origGetEntriesByName.call(window.performance, name, entryType);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
// see note in ensurePerformanceTimelineOrder() on why this is required
|
||||
if (typeof entryType !== "undefined" && entryType === "measure") {
|
||||
ensurePerformanceTimelineOrder();
|
||||
}
|
||||
|
||||
// find all entries of the name and (optionally) type
|
||||
var entries = [];
|
||||
for (i = 0; i < performanceTimeline.length; i++) {
|
||||
if (typeof entryType !== "undefined" &&
|
||||
performanceTimeline[i].entryType !== entryType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (performanceTimeline[i].name === name) {
|
||||
entries.push(performanceTimeline[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasNativeGetEntriesButNotUserTiming && origGetEntriesByName) {
|
||||
// merge in native
|
||||
Array.prototype.push.apply(entries, origGetEntriesByName.call(window.performance, name, entryType));
|
||||
|
||||
// sort by startTime
|
||||
entries.sort(function(a, b) {
|
||||
return a.startTime - b.startTime;
|
||||
});
|
||||
}
|
||||
|
||||
return entries;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// UserTiming support
|
||||
//
|
||||
if (typeof window.performance.mark !== "function") {
|
||||
window.performance.userTimingJsUserTiming = true;
|
||||
|
||||
// copy prefixed version over if it exists
|
||||
prefixes = ["webkit", "moz", "ms"];
|
||||
methods = ["mark", "measure", "clearMarks", "clearMeasures"];
|
||||
|
||||
for (i = 0; i < methods.length; i++) {
|
||||
for (j = 0; j < prefixes.length; j++) {
|
||||
// prefixed method will likely have an upper-case first letter
|
||||
methodTest = prefixes[j] + methods[i].substr(0, 1).toUpperCase() + methods[i].substr(1);
|
||||
|
||||
if (typeof window.performance[methodTest] === "function") {
|
||||
window.performance[methods[i]] = window.performance[methodTest];
|
||||
|
||||
window.performance.userTimingJsUserTimingPrefixed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// only used for measure(), to quickly see the latest timestamp of a mark
|
||||
var marks = {};
|
||||
|
||||
if (typeof window.performance.mark !== "function") {
|
||||
/**
|
||||
* UserTiming mark
|
||||
* http://www.w3.org/TR/user-timing/#dom-performance-mark
|
||||
*
|
||||
* @param {string} markName Mark name
|
||||
*/
|
||||
window.performance.mark = function(markName) {
|
||||
var now = window.performance.now();
|
||||
|
||||
// mark name is required
|
||||
if (typeof markName === "undefined") {
|
||||
throw new SyntaxError("Mark name must be specified");
|
||||
}
|
||||
|
||||
// mark name can't be a NT timestamp
|
||||
if (window.performance.timing && markName in window.performance.timing) {
|
||||
throw new SyntaxError("Mark name is not allowed");
|
||||
}
|
||||
|
||||
if (!marks[markName]) {
|
||||
marks[markName] = [];
|
||||
}
|
||||
|
||||
marks[markName].push(now);
|
||||
|
||||
// add to perf timeline as well
|
||||
addToPerformanceTimeline({
|
||||
entryType: "mark",
|
||||
name: markName,
|
||||
startTime: now,
|
||||
duration: 0
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof window.performance.clearMarks !== "function") {
|
||||
/**
|
||||
* UserTiming clear marks
|
||||
* http://www.w3.org/TR/user-timing/#dom-performance-clearmarks
|
||||
*
|
||||
* @param {string} markName Mark name
|
||||
*/
|
||||
window.performance.clearMarks = function(markName) {
|
||||
if (!markName) {
|
||||
// clear all marks
|
||||
marks = {};
|
||||
} else {
|
||||
marks[markName] = [];
|
||||
}
|
||||
|
||||
clearEntriesFromPerformanceTimeline("mark", markName);
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof window.performance.measure !== "function") {
|
||||
/**
|
||||
* UserTiming measure
|
||||
* http://www.w3.org/TR/user-timing/#dom-performance-measure
|
||||
*
|
||||
* @param {string} measureName Measure name
|
||||
* @param {string} [startMark] Start mark name
|
||||
* @param {string} [endMark] End mark name
|
||||
*/
|
||||
window.performance.measure = function(measureName, startMark, endMark) {
|
||||
var now = window.performance.now();
|
||||
|
||||
if (typeof measureName === "undefined") {
|
||||
throw new SyntaxError("Measure must be specified");
|
||||
}
|
||||
|
||||
// if there isn't a startMark, we measure from navigationStart to now
|
||||
if (!startMark) {
|
||||
// add to perf timeline as well
|
||||
addToPerformanceTimeline({
|
||||
entryType: "measure",
|
||||
name: measureName,
|
||||
startTime: 0,
|
||||
duration: now
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// If there is a startMark, check for it first in the NavigationTiming interface,
|
||||
// then check our own marks.
|
||||
//
|
||||
var startMarkTime = 0;
|
||||
if (window.performance.timing && startMark in window.performance.timing) {
|
||||
// mark cannot have a timing of 0
|
||||
if (startMark !== "navigationStart" && window.performance.timing[startMark] === 0) {
|
||||
throw new Error(startMark + " has a timing of 0");
|
||||
}
|
||||
|
||||
// time is the offset of this mark to navigationStart's time
|
||||
startMarkTime = window.performance.timing[startMark] - window.performance.timing.navigationStart;
|
||||
} else if (startMark in marks) {
|
||||
startMarkTime = marks[startMark][marks[startMark].length - 1];
|
||||
} else {
|
||||
throw new Error(startMark + " mark not found");
|
||||
}
|
||||
|
||||
//
|
||||
// If there is a endMark, check for it first in the NavigationTiming interface,
|
||||
// then check our own marks.
|
||||
//
|
||||
var endMarkTime = now;
|
||||
|
||||
if (endMark) {
|
||||
endMarkTime = 0;
|
||||
|
||||
if (window.performance.timing && endMark in window.performance.timing) {
|
||||
// mark cannot have a timing of 0
|
||||
if (endMark !== "navigationStart" && window.performance.timing[endMark] === 0) {
|
||||
throw new Error(endMark + " has a timing of 0");
|
||||
}
|
||||
|
||||
// time is the offset of this mark to navigationStart's time
|
||||
endMarkTime = window.performance.timing[endMark] - window.performance.timing.navigationStart;
|
||||
} else if (endMark in marks) {
|
||||
endMarkTime = marks[endMark][marks[endMark].length - 1];
|
||||
} else {
|
||||
throw new Error(endMark + " mark not found");
|
||||
}
|
||||
}
|
||||
|
||||
// add to our measure array
|
||||
var duration = endMarkTime - startMarkTime;
|
||||
|
||||
// add to perf timeline as well
|
||||
addToPerformanceTimeline({
|
||||
entryType: "measure",
|
||||
name: measureName,
|
||||
startTime: startMarkTime,
|
||||
duration: duration
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
if (typeof window.performance.clearMeasures !== "function") {
|
||||
/**
|
||||
* UserTiming clear measures
|
||||
* http://www.w3.org/TR/user-timing/#dom-performance-clearmeasures
|
||||
*
|
||||
* @param {string} measureName Measure name
|
||||
*/
|
||||
window.performance.clearMeasures = function(measureName) {
|
||||
clearEntriesFromPerformanceTimeline("measure", measureName);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return window
|
||||
}
|
||||
|
||||
loadUserTiming = function() {
|
||||
return userTiming();
|
||||
}
|
18
examples/libraries/usertimingExample.js
Normal file
18
examples/libraries/usertimingExample.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
Script.include('usertiming.js');
|
||||
var timing = loadUserTiming();
|
||||
//set a mark
|
||||
timing.performance.mark('firstMark');
|
||||
|
||||
//do something that takes time -- we're just going to set a timeout here as an example
|
||||
|
||||
Script.setTimeout(function() {
|
||||
//and set another mark
|
||||
timing.performance.mark('secondMark');
|
||||
|
||||
//measure time between marks (first parameter is a name for the measurement)
|
||||
timing.performance.measure('howlong', 'firstMark', 'secondMark');
|
||||
|
||||
//you can also get the marks by changing the type
|
||||
var measures = timing.performance.getEntriesByType('measure');
|
||||
print('measures:::' + JSON.stringify(measures))
|
||||
}, 1000)
|
|
@ -14,8 +14,8 @@ Script.include("../../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 = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj';
|
||||
|
||||
var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_convex.obj';
|
||||
var COLLISION_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/plastic_impact.L.wav';
|
||||
var center = Vec3.sum(Vec3.sum(MyAvatar.position, {
|
||||
x: 0,
|
||||
y: 0.5,
|
||||
|
@ -25,9 +25,8 @@ var center = Vec3.sum(Vec3.sum(MyAvatar.position, {
|
|||
var pingPongGun = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: MODEL_URL,
|
||||
shapeType:'box',
|
||||
// shapeType: 'compound',
|
||||
// compoundShapeURL: COLLISION_HULL_URL,
|
||||
shapeType: 'compound',
|
||||
compoundShapeURL: COLLISION_HULL_URL,
|
||||
script: scriptURL,
|
||||
position: center,
|
||||
dimensions: {
|
||||
|
@ -36,6 +35,7 @@ var pingPongGun = Entities.addEntity({
|
|||
z: 0.47
|
||||
},
|
||||
collisionsWillMove: true,
|
||||
collisionSoundURL: COLLISION_SOUND_URL
|
||||
});
|
||||
|
||||
function cleanUp() {
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "untextured_particle_frag.h"
|
||||
#include "textured_particle_vert.h"
|
||||
#include "textured_particle_frag.h"
|
||||
#include "textured_particle_alpha_discard_frag.h"
|
||||
|
||||
class ParticlePayload {
|
||||
public:
|
||||
|
@ -114,8 +115,7 @@ namespace render {
|
|||
}
|
||||
}
|
||||
|
||||
gpu::PipelinePointer RenderableParticleEffectEntityItem::_texturedPipeline;
|
||||
gpu::PipelinePointer RenderableParticleEffectEntityItem::_untexturedPipeline;
|
||||
|
||||
|
||||
EntityItemPointer RenderableParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return std::make_shared<RenderableParticleEffectEntityItem>(entityID, properties);
|
||||
|
@ -203,19 +203,26 @@ void RenderableParticleEffectEntityItem::updateRenderItem() {
|
|||
|
||||
// sort particles back to front
|
||||
// NOTE: this is view frustum might be one frame out of date.
|
||||
|
||||
auto frustum = AbstractViewStateInterface::instance()->getCurrentViewFrustum();
|
||||
::zSortAxis = frustum->getDirection();
|
||||
qSort(particleDetails.begin(), particleDetails.end(), zSort);
|
||||
|
||||
// No need to sort if we're doing additive blending
|
||||
if (_additiveBlending != true) {
|
||||
::zSortAxis = frustum->getDirection();
|
||||
qSort(particleDetails.begin(), particleDetails.end(), zSort);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// allocate vertices
|
||||
_vertices.clear();
|
||||
|
||||
// build vertices from particle positions and radiuses
|
||||
glm::vec3 frustumPosition = frustum->getPosition();
|
||||
glm::vec3 dir = frustum->getDirection();
|
||||
for (auto&& particle : particleDetails) {
|
||||
glm::vec3 particleDirection = particle.position - frustumPosition;
|
||||
glm::vec3 right = glm::normalize(glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), particleDirection));
|
||||
glm::vec3 up = glm::normalize(glm::cross(right, particleDirection));
|
||||
glm::vec3 right = glm::normalize(glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), dir));
|
||||
glm::vec3 up = glm::normalize(glm::cross(right, dir));
|
||||
|
||||
glm::vec3 upOffset = up * particle.radius;
|
||||
glm::vec3 rightOffset = right * particle.radius;
|
||||
|
@ -309,12 +316,21 @@ void RenderableParticleEffectEntityItem::updateRenderItem() {
|
|||
}
|
||||
|
||||
void RenderableParticleEffectEntityItem::createPipelines() {
|
||||
bool writeToDepthBuffer = false;
|
||||
gpu::State::BlendArg destinationColorBlendArg;
|
||||
if (_additiveBlending) {
|
||||
destinationColorBlendArg = gpu::State::ONE;
|
||||
}
|
||||
else {
|
||||
destinationColorBlendArg = gpu::State::INV_SRC_ALPHA;
|
||||
writeToDepthBuffer = true;
|
||||
}
|
||||
if (!_untexturedPipeline) {
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
state->setDepthTest(true, writeToDepthBuffer, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD,
|
||||
gpu::State::ONE, gpu::State::FACTOR_ALPHA,
|
||||
destinationColorBlendArg, gpu::State::FACTOR_ALPHA,
|
||||
gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
auto vertShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(untextured_particle_vert)));
|
||||
auto fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(untextured_particle_frag)));
|
||||
|
@ -324,13 +340,24 @@ void RenderableParticleEffectEntityItem::createPipelines() {
|
|||
if (!_texturedPipeline) {
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setCullMode(gpu::State::CULL_BACK);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
|
||||
|
||||
bool writeToDepthBuffer = !_additiveBlending;
|
||||
state->setDepthTest(true, writeToDepthBuffer, gpu::LESS_EQUAL);
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD,
|
||||
gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA,
|
||||
destinationColorBlendArg, gpu::State::FACTOR_ALPHA,
|
||||
gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
auto vertShader = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(textured_particle_vert)));
|
||||
auto fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_frag)));
|
||||
gpu::ShaderPointer fragShader;
|
||||
if (_additiveBlending) {
|
||||
fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_frag)));
|
||||
}
|
||||
else {
|
||||
//If we are sorting and have no additive blending, we want to discard pixels with low alpha to avoid inter-particle entity artifacts
|
||||
fragShader = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(textured_particle_alpha_discard_frag)));
|
||||
}
|
||||
auto program = gpu::ShaderPointer(gpu::Shader::createProgram(vertShader, fragShader));
|
||||
_texturedPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,11 +38,11 @@ protected:
|
|||
uint32_t rgba;
|
||||
};
|
||||
|
||||
static void createPipelines();
|
||||
void createPipelines();
|
||||
|
||||
std::vector<Vertex> _vertices;
|
||||
static gpu::PipelinePointer _untexturedPipeline;
|
||||
static gpu::PipelinePointer _texturedPipeline;
|
||||
gpu::PipelinePointer _untexturedPipeline;
|
||||
gpu::PipelinePointer _texturedPipeline;
|
||||
|
||||
render::ScenePointer _scene;
|
||||
NetworkTexturePointer _texture;
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// fragment shader
|
||||
//
|
||||
// Copyright 2015 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
|
||||
//
|
||||
|
||||
uniform sampler2D colorMap;
|
||||
|
||||
in vec4 _color;
|
||||
in vec2 _texCoord0;
|
||||
|
||||
out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
vec4 color = texture(colorMap, _texCoord0);
|
||||
if (color.a < 0.1) {
|
||||
discard;
|
||||
}
|
||||
outFragColor = color * _color;
|
||||
}
|
|
@ -195,6 +195,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_ALPHA_SPREAD, alphaSpread);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ALPHA_START, alphaStart);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ALPHA_FINISH, alphaFinish);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ADDITIVE_BLENDING, additiveBlending);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL);
|
||||
CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
|
||||
CHECK_PROPERTY_CHANGE(PROP_VISIBLE, visible);
|
||||
|
@ -351,6 +352,8 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_SPREAD, alphaSpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_START, alphaStart);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_FINISH, alphaFinish);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ADDITIVE_BLENDING, additiveBlending);
|
||||
|
||||
}
|
||||
|
||||
// Models only
|
||||
|
@ -502,6 +505,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaSpread, float, setAlphaSpread);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaStart, float, setAlphaStart);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(alphaFinish, float, setAlphaFinish);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(additiveBlending, bool, setAdditiveBlending);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(modelURL, QString, setModelURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(compoundShapeURL, QString, setCompoundShapeURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(glowLevel, float, setGlowLevel);
|
||||
|
@ -650,6 +654,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
|||
ADD_PROPERTY_TO_MAP(PROP_ALPHA_SPREAD, AlphaSpread, alphaSpread, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ALPHA_START, AlphaStart, alphaStart, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ALPHA_FINISH, AlphaFinish, alphaFinish, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_ADDITIVE_BLENDING, AdditiveBlending, additiveBlending, bool);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MODEL_URL, ModelURL, modelURL, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString);
|
||||
ADD_PROPERTY_TO_MAP(PROP_REGISTRATION_POINT, RegistrationPoint, registrationPoint, glm::vec3);
|
||||
|
@ -959,6 +964,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
APPEND_ENTITY_PROPERTY(PROP_ALPHA_SPREAD, properties.getAlphaSpread());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ALPHA_START, properties.getAlphaStart());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ALPHA_FINISH, properties.getAlphaFinish());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, properties.getAdditiveBlending());
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Zone) {
|
||||
|
@ -1241,6 +1247,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_SPREAD, float, setAlphaSpread);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_START, float, setAlphaStart);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_FINISH, float, setAlphaFinish);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ADDITIVE_BLENDING, bool, setAdditiveBlending);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Zone) {
|
||||
|
@ -1579,6 +1586,9 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
if (alphaFinishChanged()) {
|
||||
out += "alphaFinish";
|
||||
}
|
||||
if (additiveBlendingChanged()) {
|
||||
out += "additiveBlending";
|
||||
}
|
||||
if (modelURLChanged()) {
|
||||
out += "modelURL";
|
||||
}
|
||||
|
|
|
@ -159,6 +159,7 @@ public:
|
|||
DEFINE_PROPERTY(PROP_RADIUS_SPREAD, RadiusSpread, radiusSpread, float, ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD);
|
||||
DEFINE_PROPERTY(PROP_RADIUS_START, RadiusStart, radiusStart, float, ParticleEffectEntityItem::DEFAULT_RADIUS_START);
|
||||
DEFINE_PROPERTY(PROP_RADIUS_FINISH, RadiusFinish, radiusFinish, float, ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH);
|
||||
DEFINE_PROPERTY(PROP_ADDITIVE_BLENDING, AdditiveBlending, additiveBlending, bool, ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING);
|
||||
DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID);
|
||||
DEFINE_PROPERTY_GROUP(KeyLight, keyLight, KeyLightPropertyGroup);
|
||||
DEFINE_PROPERTY_REF(PROP_VOXEL_VOLUME_SIZE, VoxelVolumeSize, voxelVolumeSize, glm::vec3, PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE);
|
||||
|
|
|
@ -149,6 +149,8 @@ enum EntityPropertyList {
|
|||
PROP_ANIMATION_HOLD,
|
||||
PROP_ANIMATION_START_AUTOMATICALLY,
|
||||
|
||||
PROP_ADDITIVE_BLENDING,
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ATTENTION: add new properties to end of list just ABOVE this line
|
||||
PROP_AFTER_LAST_ITEM,
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "EntityItemProperties.h"
|
||||
#include "EntityTree.h"
|
||||
#include "EntityTreeElement.h"
|
||||
#include "EntityTypes.h"
|
||||
|
||||
EntityTreeElement::EntityTreeElement(unsigned char* octalCode) : OctreeElement() {
|
||||
init(octalCode);
|
||||
|
@ -591,7 +592,8 @@ bool EntityTreeElement::findDetailedRayIntersection(const glm::vec3& origin, con
|
|||
}
|
||||
} else {
|
||||
// if the entity type doesn't support a detailed intersection, then just return the non-AABox results
|
||||
if (localDistance < distance) {
|
||||
// Never intersect with particle effect entities
|
||||
if (localDistance < distance && EntityTypes::getEntityTypeName(entity->getType()) != "ParticleEffect") {
|
||||
distance = localDistance;
|
||||
face = localFace;
|
||||
surfaceNormal = localSurfaceNormal;
|
||||
|
|
|
@ -94,6 +94,7 @@ const float ParticleEffectEntityItem::DEFAULT_RADIUS_SPREAD = 0.0f;
|
|||
const float ParticleEffectEntityItem::DEFAULT_RADIUS_START = DEFAULT_PARTICLE_RADIUS;
|
||||
const float ParticleEffectEntityItem::DEFAULT_RADIUS_FINISH = DEFAULT_PARTICLE_RADIUS;
|
||||
const QString ParticleEffectEntityItem::DEFAULT_TEXTURES = "";
|
||||
const bool ParticleEffectEntityItem::DEFAULT_ADDITIVE_BLENDING = false;
|
||||
|
||||
|
||||
EntityItemPointer ParticleEffectEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
|
@ -121,7 +122,8 @@ ParticleEffectEntityItem::ParticleEffectEntityItem(const EntityItemID& entityIte
|
|||
_alphaMiddles(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA),
|
||||
_alphaFinishes(DEFAULT_MAX_PARTICLES, DEFAULT_ALPHA),
|
||||
_particleMaxBound(glm::vec3(1.0f, 1.0f, 1.0f)),
|
||||
_particleMinBound(glm::vec3(-1.0f, -1.0f, -1.0f))
|
||||
_particleMinBound(glm::vec3(-1.0f, -1.0f, -1.0f)) ,
|
||||
_additiveBlending(DEFAULT_ADDITIVE_BLENDING)
|
||||
{
|
||||
|
||||
_type = EntityTypes::ParticleEffect;
|
||||
|
@ -355,6 +357,8 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(EntityPropertyFlags
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaStart, getAlphaStart);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaFinish, getAlphaFinish);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(additiveBlending, getAdditiveBlending);
|
||||
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
@ -392,6 +396,7 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaStart, setAlphaStart);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaFinish, setAlphaFinish);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(additiveBlending, setAdditiveBlending);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
|
@ -483,6 +488,10 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
|
|||
READ_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, float, setAzimuthFinish);
|
||||
}
|
||||
|
||||
if (args.bitstreamVersion >= VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING) {
|
||||
READ_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, bool, setAdditiveBlending);
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
@ -520,6 +529,7 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea
|
|||
requestedProperties += PROP_POLAR_FINISH;
|
||||
requestedProperties += PROP_AZIMUTH_START;
|
||||
requestedProperties += PROP_AZIMUTH_FINISH;
|
||||
requestedProperties += PROP_ADDITIVE_BLENDING;
|
||||
|
||||
return requestedProperties;
|
||||
}
|
||||
|
@ -562,6 +572,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData,
|
|||
APPEND_ENTITY_PROPERTY(PROP_POLAR_FINISH, getPolarFinish());
|
||||
APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_START, getAzimuthStart());
|
||||
APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, getAzimuthFinish());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ADDITIVE_BLENDING, getAdditiveBlending());
|
||||
}
|
||||
|
||||
bool ParticleEffectEntityItem::isEmittingParticles() const {
|
||||
|
|
|
@ -209,6 +209,14 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
static const bool DEFAULT_ADDITIVE_BLENDING;
|
||||
bool getAdditiveBlending() const { return _additiveBlending; }
|
||||
void setAdditiveBlending(bool additiveBlending) {
|
||||
_additiveBlending = additiveBlending;
|
||||
}
|
||||
|
||||
virtual bool supportsDetailedRayIntersection() const { return false; }
|
||||
|
||||
protected:
|
||||
|
||||
bool isAnimatingSomething() const;
|
||||
|
@ -219,7 +227,6 @@ protected:
|
|||
void extendBounds(const glm::vec3& point);
|
||||
void integrateParticle(quint32 index, float deltaTime);
|
||||
quint32 getLivingParticleCount() const;
|
||||
|
||||
// the properties of this entity
|
||||
rgbColor _color;
|
||||
xColor _colorStart = DEFAULT_COLOR;
|
||||
|
@ -284,6 +291,8 @@ protected:
|
|||
// bounding volume
|
||||
glm::vec3 _particleMaxBound;
|
||||
glm::vec3 _particleMinBound;
|
||||
|
||||
bool _additiveBlending;
|
||||
};
|
||||
|
||||
#endif // hifi_ParticleEffectEntityItem_h
|
||||
|
|
|
@ -108,19 +108,13 @@ void SixenseManager::setSixenseFilter(bool filter) {
|
|||
|
||||
void SixenseManager::pluginUpdate(float deltaTime, bool jointsCaptured) {
|
||||
_inputDevice->update(deltaTime, jointsCaptured);
|
||||
if (_inputDevice->_calibrationState == CALIBRATION_STATE_COMPLETE) {
|
||||
if (_inputDevice->_requestReset) {
|
||||
_container->requestReset();
|
||||
_inputDevice->_calibrationState = CALIBRATION_STATE_IDLE;
|
||||
_inputDevice->_requestReset = false;
|
||||
}
|
||||
}
|
||||
|
||||
void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) {
|
||||
// FIXME - Some of the code in update() will crash if you haven't actually activated the
|
||||
// plugin. But we want register with the UserInputMapper if we don't call this.
|
||||
// We need to clean this up.
|
||||
//if (!_activated) {
|
||||
// return;
|
||||
//}
|
||||
#ifdef HAVE_SIXENSE
|
||||
_buttonPressedMap.clear();
|
||||
|
||||
|
@ -153,14 +147,14 @@ void SixenseManager::InputDevice::update(float deltaTime, bool jointsCaptured) {
|
|||
int maxControllers = sixenseGetMaxControllers();
|
||||
|
||||
// we only support two controllers
|
||||
sixenseControllerData controllers[2];
|
||||
SixenseControllerData controllers[2];
|
||||
|
||||
int numActiveControllers = 0;
|
||||
for (int i = 0; i < maxControllers && numActiveControllers < 2; i++) {
|
||||
if (!sixenseIsControllerEnabled(i)) {
|
||||
continue;
|
||||
}
|
||||
sixenseControllerData* data = controllers + numActiveControllers;
|
||||
SixenseControllerData* data = controllers + numActiveControllers;
|
||||
++numActiveControllers;
|
||||
sixenseGetNewestData(i, data);
|
||||
|
||||
|
@ -221,21 +215,23 @@ static const float MINIMUM_ARM_REACH = 0.3f; // meters
|
|||
static const float MAXIMUM_NOISE_LEVEL = 0.05f; // meters
|
||||
static const quint64 LOCK_DURATION = USECS_PER_SECOND / 4; // time for lock to be acquired
|
||||
|
||||
void SixenseManager::InputDevice::updateCalibration(void* controllersX) {
|
||||
auto controllers = reinterpret_cast<sixenseControllerData*>(controllersX);
|
||||
const sixenseControllerData* dataLeft = controllers;
|
||||
const sixenseControllerData* dataRight = controllers + 1;
|
||||
static bool calibrationRequested(SixenseControllerData* controllers) {
|
||||
return (controllers[0].buttons == BUTTON_FWD && controllers[1].buttons == BUTTON_FWD);
|
||||
}
|
||||
|
||||
// calibration only happpens while both hands are holding BUTTON_FORWARD
|
||||
if (dataLeft->buttons != BUTTON_FWD || dataRight->buttons != BUTTON_FWD) {
|
||||
if (_calibrationState == CALIBRATION_STATE_IDLE) {
|
||||
return;
|
||||
}
|
||||
void SixenseManager::InputDevice::updateCalibration(SixenseControllerData* controllers) {
|
||||
const SixenseControllerData* dataLeft = controllers;
|
||||
const SixenseControllerData* dataRight = controllers + 1;
|
||||
|
||||
// Calibration buttons aren't set, so check the state, and request a reset if necessary.
|
||||
if (!calibrationRequested(controllers)) {
|
||||
switch (_calibrationState) {
|
||||
case CALIBRATION_STATE_COMPLETE:
|
||||
{
|
||||
case CALIBRATION_STATE_IDLE:
|
||||
return;
|
||||
|
||||
case CALIBRATION_STATE_COMPLETE: {
|
||||
// compute calibration results
|
||||
_avatarPosition = - 0.5f * (_reachLeft + _reachRight); // neck is midway between right and left hands
|
||||
_avatarPosition = -0.5f * (_reachLeft + _reachRight); // neck is midway between right and left hands
|
||||
glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft);
|
||||
glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, Vectors::UNIT_Y));
|
||||
xAxis = glm::normalize(glm::cross(Vectors::UNIT_Y, zAxis));
|
||||
|
@ -243,16 +239,19 @@ void SixenseManager::InputDevice::updateCalibration(void* controllersX) {
|
|||
const float Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR = -0.3f;
|
||||
_avatarPosition.y += Y_OFFSET_CALIBRATED_HANDS_TO_AVATAR;
|
||||
qCDebug(inputplugins, "succeess: sixense calibration");
|
||||
_requestReset = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
_calibrationState = CALIBRATION_STATE_IDLE;
|
||||
qCDebug(inputplugins, "failed: sixense calibration");
|
||||
break;
|
||||
}
|
||||
|
||||
_calibrationState = CALIBRATION_STATE_IDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
// Calibration buttons are set, continue calibration work
|
||||
// NOTE: Sixense API returns pos data in millimeters but we IMMEDIATELY convert to meters.
|
||||
const float* pos = dataLeft->pos;
|
||||
glm::vec3 positionLeft(pos[0], pos[1], pos[2]);
|
||||
|
@ -261,6 +260,7 @@ void SixenseManager::InputDevice::updateCalibration(void* controllersX) {
|
|||
glm::vec3 positionRight(pos[0], pos[1], pos[2]);
|
||||
positionRight *= METERS_PER_MILLIMETER;
|
||||
|
||||
// Gather initial calibration data
|
||||
if (_calibrationState == CALIBRATION_STATE_IDLE) {
|
||||
float reach = glm::distance(positionLeft, positionRight);
|
||||
if (reach > 2.0f * MINIMUM_ARM_REACH) {
|
||||
|
@ -308,9 +308,6 @@ void SixenseManager::InputDevice::focusOutEvent() {
|
|||
_buttonPressedMap.clear();
|
||||
};
|
||||
|
||||
void SixenseManager::InputDevice::handleAxisEvent(float stickX, float stickY, float trigger, bool left) {
|
||||
}
|
||||
|
||||
void SixenseManager::InputDevice::handleButtonEvent(unsigned int buttons, bool left) {
|
||||
using namespace controller;
|
||||
if (buttons & BUTTON_0) {
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
#include "InputPlugin.h"
|
||||
|
||||
struct _sixenseControllerData;
|
||||
using SixenseControllerData = _sixenseControllerData;
|
||||
|
||||
// Handles interaction with the Sixense SDK (e.g., Razer Hydra).
|
||||
class SixenseManager : public InputPlugin {
|
||||
Q_OBJECT
|
||||
|
@ -65,9 +68,8 @@ private:
|
|||
virtual void focusOutEvent() override;
|
||||
|
||||
void handleButtonEvent(unsigned int buttons, bool left);
|
||||
void handleAxisEvent(float x, float y, float trigger, bool left);
|
||||
void handlePoseEvent(float deltaTime, glm::vec3 position, glm::quat rotation, bool left);
|
||||
void updateCalibration(void* controllers);
|
||||
void updateCalibration(SixenseControllerData* controllers);
|
||||
|
||||
friend class SixenseManager;
|
||||
|
||||
|
@ -79,6 +81,7 @@ private:
|
|||
glm::quat _avatarRotation; // in hydra-frame
|
||||
|
||||
float _lastDistance;
|
||||
bool _requestReset { false };
|
||||
// these are measured values used to compute the calibration results
|
||||
quint64 _lockExpiry;
|
||||
glm::vec3 _averageLeft;
|
||||
|
|
|
@ -38,7 +38,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::EntityAdd:
|
||||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
return VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP_BIS;
|
||||
return VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING;
|
||||
case PacketType::AvatarData:
|
||||
case PacketType::BulkAvatarData:
|
||||
default:
|
||||
|
|
|
@ -145,5 +145,6 @@ const PacketVersion VERSION_ENTITIES_PROTOCOL_CHANNELS = 45;
|
|||
const PacketVersion VERSION_ENTITIES_ANIMATION_PROPERTIES_GROUP = 46;
|
||||
const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP = 47;
|
||||
const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP_BIS = 48;
|
||||
const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49;
|
||||
|
||||
#endif // hifi_PacketHeaders_h
|
||||
|
|
|
@ -887,8 +887,8 @@
|
|||
|
||||
function createPingPongBallGun() {
|
||||
var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx';
|
||||
var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj';
|
||||
|
||||
var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_convex.obj';
|
||||
var COLLISION_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/plastic_impact.L.wav';
|
||||
var position = {
|
||||
x: 548.6,
|
||||
y: 495.4,
|
||||
|
@ -900,7 +900,8 @@
|
|||
var pingPongGun = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: MODEL_URL,
|
||||
shapeType: 'box',
|
||||
shapeType: 'compound',
|
||||
compoundShapeURL: COLLISION_SOUND_URL,
|
||||
script: pingPongScriptURL,
|
||||
position: position,
|
||||
rotation: rotation,
|
||||
|
@ -915,6 +916,7 @@
|
|||
z: 0.47
|
||||
},
|
||||
collisionsWillMove: true,
|
||||
collisionSoundURL: COLLISION_SOUND_URL,
|
||||
userData: JSON.stringify({
|
||||
resetMe: {
|
||||
resetMe: true
|
||||
|
|
|
@ -869,8 +869,8 @@ MasterReset = function() {
|
|||
|
||||
function createPingPongBallGun() {
|
||||
var MODEL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun.fbx';
|
||||
var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_collision_hull.obj';
|
||||
|
||||
var COLLISION_HULL_URL = 'http://hifi-public.s3.amazonaws.com/models/ping_pong_gun/ping_pong_gun_convex.obj';
|
||||
var COLLISION_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/Collisions-otherorganic/plastic_impact.L.wav';
|
||||
var position = {
|
||||
x: 548.6,
|
||||
y: 495.4,
|
||||
|
@ -882,7 +882,8 @@ MasterReset = function() {
|
|||
var pingPongGun = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: MODEL_URL,
|
||||
shapeType: 'box',
|
||||
shapeType: 'compound',
|
||||
compoundShapeURL:COLLISION_SOUND_URL,
|
||||
script: pingPongScriptURL,
|
||||
position: position,
|
||||
rotation: rotation,
|
||||
|
@ -897,6 +898,7 @@ MasterReset = function() {
|
|||
z: 0.47
|
||||
},
|
||||
collisionsWillMove: true,
|
||||
collisionSoundURL: COLLISION_SOUND_URL,
|
||||
userData: JSON.stringify({
|
||||
resetMe: {
|
||||
resetMe: true
|
||||
|
|
Loading…
Reference in a new issue