mirror of
https://github.com/lubosz/overte.git
synced 2025-08-07 16:41:02 +02:00
Merge remote-tracking branch 'upstream/master' into quick_audio_PR
This commit is contained in:
commit
35419eb939
62 changed files with 1136 additions and 349 deletions
7
BUILD.md
7
BUILD.md
|
@ -24,9 +24,12 @@ In order for CMake to find the Qt5 find modules, you will need to set an ENV var
|
||||||
|
|
||||||
For example, a Qt5 5.2.0 installation to /usr/local/qt5 would require that QT_CMAKE_PREFIX_PATH be set with the following command. This can either be entered directly into your shell session before you build or in your shell profile (e.g.: ~/.bash_profile, ~/.bashrc, ~/.zshrc - this depends on your shell and environment).
|
For example, a Qt5 5.2.0 installation to /usr/local/qt5 would require that QT_CMAKE_PREFIX_PATH be set with the following command. This can either be entered directly into your shell session before you build or in your shell profile (e.g.: ~/.bash_profile, ~/.bashrc, ~/.zshrc - this depends on your shell and environment).
|
||||||
|
|
||||||
export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.2.0/clang_64/lib/cmake/
|
The path it needs to be set to will depend on where and how Qt5 was installed. e.g.
|
||||||
|
|
||||||
|
export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.2.0/clang_64/lib/cmake/
|
||||||
|
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.2.1/lib/cmake
|
||||||
|
export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake
|
||||||
|
|
||||||
The path it needs to be set to will depend on where and how Qt5 was installed.
|
|
||||||
|
|
||||||
####Generating build files
|
####Generating build files
|
||||||
Create a build directory in the root of your checkout and then run the CMake build from there. This will keep the rest of the directory clean.
|
Create a build directory in the root of your checkout and then run the CMake build from there. This will keep the rest of the directory clean.
|
||||||
|
|
|
@ -32,14 +32,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
# Instruct CMake to run moc automatically when needed.
|
# Instruct CMake to run moc automatically when needed.
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
if (APPLE)
|
|
||||||
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
|
|
||||||
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
|
|
||||||
if (DARWIN_VERSION GREATER 12)
|
|
||||||
set(CMAKE_CXX_FLAGS "-stdlib=libstdc++")
|
|
||||||
endif (DARWIN_VERSION GREATER 12)
|
|
||||||
endif (APPLE)
|
|
||||||
|
|
||||||
# targets not supported on windows
|
# targets not supported on windows
|
||||||
if (NOT WIN32)
|
if (NOT WIN32)
|
||||||
add_subdirectory(animation-server)
|
add_subdirectory(animation-server)
|
||||||
|
|
|
@ -87,13 +87,14 @@ void MetavoxelServer::sendDeltas() {
|
||||||
int elapsed = now - _lastSend;
|
int elapsed = now - _lastSend;
|
||||||
_lastSend = now;
|
_lastSend = now;
|
||||||
|
|
||||||
_sendTimer.start(qMax(0, 2 * SEND_INTERVAL - elapsed));
|
_sendTimer.start(qMax(0, 2 * SEND_INTERVAL - qMax(elapsed, SEND_INTERVAL)));
|
||||||
}
|
}
|
||||||
|
|
||||||
MetavoxelSession::MetavoxelSession(const SharedNodePointer& node, MetavoxelServer* server) :
|
MetavoxelSession::MetavoxelSession(const SharedNodePointer& node, MetavoxelServer* server) :
|
||||||
Endpoint(node, new PacketRecord(), NULL),
|
Endpoint(node, new PacketRecord(), NULL),
|
||||||
_server(server),
|
_server(server),
|
||||||
_reliableDeltaChannel(NULL) {
|
_reliableDeltaChannel(NULL),
|
||||||
|
_reliableDeltaID(0) {
|
||||||
|
|
||||||
connect(&_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)), SLOT(handleMessage(const QVariant&)));
|
connect(&_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)), SLOT(handleMessage(const QVariant&)));
|
||||||
connect(&_sequencer, SIGNAL(sendAcknowledged(int)), SLOT(checkReliableDeltaReceived()));
|
connect(&_sequencer, SIGNAL(sendAcknowledged(int)), SLOT(checkReliableDeltaReceived()));
|
||||||
|
@ -108,9 +109,7 @@ void MetavoxelSession::update() {
|
||||||
}
|
}
|
||||||
// if we're sending a reliable delta, wait until it's acknowledged
|
// if we're sending a reliable delta, wait until it's acknowledged
|
||||||
if (_reliableDeltaChannel) {
|
if (_reliableDeltaChannel) {
|
||||||
Bitstream& out = _sequencer.startPacket();
|
sendPacketGroup();
|
||||||
out << QVariant::fromValue(MetavoxelDeltaPendingMessage());
|
|
||||||
_sequencer.endPacket();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Bitstream& out = _sequencer.startPacket();
|
Bitstream& out = _sequencer.startPacket();
|
||||||
|
@ -134,12 +133,16 @@ void MetavoxelSession::update() {
|
||||||
|
|
||||||
// go back to the beginning with the current packet and note that there's a delta pending
|
// go back to the beginning with the current packet and note that there's a delta pending
|
||||||
_sequencer.getOutputStream().getUnderlying().device()->seek(start);
|
_sequencer.getOutputStream().getUnderlying().device()->seek(start);
|
||||||
out << QVariant::fromValue(MetavoxelDeltaPendingMessage());
|
MetavoxelDeltaPendingMessage msg = { ++_reliableDeltaID };
|
||||||
|
out << QVariant::fromValue(msg);
|
||||||
_sequencer.endPacket();
|
_sequencer.endPacket();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
_sequencer.endPacket();
|
_sequencer.endPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// perhaps send additional packets to fill out the group
|
||||||
|
sendPacketGroup(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MetavoxelSession::handleMessage(const QVariant& message, Bitstream& in) {
|
void MetavoxelSession::handleMessage(const QVariant& message, Bitstream& in) {
|
||||||
|
@ -176,3 +179,17 @@ void MetavoxelSession::checkReliableDeltaReceived() {
|
||||||
_reliableDeltaData = MetavoxelData();
|
_reliableDeltaData = MetavoxelData();
|
||||||
_reliableDeltaChannel = NULL;
|
_reliableDeltaChannel = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MetavoxelSession::sendPacketGroup(int alreadySent) {
|
||||||
|
int additionalPackets = _sequencer.notePacketGroup() - alreadySent;
|
||||||
|
for (int i = 0; i < additionalPackets; i++) {
|
||||||
|
Bitstream& out = _sequencer.startPacket();
|
||||||
|
if (_reliableDeltaChannel) {
|
||||||
|
MetavoxelDeltaPendingMessage msg = { _reliableDeltaID };
|
||||||
|
out << QVariant::fromValue(msg);
|
||||||
|
} else {
|
||||||
|
out << QVariant();
|
||||||
|
}
|
||||||
|
_sequencer.endPacket();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -74,6 +74,8 @@ private slots:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void sendPacketGroup(int alreadySent = 0);
|
||||||
|
|
||||||
MetavoxelServer* _server;
|
MetavoxelServer* _server;
|
||||||
|
|
||||||
MetavoxelLOD _lod;
|
MetavoxelLOD _lod;
|
||||||
|
@ -83,6 +85,7 @@ private:
|
||||||
MetavoxelData _reliableDeltaData;
|
MetavoxelData _reliableDeltaData;
|
||||||
MetavoxelLOD _reliableDeltaLOD;
|
MetavoxelLOD _reliableDeltaLOD;
|
||||||
Bitstream::WriteMappings _reliableDeltaWriteMappings;
|
Bitstream::WriteMappings _reliableDeltaWriteMappings;
|
||||||
|
int _reliableDeltaID;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_MetavoxelServer_h
|
#endif // hifi_MetavoxelServer_h
|
||||||
|
|
|
@ -26,8 +26,8 @@ else ()
|
||||||
set(RTMIDI_SEARCH_DIRS "${RTMIDI_ROOT_DIR}" "$ENV{HIFI_LIB_DIR}/rtmidi")
|
set(RTMIDI_SEARCH_DIRS "${RTMIDI_ROOT_DIR}" "$ENV{HIFI_LIB_DIR}/rtmidi")
|
||||||
|
|
||||||
find_path(RTMIDI_INCLUDE_DIR RtMidi.h PATH_SUFFIXES include HINTS ${RTMIDI_SEARCH_DIRS})
|
find_path(RTMIDI_INCLUDE_DIR RtMidi.h PATH_SUFFIXES include HINTS ${RTMIDI_SEARCH_DIRS})
|
||||||
find_file(RTMIDI_CPP NAMES RtMidi.cpp PATH_SUFFIXES src HINTS ${RTMIDI_SEARCH_DIRS})
|
find_library(RTMIDI_LIBRARY NAMES rtmidi PATH_SUFFIXES lib HINTS ${RTMIDI_SEARCH_DIRS})
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
find_package_handle_standard_args(RTMIDI DEFAULT_MSG RTMIDI_INCLUDE_DIR RTMIDI_CPP)
|
find_package_handle_standard_args(RTMIDI DEFAULT_MSG RTMIDI_INCLUDE_DIR RTMIDI_LIBRARY)
|
||||||
endif ()
|
endif ()
|
126
examples/avatarLocalLight.js
Normal file
126
examples/avatarLocalLight.js
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
//
|
||||||
|
// avatarLocalLight.js
|
||||||
|
//
|
||||||
|
// Created by Tony Peng on July 2nd, 2014
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Set the local light direction and color on the avatar
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
var localLightDirections = [ {x: 1.0, y:0.0, z: 0.0}, {x: 0.0, y:1.0, z: 1.0}, {x: 0.0, y:0.0, z: 1.0}, {x: 1.0, y:1.0, z: 1.0} ];
|
||||||
|
var localLightColors = [ {x: 0.0, y:0.0, z: 0.0}, {x: 0.0, y:0.0, z: 0.0}, {x: 0.0, y:0.0, z: 0.0}, {x: 0.0, y:0.0, z: 0.0} ];
|
||||||
|
|
||||||
|
var currentSelection = 0;
|
||||||
|
var currentNumLights = 1;
|
||||||
|
var maxNumLights = 2;
|
||||||
|
|
||||||
|
function keyPressEvent(event) {
|
||||||
|
|
||||||
|
var choice = parseInt(event.text);
|
||||||
|
|
||||||
|
if (event.text == "1") {
|
||||||
|
currentSelection = 0;
|
||||||
|
print("light election = " + currentSelection);
|
||||||
|
}
|
||||||
|
else if (event.text == "2" ) {
|
||||||
|
currentSelection = 1;
|
||||||
|
print("light selection = " + currentSelection);
|
||||||
|
}
|
||||||
|
else if (event.text == "3" ) {
|
||||||
|
currentSelection = 2;
|
||||||
|
print("light selection = " + currentSelection);
|
||||||
|
}
|
||||||
|
else if (event.text == "4" ) {
|
||||||
|
currentSelection = 3;
|
||||||
|
print("light selection = " + currentSelection);
|
||||||
|
}
|
||||||
|
else if (event.text == "5" ) {
|
||||||
|
localLightColors[currentSelection].x += 0.01;
|
||||||
|
if ( localLightColors[currentSelection].x > 1.0) {
|
||||||
|
localLightColors[currentSelection].x = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyAvatar.setLocalLightColor(localLightColors[currentSelection], currentSelection);
|
||||||
|
}
|
||||||
|
else if (event.text == "6" ) {
|
||||||
|
localLightColors[currentSelection].y += 0.01;
|
||||||
|
if ( localLightColors[currentSelection].y > 1.0) {
|
||||||
|
localLightColors[currentSelection].y = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyAvatar.setLocalLightColor(localLightColors[currentSelection], currentSelection);
|
||||||
|
}
|
||||||
|
else if (event.text == "7" ) {
|
||||||
|
localLightColors[currentSelection].z += 0.01;
|
||||||
|
if ( localLightColors[currentSelection].z > 1.0) {
|
||||||
|
localLightColors[currentSelection].z = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyAvatar.setLocalLightColor(localLightColors[currentSelection], currentSelection);
|
||||||
|
}
|
||||||
|
else if (event.text == "8" ) {
|
||||||
|
localLightDirections[currentSelection].x += 0.01;
|
||||||
|
if (localLightDirections[currentSelection].x > 1.0) {
|
||||||
|
localLightDirections[currentSelection].x = -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection);
|
||||||
|
}
|
||||||
|
else if (event.text == "9" ) {
|
||||||
|
localLightDirections[currentSelection].x -= 0.01;
|
||||||
|
if (localLightDirections[currentSelection].x < -1.0) {
|
||||||
|
localLightDirections[currentSelection].x = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection);
|
||||||
|
}
|
||||||
|
else if (event.text == "[" ) {
|
||||||
|
localLightDirections[currentSelection].y += 0.01;
|
||||||
|
if (localLightDirections[currentSelection].y > 1.0) {
|
||||||
|
localLightDirections[currentSelection].y = -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection);
|
||||||
|
}
|
||||||
|
else if (event.text == "]" ) {
|
||||||
|
localLightDirections[currentSelection].y -= 0.01;
|
||||||
|
if (localLightDirections[currentSelection].y < -1.0) {
|
||||||
|
localLightDirections[currentSelection].y = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
MyAvatar.setLocalLightDirection(localLightDirections[currentSelection], currentSelection);
|
||||||
|
}
|
||||||
|
else if (event.text == "," ) {
|
||||||
|
if (currentNumLights + 1 <= maxNumLights) {
|
||||||
|
var darkGrayColor = {x:0.3, y:0.3, z:0.3};
|
||||||
|
|
||||||
|
// default light
|
||||||
|
localLightColors[currentNumLights].x = darkGrayColor.x;
|
||||||
|
localLightColors[currentNumLights].y = darkGrayColor.y;
|
||||||
|
localLightColors[currentNumLights].z = darkGrayColor.z;
|
||||||
|
|
||||||
|
MyAvatar.addLocalLight();
|
||||||
|
MyAvatar.setLocalLightColor(localLightColors[currentNumLights], currentNumLights);
|
||||||
|
MyAvatar.setLocalLightDirection(localLightDirections[currentNumLights], currentNumLights);
|
||||||
|
|
||||||
|
++currentNumLights;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event.text == "." ) {
|
||||||
|
if (currentNumLights - 1 >= 0 ) {
|
||||||
|
|
||||||
|
// no light contribution
|
||||||
|
localLightColors[currentNumLights - 1].x = 0.0;
|
||||||
|
localLightColors[currentNumLights - 1].y = 0.0;
|
||||||
|
localLightColors[currentNumLights - 1].z = 0.0;
|
||||||
|
|
||||||
|
MyAvatar.removeLocalLight();
|
||||||
|
--currentNumLights;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller.keyPressEvent.connect(keyPressEvent);
|
173
examples/clap.js
173
examples/clap.js
|
@ -1,72 +1,147 @@
|
||||||
//
|
//
|
||||||
// cameraExample.js
|
// clap.js
|
||||||
// examples
|
// examples
|
||||||
//
|
//
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
//
|
//
|
||||||
// This sample script watches your hydra hands and makes clapping sound when they come close together fast
|
// This sample script watches your hydra hands and makes clapping sound when they come close together fast,
|
||||||
|
// and also watches for the 'shift' key and claps when that key is pressed. Clapping multiple times by pressing
|
||||||
|
// the shift key again makes the animation and sound match your pace of clapping.
|
||||||
//
|
//
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
function length(v) {
|
var clapAnimation = "https://s3-us-west-1.amazonaws.com/highfidelity-public/animations/ClapAnimations/ClapHands_Standing.fbx";
|
||||||
return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
|
var ANIMATION_FRAMES_PER_CLAP = 10.0;
|
||||||
}
|
var startEndFrames = [];
|
||||||
|
startEndFrames.push({ start: 0, end: 10});
|
||||||
|
startEndFrames.push({ start: 10, end: 20});
|
||||||
|
startEndFrames.push({ start: 20, end: 30});
|
||||||
|
startEndFrames.push({ start: 30, end: 40});
|
||||||
|
startEndFrames.push({ start: 41, end: 51});
|
||||||
|
startEndFrames.push({ start: 53, end: 0});
|
||||||
|
|
||||||
|
var lastClapFrame = 0;
|
||||||
|
var lastAnimFrame = 0;
|
||||||
|
|
||||||
function printVector(v) {
|
var claps = [];
|
||||||
print(v.x + ", " + v.y + ", " + v.z + "\n");
|
claps.push(new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/claps/BClap1Rvb.wav"));
|
||||||
}
|
claps.push(new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/claps/BClap2Rvb.wav"));
|
||||||
|
claps.push(new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/claps/BClap3Rvb.wav"));
|
||||||
|
claps.push(new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/claps/BClap4Rvb.wav"));
|
||||||
|
claps.push(new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/claps/BClap5Rvb.wav"));
|
||||||
|
claps.push(new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/claps/BClap6Rvb.wav"));
|
||||||
|
claps.push(new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/claps/BClap7Rvb.wav"));
|
||||||
|
claps.push(new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/claps/BClap8Rvb.wav"));
|
||||||
|
claps.push(new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/claps/BClap9Rvb.wav"));
|
||||||
|
claps.push(new Sound("http://highfidelity-public.s3-us-west-1.amazonaws.com/sounds/claps/BClap10Rvb.wav"));
|
||||||
|
var numberOfSounds = claps.length;
|
||||||
|
|
||||||
function vMinus(a, b) {
|
var clappingNow = false;
|
||||||
var rval = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
|
var collectedClicks = 0;
|
||||||
return rval;
|
|
||||||
}
|
|
||||||
|
|
||||||
// First, load the clap sound from a URL
|
var clickStartTime, clickEndTime;
|
||||||
var clap1 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap1.raw");
|
var clickClappingNow = false;
|
||||||
var clap2 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap2.raw");
|
var CLAP_START_RATE = 15.0;
|
||||||
var clap3 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap3.raw");
|
var clapRate = CLAP_START_RATE;
|
||||||
var clap4 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap4.raw");
|
var startedTimer = false;
|
||||||
var clap5 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap5.raw");
|
|
||||||
var clap6 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap6.raw");
|
|
||||||
|
|
||||||
var clapping = new Array();
|
|
||||||
clapping[0] = false;
|
|
||||||
clapping[1] = false;
|
|
||||||
|
|
||||||
function maybePlaySound(deltaTime) {
|
function maybePlaySound(deltaTime) {
|
||||||
// Set the location and other info for the sound to play
|
// Set the location and other info for the sound to play
|
||||||
var palm1Position = Controller.getSpatialControlPosition(0);
|
|
||||||
var palm2Position = Controller.getSpatialControlPosition(2);
|
|
||||||
var distanceBetween = length(vMinus(palm1Position, palm2Position));
|
|
||||||
|
|
||||||
for (var palm = 0; palm < 2; palm++) {
|
var animationDetails = MyAvatar.getAnimationDetails(clapAnimation);
|
||||||
var palmVelocity = Controller.getSpatialControlVelocity(palm * 2 + 1);
|
|
||||||
var speed = length(palmVelocity);
|
|
||||||
|
|
||||||
const CLAP_SPEED = 0.2;
|
|
||||||
const CLAP_DISTANCE = 0.2;
|
|
||||||
|
|
||||||
if (!clapping[palm] && (distanceBetween < CLAP_DISTANCE) && (speed > CLAP_SPEED)) {
|
var frame = Math.floor(animationDetails.frameIndex);
|
||||||
var options = new AudioInjectionOptions();
|
|
||||||
options.position = palm1Position;
|
if (frame != lastAnimFrame) {
|
||||||
options.volume = speed / 2.0;
|
lastAnimFrame = frame;
|
||||||
if (options.volume > 1.0) options.volume = 1.0;
|
|
||||||
which = Math.floor((Math.random() * 6) + 1);
|
|
||||||
if (which == 1) { Audio.playSound(clap1, options); }
|
|
||||||
else if (which == 2) { Audio.playSound(clap2, options); }
|
|
||||||
else if (which == 3) { Audio.playSound(clap3, options); }
|
|
||||||
else if (which == 4) { Audio.playSound(clap4, options); }
|
|
||||||
else if (which == 5) { Audio.playSound(clap5, options); }
|
|
||||||
else { Audio.playSound(clap6, options); }
|
|
||||||
Audio.playSound(clap, options);
|
|
||||||
clapping[palm] = true;
|
|
||||||
} else if (clapping[palm] && (speed < (CLAP_SPEED / 4.0))) {
|
|
||||||
clapping[palm] = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < startEndFrames.length; i++) {
|
||||||
|
if (frame == startEndFrames[i].start && (frame != lastClapFrame)) {
|
||||||
|
playClap(1.0, Camera.getPosition());
|
||||||
|
lastClapFrame = frame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var palm1Position = MyAvatar.getLeftPalmPosition();
|
||||||
|
var palm2Position = MyAvatar.getRightPalmPosition();
|
||||||
|
var distanceBetween = Vec3.length(Vec3.subtract(palm1Position, palm2Position));
|
||||||
|
|
||||||
|
var palm1Velocity = Controller.getSpatialControlVelocity(1);
|
||||||
|
var palm2Velocity = Controller.getSpatialControlVelocity(3);
|
||||||
|
var closingVelocity = Vec3.length(Vec3.subtract(palm1Velocity, palm2Velocity));
|
||||||
|
|
||||||
|
const CLAP_SPEED = 0.7;
|
||||||
|
const CLAP_DISTANCE = 0.15;
|
||||||
|
|
||||||
|
if ((closingVelocity > CLAP_SPEED) && (distanceBetween < CLAP_DISTANCE) && !clappingNow) {
|
||||||
|
var volume = closingVelocity / 2.0;
|
||||||
|
if (volume > 1.0) volume = 1.0;
|
||||||
|
playClap(volume, palm1Position);
|
||||||
|
clappingNow = true;
|
||||||
|
} else if (clappingNow && (distanceBetween > CLAP_DISTANCE * 1.2)) {
|
||||||
|
clappingNow = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function playClap(volume, position) {
|
||||||
|
var options = new AudioInjectionOptions();
|
||||||
|
options.position = position;
|
||||||
|
options.volume = 1.0;
|
||||||
|
var clip = Math.floor(Math.random() * numberOfSounds);
|
||||||
|
Audio.playSound(claps[clip], options);
|
||||||
|
}
|
||||||
|
|
||||||
|
var FASTEST_CLAP_INTERVAL = 100.0;
|
||||||
|
var SLOWEST_CLAP_INTERVAL = 2000.0;
|
||||||
|
|
||||||
|
Controller.keyPressEvent.connect(function(event) {
|
||||||
|
if(event.text == "SHIFT") {
|
||||||
|
if (!clickClappingNow) {
|
||||||
|
clickClappingNow = true;
|
||||||
|
clickStartTime = new Date();
|
||||||
|
playClap(1.0, Camera.getPosition());
|
||||||
|
lastClapFrame = 0;
|
||||||
|
MyAvatar.startAnimation(clapAnimation, clapRate, 1.0, true, false);
|
||||||
|
} else {
|
||||||
|
// Adjust animation speed for measured clicking interval
|
||||||
|
clickEndTime = new Date();
|
||||||
|
var milliseconds = clickEndTime - clickStartTime;
|
||||||
|
clickStartTime = new Date();
|
||||||
|
if ((milliseconds < SLOWEST_CLAP_INTERVAL) && (milliseconds > FASTEST_CLAP_INTERVAL)) {
|
||||||
|
clapRate = ANIMATION_FRAMES_PER_CLAP * (1000.0 / milliseconds);
|
||||||
|
playClap(1.0, Camera.getPosition());
|
||||||
|
MyAvatar.stopAnimation(clapAnimation);
|
||||||
|
MyAvatar.startAnimation(clapAnimation, clapRate, 1.0, true, false);
|
||||||
|
}
|
||||||
|
collectedClicks = collectedClicks + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var CLAP_END_WAIT_MSECS = 300;
|
||||||
|
Controller.keyReleaseEvent.connect(function(event) {
|
||||||
|
if (event.text == "SHIFT") {
|
||||||
|
collectedClicks = 0;
|
||||||
|
if (!startedTimer) {
|
||||||
|
collectedClicks = 0;
|
||||||
|
Script.setTimeout(stopClapping, CLAP_END_WAIT_MSECS);
|
||||||
|
startedTimer = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function stopClapping() {
|
||||||
|
if (collectedClicks == 0) {
|
||||||
|
startedTimer = false;
|
||||||
|
MyAvatar.stopAnimation(clapAnimation);
|
||||||
|
clapRate = CLAP_START_RATE;
|
||||||
|
clickClappingNow = false;
|
||||||
|
} else {
|
||||||
|
startedTimer = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Connect a call back that happens every frame
|
// Connect a call back that happens every frame
|
||||||
|
|
72
examples/concertCamera_kims.js
Normal file
72
examples/concertCamera_kims.js
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
//
|
||||||
|
// concertCamera.js
|
||||||
|
//
|
||||||
|
// Created by Philip Rosedale on June 24, 2014
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Move a camera through a series of pre-set locations by pressing number keys
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
var oldMode;
|
||||||
|
var avatarPosition;
|
||||||
|
|
||||||
|
var cameraNumber = 0;
|
||||||
|
var freeCamera = false;
|
||||||
|
|
||||||
|
var cameraLocations = [ {x: 8027.5, y: 237.5, z: 7305.7}, {x: 8027.5, y: 237.5, z: 7306.6}, {x: 8027.5, y: 237.5, z: 7308.0}, {x: 8027.5, y: 237.5, z: 7303.0}, {x: 8030.8, y: 238.6, z: 7311.4}, {x: 8030.9, y: 237.1, z: 7308.0} ];
|
||||||
|
var cameraLookAts = [ {x: 8027.5, y: 237.5, z: 7304.0}, {x: 8027.5, y: 237.5, z: 7305.7}, {x: 8027.5, y: 237.5, z: 7304.0}, {x: 8027.5, y: 237.5, z: 7304.0}, {x: 8027.5, y: 237.5, z: 7304.0}, {x: 8027.5, y: 237.5, z: 7304.0} ];
|
||||||
|
|
||||||
|
function saveCameraState() {
|
||||||
|
oldMode = Camera.getMode();
|
||||||
|
avatarPosition = MyAvatar.position;
|
||||||
|
Camera.setModeShiftPeriod(0.0);
|
||||||
|
Camera.setMode("independent");
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreCameraState() {
|
||||||
|
Camera.stopLooking();
|
||||||
|
Camera.setMode(oldMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function update(deltaTime) {
|
||||||
|
if (freeCamera) {
|
||||||
|
var delta = Vec3.subtract(MyAvatar.position, avatarPosition);
|
||||||
|
if (Vec3.length(delta) > 0.05) {
|
||||||
|
cameraNumber = 0;
|
||||||
|
freeCamera = false;
|
||||||
|
restoreCameraState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function keyPressEvent(event) {
|
||||||
|
|
||||||
|
var choice = parseInt(event.text);
|
||||||
|
|
||||||
|
if ((choice > 0) && (choice <= cameraLocations.length)) {
|
||||||
|
print("camera " + choice);
|
||||||
|
if (!freeCamera) {
|
||||||
|
saveCameraState();
|
||||||
|
freeCamera = true;
|
||||||
|
}
|
||||||
|
Camera.setMode("independent");
|
||||||
|
Camera.setPosition(cameraLocations[choice - 1]);
|
||||||
|
Camera.keepLookingAt(cameraLookAts[choice - 1]);
|
||||||
|
}
|
||||||
|
if (event.text == "ESC") {
|
||||||
|
cameraNumber = 0;
|
||||||
|
freeCamera = false;
|
||||||
|
restoreCameraState();
|
||||||
|
}
|
||||||
|
if (event.text == "0") {
|
||||||
|
// Show camera location in log
|
||||||
|
var cameraLocation = Camera.getPosition();
|
||||||
|
print(cameraLocation.x + ", " + cameraLocation.y + ", " + cameraLocation.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.update.connect(update);
|
||||||
|
Controller.keyPressEvent.connect(keyPressEvent);
|
72
examples/concertCamera_kyrs.js
Normal file
72
examples/concertCamera_kyrs.js
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
//
|
||||||
|
// concertCamera.js
|
||||||
|
//
|
||||||
|
// Created by Philip Rosedale on June 24, 2014
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Move a camera through a series of pre-set locations by pressing number keys
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
var oldMode;
|
||||||
|
var avatarPosition;
|
||||||
|
|
||||||
|
var cameraNumber = 0;
|
||||||
|
var freeCamera = false;
|
||||||
|
|
||||||
|
var cameraLocations = [ {x: 2921.5, y: 251.3, z: 8254.8}, {x: 2921.5, y: 251.3, z: 8254.4}, {x: 2921.5, y: 251.3, z: 8252.2}, {x: 2921.5, y: 251.3, z: 8247.2}, {x: 2921.4, y: 251.3, z: 8255.7} ];
|
||||||
|
var cameraLookAts = [ {x: 2921.5, y: 251.3, z: 8255.7}, {x: 2921.5, y: 251.3, z: 8255.7}, {x: 2921.5, y: 251.3, z: 8255.7}, {x: 2921.5, y: 251.3, z: 8255.7}, {x: 2921.4 , y: 251.3, z: 8255.1} ];
|
||||||
|
|
||||||
|
function saveCameraState() {
|
||||||
|
oldMode = Camera.getMode();
|
||||||
|
avatarPosition = MyAvatar.position;
|
||||||
|
Camera.setModeShiftPeriod(0.0);
|
||||||
|
Camera.setMode("independent");
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreCameraState() {
|
||||||
|
Camera.stopLooking();
|
||||||
|
Camera.setMode(oldMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
function update(deltaTime) {
|
||||||
|
if (freeCamera) {
|
||||||
|
var delta = Vec3.subtract(MyAvatar.position, avatarPosition);
|
||||||
|
if (Vec3.length(delta) > 0.05) {
|
||||||
|
cameraNumber = 0;
|
||||||
|
freeCamera = false;
|
||||||
|
restoreCameraState();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function keyPressEvent(event) {
|
||||||
|
|
||||||
|
var choice = parseInt(event.text);
|
||||||
|
|
||||||
|
if ((choice > 0) && (choice <= cameraLocations.length)) {
|
||||||
|
print("camera " + choice);
|
||||||
|
if (!freeCamera) {
|
||||||
|
saveCameraState();
|
||||||
|
freeCamera = true;
|
||||||
|
}
|
||||||
|
Camera.setMode("independent");
|
||||||
|
Camera.setPosition(cameraLocations[choice - 1]);
|
||||||
|
Camera.keepLookingAt(cameraLookAts[choice - 1]);
|
||||||
|
}
|
||||||
|
if (event.text == "ESC") {
|
||||||
|
cameraNumber = 0;
|
||||||
|
freeCamera = false;
|
||||||
|
restoreCameraState();
|
||||||
|
}
|
||||||
|
if (event.text == "0") {
|
||||||
|
// Show camera location in log
|
||||||
|
var cameraLocation = Camera.getPosition();
|
||||||
|
print(cameraLocation.x + ", " + cameraLocation.y + ", " + cameraLocation.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Script.update.connect(update);
|
||||||
|
Controller.keyPressEvent.connect(keyPressEvent);
|
|
@ -18,13 +18,16 @@ var RIGHT = 1;
|
||||||
var lastLeftFrame = 0;
|
var lastLeftFrame = 0;
|
||||||
var lastRightFrame = 0;
|
var lastRightFrame = 0;
|
||||||
|
|
||||||
var LAST_FRAME = 11.0; // What is the number of the last frame we want to use in the animation?
|
var leftDirection = true;
|
||||||
var SMOOTH_FACTOR = 0.80;
|
var rightDirection = true;
|
||||||
|
|
||||||
|
var LAST_FRAME = 15.0; // What is the number of the last frame we want to use in the animation?
|
||||||
|
var SMOOTH_FACTOR = 0.0;
|
||||||
|
var MAX_FRAMES = 30.0;
|
||||||
|
|
||||||
Script.update.connect(function(deltaTime) {
|
Script.update.connect(function(deltaTime) {
|
||||||
var leftTriggerValue = Math.sqrt(Controller.getTriggerValue(LEFT));
|
var leftTriggerValue = Controller.getTriggerValue(LEFT);
|
||||||
var rightTriggerValue = Math.sqrt(Controller.getTriggerValue(RIGHT));
|
var rightTriggerValue = Controller.getTriggerValue(RIGHT);
|
||||||
|
|
||||||
var leftFrame, rightFrame;
|
var leftFrame, rightFrame;
|
||||||
|
|
||||||
|
@ -32,10 +35,31 @@ Script.update.connect(function(deltaTime) {
|
||||||
leftFrame = (leftTriggerValue * LAST_FRAME) * (1.0 - SMOOTH_FACTOR) + lastLeftFrame * SMOOTH_FACTOR;
|
leftFrame = (leftTriggerValue * LAST_FRAME) * (1.0 - SMOOTH_FACTOR) + lastLeftFrame * SMOOTH_FACTOR;
|
||||||
rightFrame = (rightTriggerValue * LAST_FRAME) * (1.0 - SMOOTH_FACTOR) + lastRightFrame * SMOOTH_FACTOR;
|
rightFrame = (rightTriggerValue * LAST_FRAME) * (1.0 - SMOOTH_FACTOR) + lastRightFrame * SMOOTH_FACTOR;
|
||||||
|
|
||||||
|
if (!leftDirection) {
|
||||||
|
leftFrame = MAX_FRAMES - leftFrame;
|
||||||
|
}
|
||||||
|
if (!rightDirection) {
|
||||||
|
rightFrame = MAX_FRAMES - rightFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((leftTriggerValue == 1.0) && (leftDirection == true)) {
|
||||||
|
leftDirection = false;
|
||||||
|
lastLeftFrame = MAX_FRAMES - leftFrame;
|
||||||
|
} else if ((leftTriggerValue == 0.0) && (leftDirection == false)) {
|
||||||
|
leftDirection = true;
|
||||||
|
lastLeftFrame = leftFrame;
|
||||||
|
}
|
||||||
|
if ((rightTriggerValue == 1.0) && (rightDirection == true)) {
|
||||||
|
rightDirection = false;
|
||||||
|
lastRightFrame = MAX_FRAMES - rightFrame;
|
||||||
|
} else if ((rightTriggerValue == 0.0) && (rightDirection == false)) {
|
||||||
|
rightDirection = true;
|
||||||
|
lastRightFrame = rightFrame;
|
||||||
|
}
|
||||||
|
|
||||||
if ((leftFrame != lastLeftFrame) && leftHandAnimation.length){
|
if ((leftFrame != lastLeftFrame) && leftHandAnimation.length){
|
||||||
MyAvatar.stopAnimation(leftHandAnimation);
|
MyAvatar.stopAnimation(leftHandAnimation);
|
||||||
MyAvatar.startAnimation(leftHandAnimation, 30.0, 1.0, false, true, leftFrame, leftFrame);
|
MyAvatar.startAnimation(leftHandAnimation, 30.0, 1.0, false, true, leftFrame, leftFrame);
|
||||||
}
|
}
|
||||||
if ((rightFrame != lastRightFrame) && rightHandAnimation.length) {
|
if ((rightFrame != lastRightFrame) && rightHandAnimation.length) {
|
||||||
MyAvatar.stopAnimation(rightHandAnimation);
|
MyAvatar.stopAnimation(rightHandAnimation);
|
||||||
|
|
|
@ -111,16 +111,6 @@ if (APPLE)
|
||||||
SET(INTERFACE_SRCS ${INTERFACE_SRCS} "${CMAKE_CURRENT_SOURCE_DIR}/interface.icns")
|
SET(INTERFACE_SRCS ${INTERFACE_SRCS} "${CMAKE_CURRENT_SOURCE_DIR}/interface.icns")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# RtMidi for scripted MIDI control
|
|
||||||
find_package(RtMidi)
|
|
||||||
|
|
||||||
if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI)
|
|
||||||
add_definitions(-DHAVE_RTMIDI)
|
|
||||||
include_directories(SYSTEM ${RTMIDI_INCLUDE_DIR})
|
|
||||||
|
|
||||||
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${RTMIDI_CPP}")
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
# create the executable, make it a bundle on OS X
|
# create the executable, make it a bundle on OS X
|
||||||
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM})
|
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM})
|
||||||
|
|
||||||
|
@ -151,6 +141,7 @@ find_package(Sixense)
|
||||||
find_package(Visage)
|
find_package(Visage)
|
||||||
find_package(ZLIB)
|
find_package(ZLIB)
|
||||||
find_package(Qxmpp)
|
find_package(Qxmpp)
|
||||||
|
find_package(RtMidi)
|
||||||
|
|
||||||
# include the Sixense library for Razer Hydra if available
|
# include the Sixense library for Razer Hydra if available
|
||||||
if (SIXENSE_FOUND AND NOT DISABLE_SIXENSE)
|
if (SIXENSE_FOUND AND NOT DISABLE_SIXENSE)
|
||||||
|
@ -223,11 +214,18 @@ if (QXMPP_FOUND AND NOT DISABLE_QXMPP)
|
||||||
target_link_libraries(${TARGET_NAME} "${QXMPP_LIBRARY}")
|
target_link_libraries(${TARGET_NAME} "${QXMPP_LIBRARY}")
|
||||||
endif (QXMPP_FOUND AND NOT DISABLE_QXMPP)
|
endif (QXMPP_FOUND AND NOT DISABLE_QXMPP)
|
||||||
|
|
||||||
# link CoreMIDI if we're using RtMidi
|
# and with RtMidi for RtMidi control
|
||||||
if (RTMIDI_FOUND AND APPLE)
|
if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI)
|
||||||
find_library(CoreMIDI CoreMIDI)
|
|
||||||
add_definitions(-D__MACOSX_CORE__)
|
add_definitions(-DHAVE_RTMIDI)
|
||||||
target_link_libraries(${TARGET_NAME} ${CoreMIDI})
|
include_directories(SYSTEM ${RTMIDI_INCLUDE_DIR})
|
||||||
|
target_link_libraries(${TARGET_NAME} "${RTMIDI_LIBRARY}")
|
||||||
|
|
||||||
|
if (APPLE)
|
||||||
|
find_library(CoreMIDI CoreMIDI)
|
||||||
|
add_definitions(-D__MACOSX_CORE__)
|
||||||
|
target_link_libraries(${TARGET_NAME} ${CoreMIDI})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# include headers for interface and InterfaceConfig.
|
# include headers for interface and InterfaceConfig.
|
||||||
|
|
4
interface/external/rtmidi/readme.txt
vendored
4
interface/external/rtmidi/readme.txt
vendored
|
@ -7,7 +7,9 @@ Stephen Birarda, June 30, 2014
|
||||||
|
|
||||||
2. Copy RtMidi.h to externals/rtmidi/include.
|
2. Copy RtMidi.h to externals/rtmidi/include.
|
||||||
|
|
||||||
3. Copy RtMidi.cpp to externals/rtmidi/src
|
3. Compile the RtMidi library.
|
||||||
|
|
||||||
|
3. Copy either librtmidi.dylib (dynamic) or librtmidi.a (static) to externals/rtmidi/lib
|
||||||
|
|
||||||
4. Delete your build directory, run cmake and build, and you should be all set.
|
4. Delete your build directory, run cmake and build, and you should be all set.
|
||||||
|
|
||||||
|
|
|
@ -11,9 +11,16 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
// the diffuse texture
|
// the diffuse texture
|
||||||
uniform sampler2D diffuseMap;
|
uniform sampler2D diffuseMap;
|
||||||
|
|
||||||
|
// local lights
|
||||||
|
const int MAX_LOCAL_LIGHTS = 2; // 2 lights for now, will probably need more later on
|
||||||
|
uniform int numLocalLights;
|
||||||
|
uniform vec3 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||||
|
uniform vec3 localLightColors[MAX_LOCAL_LIGHTS];
|
||||||
|
|
||||||
// the interpolated position
|
// the interpolated position
|
||||||
varying vec4 position;
|
varying vec4 position;
|
||||||
|
|
||||||
|
@ -25,8 +32,19 @@ void main(void) {
|
||||||
vec4 normalizedNormal = normalize(normal);
|
vec4 normalizedNormal = normalize(normal);
|
||||||
float diffuse = dot(normalizedNormal, gl_LightSource[0].position);
|
float diffuse = dot(normalizedNormal, gl_LightSource[0].position);
|
||||||
float facingLight = step(0.0, diffuse);
|
float facingLight = step(0.0, diffuse);
|
||||||
|
|
||||||
|
// the local light that is always present
|
||||||
|
vec4 totalLocalLight = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
for (int i = 0; i < numLocalLights; i++) {
|
||||||
|
float localDiffuse = dot(normalizedNormal, vec4(localLightDirections[i], 1.0));
|
||||||
|
float localLight = step(0.0, localDiffuse);
|
||||||
|
float localLightVal = localDiffuse * localLight;
|
||||||
|
|
||||||
|
totalLocalLight += (localLightVal * vec4( localLightColors[i], 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||||
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
|
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight) + totalLocalLight);
|
||||||
|
|
||||||
// compute the specular component (sans exponent)
|
// compute the specular component (sans exponent)
|
||||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
|
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
const int MAX_LOCAL_LIGHTS = 4;
|
||||||
|
|
||||||
// the interpolated position
|
// the interpolated position
|
||||||
varying vec4 position;
|
varying vec4 position;
|
||||||
|
|
||||||
|
@ -37,3 +39,4 @@ void main(void) {
|
||||||
// use standard pipeline transform
|
// use standard pipeline transform
|
||||||
gl_Position = ftransform();
|
gl_Position = ftransform();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,14 @@ void main(void) {
|
||||||
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0);
|
||||||
float diffuse = dot(viewNormal, gl_LightSource[0].position);
|
float diffuse = dot(viewNormal, gl_LightSource[0].position);
|
||||||
float facingLight = step(0.0, diffuse);
|
float facingLight = step(0.0, diffuse);
|
||||||
|
float localDiffuse = dot(viewNormal, gl_LightSource[1].position);
|
||||||
|
float localLight = step(0.0, localDiffuse);
|
||||||
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||||
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
|
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight) + gl_FrontLightProduct[1].diffuse * (localDiffuse * localLight));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// compute the specular component (sans exponent)
|
// compute the specular component (sans exponent)
|
||||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position -
|
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position -
|
||||||
normalize(vec4(vec3(interpolatedPosition), 0.0))), viewNormal));
|
normalize(vec4(vec3(interpolatedPosition), 0.0))), viewNormal));
|
||||||
|
|
|
@ -10,6 +10,11 @@
|
||||||
// Distributed under the Apache License, Version 2.0.
|
// Distributed under the Apache License, Version 2.0.
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
const int MAX_LOCAL_LIGHTS = 2;
|
||||||
|
|
||||||
|
uniform int numLocalLights;
|
||||||
|
uniform vec3 localLightDirections[MAX_LOCAL_LIGHTS];
|
||||||
|
uniform vec3 localLightColors[MAX_LOCAL_LIGHTS];
|
||||||
|
|
||||||
// the diffuse texture
|
// the diffuse texture
|
||||||
uniform sampler2D diffuseMap;
|
uniform sampler2D diffuseMap;
|
||||||
|
@ -28,8 +33,19 @@ void main(void) {
|
||||||
vec4 normalizedNormal = normalize(normal);
|
vec4 normalizedNormal = normalize(normal);
|
||||||
float diffuse = dot(normalizedNormal, gl_LightSource[0].position);
|
float diffuse = dot(normalizedNormal, gl_LightSource[0].position);
|
||||||
float facingLight = step(0.0, diffuse);
|
float facingLight = step(0.0, diffuse);
|
||||||
|
|
||||||
|
// the local light that is always present
|
||||||
|
vec4 totalLocalLight = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
for (int i = 0; i < numLocalLights; i++) {
|
||||||
|
float localDiffuse = dot(normalizedNormal, vec4(localLightDirections[i], 1.0));
|
||||||
|
float localLight = step(0.0, localDiffuse);
|
||||||
|
float localLightVal = localDiffuse * localLight;
|
||||||
|
|
||||||
|
totalLocalLight += (localLightVal * vec4( localLightColors[i], 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
vec4 base = gl_Color * (gl_FrontLightModelProduct.sceneColor + gl_FrontLightProduct[0].ambient +
|
||||||
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight));
|
gl_FrontLightProduct[0].diffuse * (diffuse * facingLight) + totalLocalLight);
|
||||||
|
|
||||||
// compute the specular component (sans exponent)
|
// compute the specular component (sans exponent)
|
||||||
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
|
float specular = facingLight * max(0.0, dot(normalize(gl_LightSource[0].position - normalize(vec4(position.xyz, 0.0))),
|
||||||
|
@ -38,4 +54,5 @@ void main(void) {
|
||||||
// modulate texture by base color and add specular contribution
|
// modulate texture by base color and add specular contribution
|
||||||
gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + vec4(pow(specular, gl_FrontMaterial.shininess) *
|
gl_FragColor = base * texture2D(diffuseMap, gl_TexCoord[0].st) + vec4(pow(specular, gl_FrontMaterial.shininess) *
|
||||||
gl_FrontLightProduct[0].specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0);
|
gl_FrontLightProduct[0].specular.rgb * texture2D(specularMap, gl_TexCoord[0].st).rgb, 0.0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ void main(void) {
|
||||||
position += clusterMatrix * gl_Vertex * clusterWeight;
|
position += clusterMatrix * gl_Vertex * clusterWeight;
|
||||||
normal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight;
|
normal += clusterMatrix * vec4(gl_Normal, 0.0) * clusterWeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
position = gl_ModelViewMatrix * position;
|
position = gl_ModelViewMatrix * position;
|
||||||
normal = normalize(gl_ModelViewMatrix * normal);
|
normal = normalize(gl_ModelViewMatrix * normal);
|
||||||
|
|
||||||
|
|
|
@ -354,6 +354,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
||||||
|
|
||||||
// Set the sixense filtering
|
// Set the sixense filtering
|
||||||
_sixenseManager.setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense));
|
_sixenseManager.setFilter(Menu::getInstance()->isOptionChecked(MenuOption::FilterSixense));
|
||||||
|
|
||||||
|
// Set hand controller velocity filtering
|
||||||
|
_sixenseManager.setLowVelocityFilter(Menu::getInstance()->isOptionChecked(MenuOption::LowVelocityFilter));
|
||||||
|
|
||||||
checkVersion();
|
checkVersion();
|
||||||
|
|
||||||
|
@ -601,9 +604,19 @@ void Application::paintGL() {
|
||||||
|
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||||
_myCamera.setTightness(0.0f);
|
_myCamera.setTightness(0.0f);
|
||||||
_myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
//Only behave like a true mirror when in the OR
|
||||||
_myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
if (OculusManager::isConnected()) {
|
||||||
_myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition() + glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0));
|
_myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
||||||
|
_myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
||||||
|
_myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition() + glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0));
|
||||||
|
} else {
|
||||||
|
_myCamera.setTightness(0.0f);
|
||||||
|
glm::vec3 eyePosition = _myAvatar->getHead()->calculateAverageEyePosition();
|
||||||
|
float headHeight = eyePosition.y - _myAvatar->getPosition().y;
|
||||||
|
_myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
|
||||||
|
_myCamera.setTargetPosition(_myAvatar->getPosition() + glm::vec3(0, headHeight + (_raiseMirror * _myAvatar->getScale()), 0));
|
||||||
|
_myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update camera position
|
// Update camera position
|
||||||
|
@ -682,13 +695,10 @@ void Application::paintGL() {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("paintGL/renderOverlay");
|
PerformanceTimer perfTimer("renderOverlay");
|
||||||
//If alpha is 1, we can render directly to the screen.
|
// PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay()
|
||||||
if (_applicationOverlay.getAlpha() == 1.0f) {
|
_applicationOverlay.renderOverlay(true);
|
||||||
_applicationOverlay.renderOverlay();
|
if (Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)) {
|
||||||
} else {
|
|
||||||
//Render to to texture so we can fade it
|
|
||||||
_applicationOverlay.renderOverlay(true);
|
|
||||||
_applicationOverlay.displayOverlayTexture();
|
_applicationOverlay.displayOverlayTexture();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -713,6 +723,7 @@ void Application::resizeGL(int width, int height) {
|
||||||
resetCamerasOnResizeGL(_myCamera, width, height);
|
resetCamerasOnResizeGL(_myCamera, width, height);
|
||||||
|
|
||||||
glViewport(0, 0, width, height); // shouldn't this account for the menu???
|
glViewport(0, 0, width, height); // shouldn't this account for the menu???
|
||||||
|
_applicationOverlay.resize();
|
||||||
|
|
||||||
updateProjectionMatrix();
|
updateProjectionMatrix();
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
|
@ -1010,6 +1021,9 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
Menu::getInstance()->triggerOption(MenuOption::FullscreenMirror);
|
Menu::getInstance()->triggerOption(MenuOption::FullscreenMirror);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case Qt::Key_Slash:
|
||||||
|
Menu::getInstance()->triggerOption(MenuOption::UserInterface);
|
||||||
|
break;
|
||||||
case Qt::Key_F:
|
case Qt::Key_F:
|
||||||
if (isShifted) {
|
if (isShifted) {
|
||||||
Menu::getInstance()->triggerOption(MenuOption::DisplayFrustum);
|
Menu::getInstance()->triggerOption(MenuOption::DisplayFrustum);
|
||||||
|
@ -1029,7 +1043,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
break;
|
break;
|
||||||
case Qt::Key_Slash:
|
case Qt::Key_Percent:
|
||||||
Menu::getInstance()->triggerOption(MenuOption::Stats);
|
Menu::getInstance()->triggerOption(MenuOption::Stats);
|
||||||
break;
|
break;
|
||||||
case Qt::Key_Plus:
|
case Qt::Key_Plus:
|
||||||
|
@ -1355,18 +1369,18 @@ void Application::idle() {
|
||||||
if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) {
|
if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) {
|
||||||
_lastTimeUpdated.start();
|
_lastTimeUpdated.start();
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("idle/update");
|
PerformanceTimer perfTimer("update");
|
||||||
PerformanceWarning warn(showWarnings, "Application::idle()... update()");
|
PerformanceWarning warn(showWarnings, "Application::idle()... update()");
|
||||||
const float BIGGEST_DELTA_TIME_SECS = 0.25f;
|
const float BIGGEST_DELTA_TIME_SECS = 0.25f;
|
||||||
update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS));
|
update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("idle/updateGL");
|
PerformanceTimer perfTimer("updateGL");
|
||||||
PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()");
|
PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()");
|
||||||
_glWidget->updateGL();
|
_glWidget->updateGL();
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("idle/rest");
|
PerformanceTimer perfTimer("rest");
|
||||||
PerformanceWarning warn(showWarnings, "Application::idle()... rest of it");
|
PerformanceWarning warn(showWarnings, "Application::idle()... rest of it");
|
||||||
_idleLoopStdev.addValue(timeSinceLastUpdate);
|
_idleLoopStdev.addValue(timeSinceLastUpdate);
|
||||||
|
|
||||||
|
@ -1378,7 +1392,7 @@ void Application::idle() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {
|
||||||
PerformanceTimer perfTimer("idle/rest/_buckyBalls");
|
PerformanceTimer perfTimer("buckyBalls");
|
||||||
_buckyBalls.simulate(timeSinceLastUpdate / 1000.f, Application::getInstance()->getAvatar()->getHandData());
|
_buckyBalls.simulate(timeSinceLastUpdate / 1000.f, Application::getInstance()->getAvatar()->getHandData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1426,6 +1440,10 @@ void Application::setRenderVoxels(bool voxelRender) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Application::setLowVelocityFilter(bool lowVelocityFilter) {
|
||||||
|
getSixenseManager()->setLowVelocityFilter(lowVelocityFilter);
|
||||||
|
}
|
||||||
|
|
||||||
void Application::doKillLocalVoxels() {
|
void Application::doKillLocalVoxels() {
|
||||||
_wantToKillLocalVoxels = true;
|
_wantToKillLocalVoxels = true;
|
||||||
}
|
}
|
||||||
|
@ -1792,7 +1810,7 @@ bool Application::isLookingAtMyAvatar(Avatar* avatar) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateLOD() {
|
void Application::updateLOD() {
|
||||||
PerformanceTimer perfTimer("idle/update/updateLOD");
|
PerformanceTimer perfTimer("LOD");
|
||||||
// adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
|
// adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode
|
||||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) {
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) {
|
||||||
Menu::getInstance()->autoAdjustLOD(_fps);
|
Menu::getInstance()->autoAdjustLOD(_fps);
|
||||||
|
@ -1802,7 +1820,7 @@ void Application::updateLOD() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateMouseRay() {
|
void Application::updateMouseRay() {
|
||||||
PerformanceTimer perfTimer("idle/update/updateMouseRay");
|
PerformanceTimer perfTimer("mouseRay");
|
||||||
|
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateMouseRay()");
|
PerformanceWarning warn(showWarnings, "Application::updateMouseRay()");
|
||||||
|
@ -1835,8 +1853,6 @@ void Application::updateMouseRay() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateFaceshift() {
|
void Application::updateFaceshift() {
|
||||||
PerformanceTimer perfTimer("idle/update/updateFaceshift");
|
|
||||||
|
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateFaceshift()");
|
PerformanceWarning warn(showWarnings, "Application::updateFaceshift()");
|
||||||
|
|
||||||
|
@ -1850,8 +1866,6 @@ void Application::updateFaceshift() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateVisage() {
|
void Application::updateVisage() {
|
||||||
PerformanceTimer perfTimer("idle/update/updateVisage");
|
|
||||||
|
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateVisage()");
|
PerformanceWarning warn(showWarnings, "Application::updateVisage()");
|
||||||
|
|
||||||
|
@ -1860,11 +1874,11 @@ void Application::updateVisage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateMyAvatarLookAtPosition() {
|
void Application::updateMyAvatarLookAtPosition() {
|
||||||
PerformanceTimer perfTimer("idle/update/updateMyAvatarLookAtPosition");
|
PerformanceTimer perfTimer("lookAt");
|
||||||
|
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()");
|
PerformanceWarning warn(showWarnings, "Application::updateMyAvatarLookAtPosition()");
|
||||||
|
|
||||||
|
_myAvatar->updateLookAtTargetAvatar();
|
||||||
FaceTracker* tracker = getActiveFaceTracker();
|
FaceTracker* tracker = getActiveFaceTracker();
|
||||||
|
|
||||||
bool isLookingAtSomeone = false;
|
bool isLookingAtSomeone = false;
|
||||||
|
@ -1927,7 +1941,7 @@ void Application::updateMyAvatarLookAtPosition() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateThreads(float deltaTime) {
|
void Application::updateThreads(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("idle/update/updateThreads");
|
PerformanceTimer perfTimer("updateThreads");
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateThreads()");
|
PerformanceWarning warn(showWarnings, "Application::updateThreads()");
|
||||||
|
|
||||||
|
@ -1942,7 +1956,7 @@ void Application::updateThreads(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateMetavoxels(float deltaTime) {
|
void Application::updateMetavoxels(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("idle/update/updateMetavoxels");
|
PerformanceTimer perfTimer("updateMetavoxels");
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateMetavoxels()");
|
PerformanceWarning warn(showWarnings, "Application::updateMetavoxels()");
|
||||||
|
|
||||||
|
@ -1972,7 +1986,7 @@ void Application::cameraMenuChanged() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateCamera(float deltaTime) {
|
void Application::updateCamera(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("idle/update/updateCamera");
|
PerformanceTimer perfTimer("updateCamera");
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateCamera()");
|
PerformanceWarning warn(showWarnings, "Application::updateCamera()");
|
||||||
|
|
||||||
|
@ -1990,7 +2004,7 @@ void Application::updateCamera(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateDialogs(float deltaTime) {
|
void Application::updateDialogs(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("idle/update/updateDialogs");
|
PerformanceTimer perfTimer("updateDialogs");
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateDialogs()");
|
PerformanceWarning warn(showWarnings, "Application::updateDialogs()");
|
||||||
|
|
||||||
|
@ -2007,7 +2021,7 @@ void Application::updateDialogs(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateCursor(float deltaTime) {
|
void Application::updateCursor(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("idle/update/updateCursor");
|
PerformanceTimer perfTimer("updateCursor");
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateCursor()");
|
PerformanceWarning warn(showWarnings, "Application::updateCursor()");
|
||||||
|
|
||||||
|
@ -2032,83 +2046,69 @@ void Application::updateCursor(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::update(float deltaTime) {
|
void Application::update(float deltaTime) {
|
||||||
//PerformanceTimer perfTimer("idle/update"); // NOTE: we track this above in Application::idle()
|
|
||||||
|
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::update()");
|
PerformanceWarning warn(showWarnings, "Application::update()");
|
||||||
|
|
||||||
updateLOD();
|
updateLOD();
|
||||||
updateMouseRay(); // check what's under the mouse and update the mouse voxel
|
updateMouseRay(); // check what's under the mouse and update the mouse voxel
|
||||||
updateFaceshift();
|
|
||||||
updateVisage();
|
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("idle/update/updateLookAtTargetAvatar");
|
PerformanceTimer perfTimer("devices");
|
||||||
_myAvatar->updateLookAtTargetAvatar();
|
updateFaceshift();
|
||||||
}
|
updateVisage();
|
||||||
updateMyAvatarLookAtPosition();
|
|
||||||
{
|
|
||||||
PerformanceTimer perfTimer("idle/update/sixense,joystick,prioVR");
|
|
||||||
_sixenseManager.update(deltaTime);
|
_sixenseManager.update(deltaTime);
|
||||||
_joystickManager.update();
|
_joystickManager.update();
|
||||||
_prioVR.update(deltaTime);
|
_prioVR.update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("idle/update/updateMyAvatar");
|
PerformanceTimer perfTimer("myAvatar");
|
||||||
|
updateMyAvatarLookAtPosition();
|
||||||
updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
||||||
}
|
}
|
||||||
|
|
||||||
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
updateThreads(deltaTime); // If running non-threaded, then give the threads some time to process...
|
||||||
|
|
||||||
{
|
_avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them...
|
||||||
PerformanceTimer perfTimer("idle/update/_avatarManager");
|
|
||||||
_avatarManager.updateOtherAvatars(deltaTime); //loop through all the other avatars and simulate them...
|
|
||||||
}
|
|
||||||
updateMetavoxels(deltaTime); // update metavoxels
|
updateMetavoxels(deltaTime); // update metavoxels
|
||||||
updateCamera(deltaTime); // handle various camera tweaks like off axis projection
|
updateCamera(deltaTime); // handle various camera tweaks like off axis projection
|
||||||
updateDialogs(deltaTime); // update various stats dialogs if present
|
updateDialogs(deltaTime); // update various stats dialogs if present
|
||||||
updateCursor(deltaTime); // Handle cursor updates
|
updateCursor(deltaTime); // Handle cursor updates
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("idle/update/_particles");
|
PerformanceTimer perfTimer("particles");
|
||||||
_particles.update(); // update the particles...
|
_particles.update(); // update the particles...
|
||||||
}
|
{
|
||||||
{
|
PerformanceTimer perfTimer("collisions");
|
||||||
PerformanceTimer perfTimer("idle/update/_particleCollisionSystem");
|
_particleCollisionSystem.update(); // collide the particles...
|
||||||
_particleCollisionSystem.update(); // collide the particles...
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("idle/update/_models");
|
PerformanceTimer perfTimer("models");
|
||||||
_models.update(); // update the models...
|
_models.update(); // update the models...
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("idle/update/_overlays");
|
PerformanceTimer perfTimer("overlays");
|
||||||
_overlays.update(deltaTime);
|
_overlays.update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("idle/update/emit simulating");
|
PerformanceTimer perfTimer("emitSimulating");
|
||||||
// let external parties know we're updating
|
// let external parties know we're updating
|
||||||
emit simulating(deltaTime);
|
emit simulating(deltaTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateMyAvatar(float deltaTime) {
|
void Application::updateMyAvatar(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("updateMyAvatar");
|
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateMyAvatar()");
|
PerformanceWarning warn(showWarnings, "Application::updateMyAvatar()");
|
||||||
|
|
||||||
{
|
_myAvatar->update(deltaTime);
|
||||||
PerformanceTimer perfTimer("updateMyAvatar/_myAvatar->update()");
|
|
||||||
_myAvatar->update(deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
// send head/hand data to the avatar mixer and voxel server
|
// send head/hand data to the avatar mixer and voxel server
|
||||||
PerformanceTimer perfTimer("updateMyAvatar/sendToAvatarMixer");
|
PerformanceTimer perfTimer("send");
|
||||||
QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeAvatarData);
|
QByteArray packet = byteArrayWithPopulatedHeader(PacketTypeAvatarData);
|
||||||
packet.append(_myAvatar->toByteArray());
|
packet.append(_myAvatar->toByteArray());
|
||||||
controlledBroadcastToNodes(packet, NodeSet() << NodeType::AvatarMixer);
|
controlledBroadcastToNodes(packet, NodeSet() << NodeType::AvatarMixer);
|
||||||
|
@ -2121,13 +2121,13 @@ void Application::updateMyAvatar(float deltaTime) {
|
||||||
// actually need to calculate the view frustum planes to send these details
|
// actually need to calculate the view frustum planes to send these details
|
||||||
// to the server.
|
// to the server.
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("updateMyAvatar/loadViewFrustum");
|
PerformanceTimer perfTimer("loadViewFrustum");
|
||||||
loadViewFrustum(_myCamera, _viewFrustum);
|
loadViewFrustum(_myCamera, _viewFrustum);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update my voxel servers with my current voxel query...
|
// Update my voxel servers with my current voxel query...
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("updateMyAvatar/queryOctree");
|
PerformanceTimer perfTimer("queryOctree");
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
quint64 sinceLastQuery = now - _lastQueriedTime;
|
quint64 sinceLastQuery = now - _lastQueriedTime;
|
||||||
const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND;
|
const quint64 TOO_LONG_SINCE_LAST_QUERY = 3 * USECS_PER_SECOND;
|
||||||
|
@ -2460,7 +2460,7 @@ glm::vec3 Application::getSunDirection() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::updateShadowMap() {
|
void Application::updateShadowMap() {
|
||||||
PerformanceTimer perfTimer("paintGL/updateShadowMap");
|
PerformanceTimer perfTimer("shadowMap");
|
||||||
QOpenGLFramebufferObject* fbo = _textureCache.getShadowFramebufferObject();
|
QOpenGLFramebufferObject* fbo = _textureCache.getShadowFramebufferObject();
|
||||||
fbo->bind();
|
fbo->bind();
|
||||||
glEnable(GL_DEPTH_TEST);
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
@ -2622,7 +2622,7 @@ QImage Application::renderAvatarBillboard() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide");
|
PerformanceTimer perfTimer("display");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()");
|
||||||
// transform by eye offset
|
// transform by eye offset
|
||||||
|
|
||||||
|
@ -2656,7 +2656,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
|
|
||||||
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
|
// Setup 3D lights (after the camera transform, so that they are positioned in world space)
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/setupWorldLight");
|
PerformanceTimer perfTimer("lights");
|
||||||
setupWorldLight();
|
setupWorldLight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2675,7 +2675,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
|
if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/stars");
|
PerformanceTimer perfTimer("stars");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::displaySide() ... stars...");
|
"Application::displaySide() ... stars...");
|
||||||
if (!_stars.isStarsLoaded()) {
|
if (!_stars.isStarsLoaded()) {
|
||||||
|
@ -2704,7 +2704,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
|
|
||||||
// draw the sky dome
|
// draw the sky dome
|
||||||
if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
|
if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) {
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/atmosphere");
|
PerformanceTimer perfTimer("atmosphere");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::displaySide() ... atmosphere...");
|
"Application::displaySide() ... atmosphere...");
|
||||||
_environment.renderAtmospheres(whichCamera);
|
_environment.renderAtmospheres(whichCamera);
|
||||||
|
@ -2725,13 +2725,13 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
|
|
||||||
// draw the audio reflector overlay
|
// draw the audio reflector overlay
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/audioReflector");
|
PerformanceTimer perfTimer("audio");
|
||||||
_audioReflector.render();
|
_audioReflector.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw voxels
|
// Draw voxels
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) {
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/voxels");
|
PerformanceTimer perfTimer("voxels");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::displaySide() ... voxels...");
|
"Application::displaySide() ... voxels...");
|
||||||
_voxels.render();
|
_voxels.render();
|
||||||
|
@ -2739,14 +2739,14 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
|
|
||||||
// also, metavoxels
|
// also, metavoxels
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Metavoxels)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Metavoxels)) {
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/metavoxels");
|
PerformanceTimer perfTimer("metavoxels");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::displaySide() ... metavoxels...");
|
"Application::displaySide() ... metavoxels...");
|
||||||
_metavoxels.render();
|
_metavoxels.render();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::BuckyBalls)) {
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/buckyBalls");
|
PerformanceTimer perfTimer("buckyBalls");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::displaySide() ... bucky balls...");
|
"Application::displaySide() ... bucky balls...");
|
||||||
_buckyBalls.render();
|
_buckyBalls.render();
|
||||||
|
@ -2754,7 +2754,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
|
|
||||||
// render particles...
|
// render particles...
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Particles)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Particles)) {
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/particles");
|
PerformanceTimer perfTimer("particles");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::displaySide() ... particles...");
|
"Application::displaySide() ... particles...");
|
||||||
_particles.render();
|
_particles.render();
|
||||||
|
@ -2762,7 +2762,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
|
|
||||||
// render models...
|
// render models...
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Models)) {
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/models");
|
PerformanceTimer perfTimer("models");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::displaySide() ... models...");
|
"Application::displaySide() ... models...");
|
||||||
_models.render();
|
_models.render();
|
||||||
|
@ -2770,7 +2770,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
|
|
||||||
// render the ambient occlusion effect if enabled
|
// render the ambient occlusion effect if enabled
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::AmbientOcclusion)) {
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/AmbientOcclusion");
|
PerformanceTimer perfTimer("ambientOcclusion");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::displaySide() ... AmbientOcclusion...");
|
"Application::displaySide() ... AmbientOcclusion...");
|
||||||
_ambientOcclusionEffect.render();
|
_ambientOcclusionEffect.render();
|
||||||
|
@ -2785,20 +2785,21 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
|
|
||||||
bool mirrorMode = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR);
|
bool mirrorMode = (whichCamera.getInterpolatedMode() == CAMERA_MODE_MIRROR);
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/renderAvatars");
|
PerformanceTimer perfTimer("avatars");
|
||||||
_avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE, selfAvatarOnly);
|
_avatarManager.renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE, selfAvatarOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selfAvatarOnly) {
|
if (!selfAvatarOnly) {
|
||||||
// Render the world box
|
// Render the world box
|
||||||
if (whichCamera.getMode() != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) {
|
if (whichCamera.getMode() != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Stats) &&
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/renderWorldBox");
|
Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)) {
|
||||||
|
PerformanceTimer perfTimer("worldBox");
|
||||||
renderWorldBox();
|
renderWorldBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
// view frustum for debugging
|
// view frustum for debugging
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum) && whichCamera.getMode() != CAMERA_MODE_MIRROR) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::DisplayFrustum) && whichCamera.getMode() != CAMERA_MODE_MIRROR) {
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/ViewFrustum");
|
PerformanceTimer perfTimer("viewFrustum");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::displaySide() ... renderViewFrustum...");
|
"Application::displaySide() ... renderViewFrustum...");
|
||||||
renderViewFrustum(_viewFrustum);
|
renderViewFrustum(_viewFrustum);
|
||||||
|
@ -2806,7 +2807,7 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
|
|
||||||
// render voxel fades if they exist
|
// render voxel fades if they exist
|
||||||
if (_voxelFades.size() > 0) {
|
if (_voxelFades.size() > 0) {
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/voxel fades");
|
PerformanceTimer perfTimer("voxelFades");
|
||||||
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
|
||||||
"Application::displaySide() ... voxel fades...");
|
"Application::displaySide() ... voxel fades...");
|
||||||
_voxelFadesLock.lockForWrite();
|
_voxelFadesLock.lockForWrite();
|
||||||
|
@ -2823,13 +2824,13 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
|
|
||||||
// give external parties a change to hook in
|
// give external parties a change to hook in
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/inWorldInterface");
|
PerformanceTimer perfTimer("inWorldInterface");
|
||||||
emit renderingInWorldInterface();
|
emit renderingInWorldInterface();
|
||||||
}
|
}
|
||||||
|
|
||||||
// render JS/scriptable overlays
|
// render JS/scriptable overlays
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("paintGL/displaySide/3dOverlays");
|
PerformanceTimer perfTimer("3dOverlays");
|
||||||
_overlays.render3D();
|
_overlays.render3D();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -317,6 +317,7 @@ public slots:
|
||||||
void nudgeVoxelsByVector(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec);
|
void nudgeVoxelsByVector(const VoxelDetail& sourceVoxel, const glm::vec3& nudgeVec);
|
||||||
|
|
||||||
void setRenderVoxels(bool renderVoxels);
|
void setRenderVoxels(bool renderVoxels);
|
||||||
|
void setLowVelocityFilter(bool lowVelocityFilter);
|
||||||
void doKillLocalVoxels();
|
void doKillLocalVoxels();
|
||||||
void loadDialog();
|
void loadDialog();
|
||||||
void loadScriptURLDialog();
|
void loadScriptURLDialog();
|
||||||
|
|
35
interface/src/Hair.cpp
Normal file
35
interface/src/Hair.cpp
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
//
|
||||||
|
// Hair.cpp
|
||||||
|
// interface/src
|
||||||
|
//
|
||||||
|
// Created by Philip on June 26, 2014
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
// Creates single flexible vertlet-integrated strands that can be used for hair/fur/grass
|
||||||
|
|
||||||
|
#include "Hair.h"
|
||||||
|
|
||||||
|
#include "Util.h"
|
||||||
|
#include "world.h"
|
||||||
|
|
||||||
|
|
||||||
|
Hair::Hair() {
|
||||||
|
qDebug() << "Creating Hair";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hair::simulate(float deltaTime) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Hair::render() {
|
||||||
|
//
|
||||||
|
// Before calling this function, translate/rotate to the origin of the owning object
|
||||||
|
glPushMatrix();
|
||||||
|
glColor3f(1.0f, 1.0f, 0.0f);
|
||||||
|
glutSolidSphere(1.0f, 15, 15);
|
||||||
|
glPopMatrix();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
35
interface/src/Hair.h
Normal file
35
interface/src/Hair.h
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
//
|
||||||
|
// Hair.h
|
||||||
|
// interface/src
|
||||||
|
//
|
||||||
|
// Created by Philip on June 26, 2014
|
||||||
|
// 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_Hair_h
|
||||||
|
#define hifi_Hair_h
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
|
#include "GeometryUtil.h"
|
||||||
|
#include "InterfaceConfig.h"
|
||||||
|
#include "Util.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Hair {
|
||||||
|
public:
|
||||||
|
Hair();
|
||||||
|
void simulate(float deltaTime);
|
||||||
|
void render();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_Hair_h
|
|
@ -276,6 +276,7 @@ Menu::Menu() :
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::SHIFT | Qt::Key_H, true);
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror, Qt::SHIFT | Qt::Key_H, true);
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H, false,
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror, Qt::Key_H, false,
|
||||||
appInstance, SLOT(cameraMenuChanged()));
|
appInstance, SLOT(cameraMenuChanged()));
|
||||||
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::UserInterface, Qt::Key_Slash, true);
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0,
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0,
|
||||||
false,
|
false,
|
||||||
|
@ -326,7 +327,7 @@ Menu::Menu() :
|
||||||
|
|
||||||
|
|
||||||
addDisabledActionAndSeparator(viewMenu, "Stats");
|
addDisabledActionAndSeparator(viewMenu, "Stats");
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Slash);
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, Qt::Key_Percent);
|
||||||
addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L, appInstance, SLOT(toggleLogDialog()));
|
addActionToQMenuAndActionHash(viewMenu, MenuOption::Log, Qt::CTRL | Qt::Key_L, appInstance, SLOT(toggleLogDialog()));
|
||||||
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true);
|
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Bandwidth, 0, true);
|
||||||
addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails()));
|
addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0, this, SLOT(bandwidthDetails()));
|
||||||
|
@ -406,9 +407,7 @@ Menu::Menu() :
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::GlowWhenSpeaking, 0, true);
|
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::GlowWhenSpeaking, 0, true);
|
||||||
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::ChatCircling, 0, false);
|
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::ChatCircling, 0, false);
|
||||||
|
addCheckableActionToQMenuAndActionHash(avatarOptionsMenu, MenuOption::FocusIndicators, 0, false);
|
||||||
QMenu* oculusOptionsMenu = developerMenu->addMenu("Oculus Options");
|
|
||||||
addCheckableActionToQMenuAndActionHash(oculusOptionsMenu, MenuOption::DisplayOculusOverlays, 0, true);
|
|
||||||
|
|
||||||
QMenu* sixenseOptionsMenu = developerMenu->addMenu("Sixense Options");
|
QMenu* sixenseOptionsMenu = developerMenu->addMenu("Sixense Options");
|
||||||
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseMouseInput, 0, true);
|
addCheckableActionToQMenuAndActionHash(sixenseOptionsMenu, MenuOption::SixenseMouseInput, 0, true);
|
||||||
|
@ -421,6 +420,13 @@ Menu::Menu() :
|
||||||
true,
|
true,
|
||||||
appInstance->getSixenseManager(),
|
appInstance->getSixenseManager(),
|
||||||
SLOT(setFilter(bool)));
|
SLOT(setFilter(bool)));
|
||||||
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu,
|
||||||
|
MenuOption::LowVelocityFilter,
|
||||||
|
0,
|
||||||
|
true,
|
||||||
|
appInstance,
|
||||||
|
SLOT(setLowVelocityFilter(bool)));
|
||||||
|
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHands, 0, true);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHands, 0, true);
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
|
||||||
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandsCollideWithSelf, 0, false);
|
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandsCollideWithSelf, 0, false);
|
||||||
|
|
|
@ -350,7 +350,6 @@ namespace MenuOption {
|
||||||
const QString DisplayModelBounds = "Display Model Bounds";
|
const QString DisplayModelBounds = "Display Model Bounds";
|
||||||
const QString DisplayModelElementProxy = "Display Model Element Bounds";
|
const QString DisplayModelElementProxy = "Display Model Element Bounds";
|
||||||
const QString DisplayModelElementChildProxies = "Display Model Element Children";
|
const QString DisplayModelElementChildProxies = "Display Model Element Children";
|
||||||
const QString DisplayOculusOverlays = "Display Oculus Overlays";
|
|
||||||
const QString DisplayTimingDetails = "Display Timing Details";
|
const QString DisplayTimingDetails = "Display Timing Details";
|
||||||
const QString DontFadeOnVoxelServerChanges = "Don't Fade In/Out on Voxel Server Changes";
|
const QString DontFadeOnVoxelServerChanges = "Don't Fade In/Out on Voxel Server Changes";
|
||||||
const QString EchoLocalAudio = "Echo Local Audio";
|
const QString EchoLocalAudio = "Echo Local Audio";
|
||||||
|
@ -368,7 +367,9 @@ namespace MenuOption {
|
||||||
const QString Faceplus = "Faceplus";
|
const QString Faceplus = "Faceplus";
|
||||||
const QString Faceshift = "Faceshift";
|
const QString Faceshift = "Faceshift";
|
||||||
const QString FilterSixense = "Smooth Sixense Movement";
|
const QString FilterSixense = "Smooth Sixense Movement";
|
||||||
|
const QString LowVelocityFilter = "Low Velocity Filter";
|
||||||
const QString FirstPerson = "First Person";
|
const QString FirstPerson = "First Person";
|
||||||
|
const QString FocusIndicators = "Focus Indicators";
|
||||||
const QString FrameTimer = "Show Timer";
|
const QString FrameTimer = "Show Timer";
|
||||||
const QString FrustumRenderMode = "Render Mode";
|
const QString FrustumRenderMode = "Render Mode";
|
||||||
const QString Fullscreen = "Fullscreen";
|
const QString Fullscreen = "Fullscreen";
|
||||||
|
@ -439,6 +440,7 @@ namespace MenuOption {
|
||||||
const QString UploadAttachment = "Upload Attachment Model";
|
const QString UploadAttachment = "Upload Attachment Model";
|
||||||
const QString UploadHead = "Upload Head Model";
|
const QString UploadHead = "Upload Head Model";
|
||||||
const QString UploadSkeleton = "Upload Skeleton Model";
|
const QString UploadSkeleton = "Upload Skeleton Model";
|
||||||
|
const QString UserInterface = "User Interface";
|
||||||
const QString Visage = "Visage";
|
const QString Visage = "Visage";
|
||||||
const QString VoxelMode = "Cycle Voxel Mode";
|
const QString VoxelMode = "Cycle Voxel Mode";
|
||||||
const QString Voxels = "Voxels";
|
const QString Voxels = "Voxels";
|
||||||
|
|
|
@ -14,12 +14,13 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
#include <glm/gtx/vector_angle.hpp>
|
#include <glm/gtx/vector_angle.hpp>
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
#include <NodeList.h>
|
|
||||||
#include <PacketHeaders.h>
|
|
||||||
#include <SharedUtil.h>
|
|
||||||
|
|
||||||
#include <GeometryUtil.h>
|
#include <GeometryUtil.h>
|
||||||
|
#include <NodeList.h>
|
||||||
|
#include <PacketHeaders.h>
|
||||||
|
#include <PerfStat.h>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "Avatar.h"
|
#include "Avatar.h"
|
||||||
|
@ -60,7 +61,8 @@ Avatar::Avatar() :
|
||||||
_moving(false),
|
_moving(false),
|
||||||
_collisionGroups(0),
|
_collisionGroups(0),
|
||||||
_initialized(false),
|
_initialized(false),
|
||||||
_shouldRenderBillboard(true)
|
_shouldRenderBillboard(true),
|
||||||
|
_numLocalLights(1)
|
||||||
{
|
{
|
||||||
// we may have been created in the network thread, but we live in the main thread
|
// we may have been created in the network thread, but we live in the main thread
|
||||||
moveToThread(Application::getInstance()->thread());
|
moveToThread(Application::getInstance()->thread());
|
||||||
|
@ -81,6 +83,23 @@ void Avatar::init() {
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
_shouldRenderBillboard = (getLODDistance() >= BILLBOARD_LOD_DISTANCE);
|
_shouldRenderBillboard = (getLODDistance() >= BILLBOARD_LOD_DISTANCE);
|
||||||
initializeHair();
|
initializeHair();
|
||||||
|
|
||||||
|
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||||
|
_localLightColors[i] = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
_localLightDirections[i] = glm::vec3(0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 darkGrayColor(0.3f, 0.3f, 0.3f);
|
||||||
|
glm::vec3 greenColor(0.0f, 1.0f, 0.0f);
|
||||||
|
glm::vec3 directionX(1.0f, 0.0f, 0.0f);
|
||||||
|
glm::vec3 directionY(0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
// initialize local lights
|
||||||
|
_localLightColors[0] = darkGrayColor;
|
||||||
|
_localLightColors[1] = greenColor;
|
||||||
|
|
||||||
|
_localLightDirections[0] = directionX;
|
||||||
|
_localLightDirections[1] = directionY;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 Avatar::getChestPosition() const {
|
glm::vec3 Avatar::getChestPosition() const {
|
||||||
|
@ -99,6 +118,7 @@ float Avatar::getLODDistance() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::simulate(float deltaTime) {
|
void Avatar::simulate(float deltaTime) {
|
||||||
|
PerformanceTimer perfTimer("simulate");
|
||||||
if (_scale != _targetScale) {
|
if (_scale != _targetScale) {
|
||||||
setScale(_targetScale);
|
setScale(_targetScale);
|
||||||
}
|
}
|
||||||
|
@ -118,31 +138,43 @@ void Avatar::simulate(float deltaTime) {
|
||||||
bool inViewFrustum = Application::getInstance()->getViewFrustum()->sphereInFrustum(_position, boundingRadius) !=
|
bool inViewFrustum = Application::getInstance()->getViewFrustum()->sphereInFrustum(_position, boundingRadius) !=
|
||||||
ViewFrustum::OUTSIDE;
|
ViewFrustum::OUTSIDE;
|
||||||
|
|
||||||
getHand()->simulate(deltaTime, false);
|
{
|
||||||
|
PerformanceTimer perfTimer("hand");
|
||||||
|
getHand()->simulate(deltaTime, false);
|
||||||
|
}
|
||||||
_skeletonModel.setLODDistance(getLODDistance());
|
_skeletonModel.setLODDistance(getLODDistance());
|
||||||
|
|
||||||
if (!_shouldRenderBillboard && inViewFrustum) {
|
if (!_shouldRenderBillboard && inViewFrustum) {
|
||||||
if (_hasNewJointRotations) {
|
if (_hasNewJointRotations) {
|
||||||
|
PerformanceTimer perfTimer("skeleton");
|
||||||
for (int i = 0; i < _jointData.size(); i++) {
|
for (int i = 0; i < _jointData.size(); i++) {
|
||||||
const JointData& data = _jointData.at(i);
|
const JointData& data = _jointData.at(i);
|
||||||
_skeletonModel.setJointState(i, data.valid, data.rotation);
|
_skeletonModel.setJointState(i, data.valid, data.rotation);
|
||||||
}
|
}
|
||||||
_skeletonModel.simulate(deltaTime);
|
_skeletonModel.simulate(deltaTime);
|
||||||
}
|
}
|
||||||
_skeletonModel.simulate(deltaTime, _hasNewJointRotations);
|
{
|
||||||
simulateAttachments(deltaTime);
|
PerformanceTimer perfTimer("head");
|
||||||
_hasNewJointRotations = false;
|
_skeletonModel.simulate(deltaTime, _hasNewJointRotations);
|
||||||
|
simulateAttachments(deltaTime);
|
||||||
|
_hasNewJointRotations = false;
|
||||||
|
|
||||||
glm::vec3 headPosition = _position;
|
glm::vec3 headPosition = _position;
|
||||||
_skeletonModel.getHeadPosition(headPosition);
|
_skeletonModel.getHeadPosition(headPosition);
|
||||||
Head* head = getHead();
|
Head* head = getHead();
|
||||||
head->setPosition(headPosition);
|
head->setPosition(headPosition);
|
||||||
head->setScale(_scale);
|
head->setScale(_scale);
|
||||||
head->simulate(deltaTime, false, _shouldRenderBillboard);
|
head->simulate(deltaTime, false, _shouldRenderBillboard);
|
||||||
|
}
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
|
||||||
|
PerformanceTimer perfTimer("hair");
|
||||||
simulateHair(deltaTime);
|
simulateHair(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (Hair* hair, _hairs) {
|
||||||
|
hair->simulate(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// update position by velocity, and subtract the change added earlier for gravity
|
// update position by velocity, and subtract the change added earlier for gravity
|
||||||
|
@ -219,7 +251,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
||||||
const float GLOW_DISTANCE = 20.0f;
|
const float GLOW_DISTANCE = 20.0f;
|
||||||
const float GLOW_MAX_LOUDNESS = 2500.0f;
|
const float GLOW_MAX_LOUDNESS = 2500.0f;
|
||||||
const float MAX_GLOW = 0.5f;
|
const float MAX_GLOW = 0.5f;
|
||||||
|
|
||||||
float GLOW_FROM_AVERAGE_LOUDNESS = ((this == Application::getInstance()->getAvatar())
|
float GLOW_FROM_AVERAGE_LOUDNESS = ((this == Application::getInstance()->getAvatar())
|
||||||
? 0.0f
|
? 0.0f
|
||||||
: MAX_GLOW * getHeadData()->getAudioLoudness() / GLOW_MAX_LOUDNESS);
|
: MAX_GLOW * getHeadData()->getAudioLoudness() / GLOW_MAX_LOUDNESS);
|
||||||
|
@ -230,7 +262,23 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
||||||
float glowLevel = _moving && distanceToTarget > GLOW_DISTANCE && renderMode == NORMAL_RENDER_MODE
|
float glowLevel = _moving && distanceToTarget > GLOW_DISTANCE && renderMode == NORMAL_RENDER_MODE
|
||||||
? 1.0f
|
? 1.0f
|
||||||
: GLOW_FROM_AVERAGE_LOUDNESS;
|
: GLOW_FROM_AVERAGE_LOUDNESS;
|
||||||
|
|
||||||
|
|
||||||
|
// local lights directions and colors
|
||||||
|
getSkeletonModel().setNumLocalLights(_numLocalLights);
|
||||||
|
getHead()->getFaceModel().setNumLocalLights(_numLocalLights);
|
||||||
|
for (int i = 0; i < MAX_LOCAL_LIGHTS; i++) {
|
||||||
|
glm::vec3 normalized = glm::normalize(_localLightDirections[i]);
|
||||||
|
|
||||||
|
// body
|
||||||
|
getSkeletonModel().setLocalLightColor(_localLightColors[i], i);
|
||||||
|
getSkeletonModel().setLocalLightDirection(normalized, i);
|
||||||
|
|
||||||
|
// head
|
||||||
|
getHead()->getFaceModel().setLocalLightColor(_localLightColors[i], i);
|
||||||
|
getHead()->getFaceModel().setLocalLightDirection(_localLightDirections[i], i);
|
||||||
|
}
|
||||||
|
|
||||||
// render body
|
// render body
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::Avatars)) {
|
||||||
renderBody(renderMode, glowLevel);
|
renderBody(renderMode, glowLevel);
|
||||||
|
@ -252,7 +300,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this is the avatar being looked at, render a little ball above their head
|
// If this is the avatar being looked at, render a little ball above their head
|
||||||
if (_isLookAtTarget) {
|
if (_isLookAtTarget && Menu::getInstance()->isOptionChecked(MenuOption::FocusIndicators)) {
|
||||||
const float LOOK_AT_INDICATOR_RADIUS = 0.03f;
|
const float LOOK_AT_INDICATOR_RADIUS = 0.03f;
|
||||||
const float LOOK_AT_INDICATOR_OFFSET = 0.22f;
|
const float LOOK_AT_INDICATOR_OFFSET = 0.22f;
|
||||||
const float LOOK_AT_INDICATOR_COLOR[] = { 0.8f, 0.0f, 0.0f, 0.75f };
|
const float LOOK_AT_INDICATOR_COLOR[] = { 0.8f, 0.0f, 0.0f, 0.75f };
|
||||||
|
@ -380,6 +428,9 @@ void Avatar::renderBody(RenderMode renderMode, float glowLevel) {
|
||||||
getHead()->render(1.0f, modelRenderMode);
|
getHead()->render(1.0f, modelRenderMode);
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
|
||||||
renderHair();
|
renderHair();
|
||||||
|
foreach (Hair* hair, _hairs) {
|
||||||
|
hair->render();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,7 +654,6 @@ void Avatar::initializeHair() {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
qDebug() << "Initialize Hair";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const {
|
bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const {
|
||||||
|
@ -1107,3 +1157,29 @@ void Avatar::setShowDisplayName(bool showDisplayName) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Avatar::setLocalLightDirection(const glm::vec3& direction, int lightIndex) {
|
||||||
|
_localLightDirections[lightIndex] = direction;
|
||||||
|
qDebug( "set light %d direction ( %f, %f, %f )\n", lightIndex, direction.x, direction.y, direction.z );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Avatar::setLocalLightColor(const glm::vec3& color, int lightIndex) {
|
||||||
|
_localLightColors[lightIndex] = color;
|
||||||
|
qDebug( "set light %d color ( %f, %f, %f )\n", lightIndex, color.x, color.y, color.z );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Avatar::addLocalLight() {
|
||||||
|
if (_numLocalLights + 1 <= MAX_LOCAL_LIGHTS) {
|
||||||
|
++_numLocalLights;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug("ADD LOCAL LIGHT (numLocalLights = %d)\n", _numLocalLights);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Avatar::removeLocalLight() {
|
||||||
|
if (_numLocalLights - 1 >= 0) {
|
||||||
|
--_numLocalLights;
|
||||||
|
}
|
||||||
|
|
||||||
|
qDebug("REMOVE LOCAL LIGHT (numLocalLights = %d)\n", _numLocalLights);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <AvatarData.h>
|
#include <AvatarData.h>
|
||||||
|
|
||||||
|
#include "Hair.h"
|
||||||
#include "Hand.h"
|
#include "Hand.h"
|
||||||
#include "Head.h"
|
#include "Head.h"
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
|
@ -154,11 +155,16 @@ public:
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void updateCollisionGroups();
|
void updateCollisionGroups();
|
||||||
|
void setLocalLightDirection(const glm::vec3& direction, int lightIndex);
|
||||||
|
void setLocalLightColor(const glm::vec3& color, int lightIndex);
|
||||||
|
void addLocalLight();
|
||||||
|
void removeLocalLight();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision);
|
void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
QVector<Hair*> _hairs;
|
||||||
SkeletonModel _skeletonModel;
|
SkeletonModel _skeletonModel;
|
||||||
QVector<Model*> _attachmentModels;
|
QVector<Model*> _attachmentModels;
|
||||||
float _bodyYawDelta;
|
float _bodyYawDelta;
|
||||||
|
@ -174,9 +180,14 @@ protected:
|
||||||
glm::vec3 _mouseRayDirection;
|
glm::vec3 _mouseRayDirection;
|
||||||
float _stringLength;
|
float _stringLength;
|
||||||
bool _moving; ///< set when position is changing
|
bool _moving; ///< set when position is changing
|
||||||
|
|
||||||
quint32 _collisionGroups;
|
quint32 _collisionGroups;
|
||||||
|
|
||||||
|
// always-present local lighting for the avatar
|
||||||
|
glm::vec3 _localLightDirections[MAX_LOCAL_LIGHTS];
|
||||||
|
glm::vec3 _localLightColors[MAX_LOCAL_LIGHTS];
|
||||||
|
int _numLocalLights;
|
||||||
|
|
||||||
// protected methods...
|
// protected methods...
|
||||||
glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
|
||||||
glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; }
|
glm::vec3 getBodyUpDirection() const { return getOrientation() * IDENTITY_UP; }
|
||||||
|
|
|
@ -41,9 +41,13 @@ void AvatarManager::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AvatarManager::updateOtherAvatars(float deltaTime) {
|
void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
|
if (_avatarHash.size() < 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
PerformanceWarning warn(showWarnings, "Application::updateAvatars()");
|
PerformanceWarning warn(showWarnings, "Application::updateAvatars()");
|
||||||
|
|
||||||
|
PerformanceTimer perfTimer("otherAvatars");
|
||||||
Application* applicationInstance = Application::getInstance();
|
Application* applicationInstance = Application::getInstance();
|
||||||
glm::vec3 mouseOrigin = applicationInstance->getMouseRayOrigin();
|
glm::vec3 mouseOrigin = applicationInstance->getMouseRayOrigin();
|
||||||
glm::vec3 mouseDirection = applicationInstance->getMouseRayDirection();
|
glm::vec3 mouseDirection = applicationInstance->getMouseRayDirection();
|
||||||
|
|
|
@ -49,9 +49,9 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) {
|
||||||
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
||||||
// get the rotation axes in joint space and use them to adjust the rotation
|
// get the rotation axes in joint space and use them to adjust the rotation
|
||||||
glm::mat3 axes = glm::mat3_cast(glm::quat());
|
glm::mat3 axes = glm::mat3_cast(glm::quat());
|
||||||
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) *
|
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(state.getDefaultTranslationInConstrainedFrame()) *
|
||||||
joint.preTransform * glm::mat4_cast(joint.preRotation)));
|
joint.preTransform * glm::mat4_cast(joint.preRotation)));
|
||||||
state.setRotationInParentFrame(glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2]))
|
state.setRotationInConstrainedFrame(glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2]))
|
||||||
* glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1]))
|
* glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1]))
|
||||||
* glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalPitch(), glm::normalize(inverse * axes[0]))
|
* glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalPitch(), glm::normalize(inverse * axes[0]))
|
||||||
* joint.rotation);
|
* joint.rotation);
|
||||||
|
@ -61,14 +61,14 @@ void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJ
|
||||||
// likewise with the eye joints
|
// likewise with the eye joints
|
||||||
// NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual.
|
// NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual.
|
||||||
glm::mat4 inverse = glm::inverse(glm::mat4_cast(_rotation) * parentState.getTransform() *
|
glm::mat4 inverse = glm::inverse(glm::mat4_cast(_rotation) * parentState.getTransform() *
|
||||||
glm::translate(state.getDefaultTranslationInParentFrame()) *
|
glm::translate(state.getDefaultTranslationInConstrainedFrame()) *
|
||||||
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
|
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
|
||||||
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f));
|
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f));
|
||||||
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() +
|
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() +
|
||||||
_owningHead->getSaccade() - _translation, 1.0f));
|
_owningHead->getSaccade() - _translation, 1.0f));
|
||||||
glm::quat between = rotationBetween(front, lookAt);
|
glm::quat between = rotationBetween(front, lookAt);
|
||||||
const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE;
|
const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE;
|
||||||
state.setRotationInParentFrame(glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
|
state.setRotationInConstrainedFrame(glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
|
||||||
joint.rotation);
|
joint.rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,15 +108,10 @@ void MyAvatar::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::update(float deltaTime) {
|
void MyAvatar::update(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("MyAvatar::update/");
|
|
||||||
Head* head = getHead();
|
Head* head = getHead();
|
||||||
head->relaxLean(deltaTime);
|
head->relaxLean(deltaTime);
|
||||||
{
|
updateFromTrackers(deltaTime);
|
||||||
PerformanceTimer perfTimer("MyAvatar::update/updateFromTrackers");
|
|
||||||
updateFromTrackers(deltaTime);
|
|
||||||
}
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::MoveWithLean)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::MoveWithLean)) {
|
||||||
PerformanceTimer perfTimer("MyAvatar::update/moveWithLean");
|
|
||||||
// Faceshift drive is enabled, set the avatar drive based on the head position
|
// Faceshift drive is enabled, set the avatar drive based on the head position
|
||||||
moveWithLean();
|
moveWithLean();
|
||||||
}
|
}
|
||||||
|
@ -127,19 +122,14 @@ void MyAvatar::update(float deltaTime) {
|
||||||
head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness());
|
head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness());
|
||||||
|
|
||||||
if (_motionBehaviors & AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY) {
|
if (_motionBehaviors & AVATAR_MOTION_OBEY_ENVIRONMENTAL_GRAVITY) {
|
||||||
PerformanceTimer perfTimer("MyAvatar::update/gravityWork");
|
|
||||||
setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition()));
|
setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition()));
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
simulate(deltaTime);
|
||||||
PerformanceTimer perfTimer("MyAvatar::update/simulate");
|
|
||||||
simulate(deltaTime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MyAvatar::simulate(float deltaTime) {
|
void MyAvatar::simulate(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate");
|
PerformanceTimer perfTimer("simulate");
|
||||||
|
|
||||||
if (_scale != _targetScale) {
|
if (_scale != _targetScale) {
|
||||||
float scale = (1.0f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale;
|
float scale = (1.0f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale;
|
||||||
setScale(scale);
|
setScale(scale);
|
||||||
|
@ -150,31 +140,28 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
_handState = HAND_STATE_NULL;
|
_handState = HAND_STATE_NULL;
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/updateOrientation");
|
PerformanceTimer perfTimer("transform");
|
||||||
updateOrientation(deltaTime);
|
updateOrientation(deltaTime);
|
||||||
}
|
|
||||||
{
|
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/updatePosition");
|
|
||||||
updatePosition(deltaTime);
|
updatePosition(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/hand Collision,simulate");
|
PerformanceTimer perfTimer("hand");
|
||||||
// update avatar skeleton and simulate hand and head
|
// update avatar skeleton and simulate hand and head
|
||||||
getHand()->simulate(deltaTime, true);
|
getHand()->simulate(deltaTime, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/_skeletonModel.simulate()");
|
PerformanceTimer perfTimer("skeleton");
|
||||||
_skeletonModel.simulate(deltaTime);
|
_skeletonModel.simulate(deltaTime);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/simulateAttachments");
|
PerformanceTimer perfTimer("attachments");
|
||||||
simulateAttachments(deltaTime);
|
simulateAttachments(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/copy joints");
|
PerformanceTimer perfTimer("joints");
|
||||||
// copy out the skeleton joints from the model
|
// copy out the skeleton joints from the model
|
||||||
_jointData.resize(_skeletonModel.getJointStateCount());
|
_jointData.resize(_skeletonModel.getJointStateCount());
|
||||||
for (int i = 0; i < _jointData.size(); i++) {
|
for (int i = 0; i < _jointData.size(); i++) {
|
||||||
|
@ -184,7 +171,7 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/head Simulate");
|
PerformanceTimer perfTimer("head");
|
||||||
Head* head = getHead();
|
Head* head = getHead();
|
||||||
glm::vec3 headPosition;
|
glm::vec3 headPosition;
|
||||||
if (!_skeletonModel.getHeadPosition(headPosition)) {
|
if (!_skeletonModel.getHeadPosition(headPosition)) {
|
||||||
|
@ -196,14 +183,17 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/hair Simulate");
|
PerformanceTimer perfTimer("hair");
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
|
||||||
simulateHair(deltaTime);
|
simulateHair(deltaTime);
|
||||||
|
foreach (Hair* hair, _hairs) {
|
||||||
|
hair->simulate(deltaTime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/ragdoll");
|
PerformanceTimer perfTimer("ragdoll");
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CollideAsRagdoll)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::CollideAsRagdoll)) {
|
||||||
const int minError = 0.01f;
|
const int minError = 0.01f;
|
||||||
const float maxIterations = 10;
|
const float maxIterations = 10;
|
||||||
|
@ -216,7 +206,7 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
|
|
||||||
// now that we're done stepping the avatar forward in time, compute new collisions
|
// now that we're done stepping the avatar forward in time, compute new collisions
|
||||||
if (_collisionGroups != 0) {
|
if (_collisionGroups != 0) {
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/_collisionGroups");
|
PerformanceTimer perfTimer("collisions");
|
||||||
Camera* myCamera = Application::getInstance()->getCamera();
|
Camera* myCamera = Application::getInstance()->getCamera();
|
||||||
|
|
||||||
float radius = getSkeletonHeight() * COLLISION_RADIUS_SCALE;
|
float radius = getSkeletonHeight() * COLLISION_RADIUS_SCALE;
|
||||||
|
@ -225,18 +215,18 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
radius *= COLLISION_RADIUS_SCALAR;
|
radius *= COLLISION_RADIUS_SCALAR;
|
||||||
}
|
}
|
||||||
if (_collisionGroups & COLLISION_GROUP_ENVIRONMENT) {
|
if (_collisionGroups & COLLISION_GROUP_ENVIRONMENT) {
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/updateCollisionWithEnvironment");
|
PerformanceTimer perfTimer("environment");
|
||||||
updateCollisionWithEnvironment(deltaTime, radius);
|
updateCollisionWithEnvironment(deltaTime, radius);
|
||||||
}
|
}
|
||||||
if (_collisionGroups & COLLISION_GROUP_VOXELS) {
|
if (_collisionGroups & COLLISION_GROUP_VOXELS) {
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/updateCollisionWithVoxels");
|
PerformanceTimer perfTimer("voxels");
|
||||||
updateCollisionWithVoxels(deltaTime, radius);
|
updateCollisionWithVoxels(deltaTime, radius);
|
||||||
} else {
|
} else {
|
||||||
_trapDuration = 0.0f;
|
_trapDuration = 0.0f;
|
||||||
}
|
}
|
||||||
/* TODO: Andrew to make this work
|
/* TODO: Andrew to make this work
|
||||||
if (_collisionGroups & COLLISION_GROUP_AVATARS) {
|
if (_collisionGroups & COLLISION_GROUP_AVATARS) {
|
||||||
PerformanceTimer perfTimer("MyAvatar::simulate/updateCollisionWithAvatars");
|
PerformanceTimer perfTimer("avatars");
|
||||||
updateCollisionWithAvatars(deltaTime);
|
updateCollisionWithAvatars(deltaTime);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
@ -896,6 +886,9 @@ void MyAvatar::renderBody(RenderMode renderMode, float glowLevel) {
|
||||||
getHead()->render(1.0f, modelRenderMode);
|
getHead()->render(1.0f, modelRenderMode);
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
|
||||||
renderHair();
|
renderHair();
|
||||||
|
foreach (Hair* hair, _hairs) {
|
||||||
|
hair->render();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
getHand()->render(true, modelRenderMode);
|
getHand()->render(true, modelRenderMode);
|
||||||
|
@ -910,7 +903,6 @@ bool MyAvatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode rend
|
||||||
}
|
}
|
||||||
|
|
||||||
float MyAvatar::computeDistanceToFloor(const glm::vec3& startPoint) {
|
float MyAvatar::computeDistanceToFloor(const glm::vec3& startPoint) {
|
||||||
PerformanceTimer perfTimer("MyAvatar::computeDistanceToFloor()");
|
|
||||||
glm::vec3 direction = -_worldUpDirection;
|
glm::vec3 direction = -_worldUpDirection;
|
||||||
OctreeElement* elementHit; // output from findRayIntersection
|
OctreeElement* elementHit; // output from findRayIntersection
|
||||||
float distance = FLT_MAX; // output from findRayIntersection
|
float distance = FLT_MAX; // output from findRayIntersection
|
||||||
|
@ -976,7 +968,6 @@ void MyAvatar::updateOrientation(float deltaTime) {
|
||||||
const float NEARBY_FLOOR_THRESHOLD = 5.0f;
|
const float NEARBY_FLOOR_THRESHOLD = 5.0f;
|
||||||
|
|
||||||
void MyAvatar::updatePosition(float deltaTime) {
|
void MyAvatar::updatePosition(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("MyAvatar::updatePosition");
|
|
||||||
float keyboardInput = fabsf(_driveKeys[FWD] - _driveKeys[BACK]) +
|
float keyboardInput = fabsf(_driveKeys[FWD] - _driveKeys[BACK]) +
|
||||||
fabsf(_driveKeys[RIGHT] - _driveKeys[LEFT]) +
|
fabsf(_driveKeys[RIGHT] - _driveKeys[LEFT]) +
|
||||||
fabsf(_driveKeys[UP] - _driveKeys[DOWN]);
|
fabsf(_driveKeys[UP] - _driveKeys[DOWN]);
|
||||||
|
|
|
@ -219,7 +219,7 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
|
||||||
JointState& parentState = _jointStates[parentJointIndex];
|
JointState& parentState = _jointStates[parentJointIndex];
|
||||||
parentState.setRotationFromBindFrame(palmRotation, PALM_PRIORITY);
|
parentState.setRotationFromBindFrame(palmRotation, PALM_PRIORITY);
|
||||||
// lock hand to forearm by slamming its rotation (in parent-frame) to identity
|
// lock hand to forearm by slamming its rotation (in parent-frame) to identity
|
||||||
_jointStates[jointIndex].setRotationInParentFrame(glm::quat());
|
_jointStates[jointIndex].setRotationInConstrainedFrame(glm::quat());
|
||||||
} else {
|
} else {
|
||||||
inverseKinematics(jointIndex, palmPosition, palmRotation, PALM_PRIORITY);
|
inverseKinematics(jointIndex, palmPosition, palmRotation, PALM_PRIORITY);
|
||||||
}
|
}
|
||||||
|
@ -255,9 +255,9 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const
|
||||||
}
|
}
|
||||||
// get the rotation axes in joint space and use them to adjust the rotation
|
// get the rotation axes in joint space and use them to adjust the rotation
|
||||||
glm::mat3 axes = glm::mat3_cast(glm::quat());
|
glm::mat3 axes = glm::mat3_cast(glm::quat());
|
||||||
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) *
|
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(state.getDefaultTranslationInConstrainedFrame()) *
|
||||||
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)));
|
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)));
|
||||||
state.setRotationInParentFrame(glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(),
|
state.setRotationInConstrainedFrame(glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(),
|
||||||
glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(),
|
glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(),
|
||||||
glm::normalize(inverse * axes[0])) * joint.rotation);
|
glm::normalize(inverse * axes[0])) * joint.rotation);
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,6 +109,7 @@ public:
|
||||||
void resetShapePositionsToDefaultPose(); // DEBUG method
|
void resetShapePositionsToDefaultPose(); // DEBUG method
|
||||||
|
|
||||||
void renderRagdoll();
|
void renderRagdoll();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// virtual overrrides from Ragdoll
|
// virtual overrrides from Ragdoll
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <PerfStat.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
|
@ -75,6 +76,7 @@ void Faceshift::update() {
|
||||||
if (!isActive()) {
|
if (!isActive()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
PerformanceTimer perfTimer("faceshift");
|
||||||
// get the euler angles relative to the window
|
// get the euler angles relative to the window
|
||||||
glm::vec3 eulers = glm::degrees(safeEulerAngles(_headRotation * glm::quat(glm::radians(glm::vec3(
|
glm::vec3 eulers = glm::degrees(safeEulerAngles(_headRotation * glm::quat(glm::radians(glm::vec3(
|
||||||
(_eyeGazeLeftPitch + _eyeGazeRightPitch) / 2.0f, (_eyeGazeLeftYaw + _eyeGazeRightYaw) / 2.0f, 0.0f)))));
|
(_eyeGazeLeftPitch + _eyeGazeRightPitch) / 2.0f, (_eyeGazeLeftYaw + _eyeGazeRightYaw) / 2.0f, 0.0f)))));
|
||||||
|
|
|
@ -12,9 +12,10 @@
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
|
#include <PerfStat.h>
|
||||||
|
|
||||||
#include "JoystickManager.h"
|
#include "JoystickManager.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -46,6 +47,7 @@ JoystickManager::~JoystickManager() {
|
||||||
|
|
||||||
void JoystickManager::update() {
|
void JoystickManager::update() {
|
||||||
#ifdef HAVE_SDL
|
#ifdef HAVE_SDL
|
||||||
|
PerformanceTimer perfTimer("joystick");
|
||||||
SDL_JoystickUpdate();
|
SDL_JoystickUpdate();
|
||||||
|
|
||||||
for (int i = 0; i < _joystickStates.size(); i++) {
|
for (int i = 0; i < _joystickStates.size(); i++) {
|
||||||
|
|
|
@ -269,7 +269,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
|
||||||
// We only need to render the overlays to a texture once, then we just render the texture on the hemisphere
|
// We only need to render the overlays to a texture once, then we just render the texture on the hemisphere
|
||||||
// PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay()
|
// PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay()
|
||||||
applicationOverlay.renderOverlay(true);
|
applicationOverlay.renderOverlay(true);
|
||||||
const bool displayOverlays = Menu::getInstance()->isOptionChecked(MenuOption::DisplayOculusOverlays);
|
const bool displayOverlays = Menu::getInstance()->isOptionChecked(MenuOption::UserInterface);
|
||||||
|
|
||||||
//Bind our framebuffer object. If we are rendering the glow effect, we let the glow effect shader take care of it
|
//Bind our framebuffer object. If we are rendering the glow effect, we let the glow effect shader take care of it
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)) {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
|
|
||||||
#include <FBXReader.h>
|
#include <FBXReader.h>
|
||||||
|
#include <PerfStat.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "PrioVR.h"
|
#include "PrioVR.h"
|
||||||
|
@ -166,6 +167,7 @@ void PrioVR::update(float deltaTime) {
|
||||||
if (!_skeletalDevice) {
|
if (!_skeletalDevice) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
PerformanceTimer perfTimer("PrioVR");
|
||||||
unsigned int timestamp;
|
unsigned int timestamp;
|
||||||
yei_getLastStreamDataAll(_skeletalDevice, (char*)_jointRotations.data(),
|
yei_getLastStreamDataAll(_skeletalDevice, (char*)_jointRotations.data(),
|
||||||
_jointRotations.size() * sizeof(glm::quat), ×tamp);
|
_jointRotations.size() * sizeof(glm::quat), ×tamp);
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <PerfStat.h>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "SixenseManager.h"
|
#include "SixenseManager.h"
|
||||||
#include "UserActivityLogger.h"
|
#include "UserActivityLogger.h"
|
||||||
|
@ -32,6 +34,7 @@ SixenseManager::SixenseManager() {
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
_lastMovement = 0;
|
_lastMovement = 0;
|
||||||
_amountMoved = glm::vec3(0.0f);
|
_amountMoved = glm::vec3(0.0f);
|
||||||
|
_lowVelocityFilter = false;
|
||||||
|
|
||||||
_calibrationState = CALIBRATION_STATE_IDLE;
|
_calibrationState = CALIBRATION_STATE_IDLE;
|
||||||
// By default we assume the _neckBase (in orb frame) is as high above the orb
|
// By default we assume the _neckBase (in orb frame) is as high above the orb
|
||||||
|
@ -60,10 +63,8 @@ SixenseManager::~SixenseManager() {
|
||||||
void SixenseManager::setFilter(bool filter) {
|
void SixenseManager::setFilter(bool filter) {
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
if (filter) {
|
if (filter) {
|
||||||
qDebug("Sixense Filter ON");
|
|
||||||
sixenseSetFilterEnabled(1);
|
sixenseSetFilterEnabled(1);
|
||||||
} else {
|
} else {
|
||||||
qDebug("Sixense Filter OFF");
|
|
||||||
sixenseSetFilterEnabled(0);
|
sixenseSetFilterEnabled(0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -84,7 +85,10 @@ void SixenseManager::update(float deltaTime) {
|
||||||
if (sixenseGetNumActiveControllers() == 0) {
|
if (sixenseGetNumActiveControllers() == 0) {
|
||||||
_hydrasConnected = false;
|
_hydrasConnected = false;
|
||||||
return;
|
return;
|
||||||
} else if (!_hydrasConnected) {
|
}
|
||||||
|
|
||||||
|
PerformanceTimer perfTimer("sixense");
|
||||||
|
if (!_hydrasConnected) {
|
||||||
_hydrasConnected = true;
|
_hydrasConnected = true;
|
||||||
UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra");
|
UserActivityLogger::getInstance().connectedDevice("spatial_controller", "hydra");
|
||||||
}
|
}
|
||||||
|
@ -160,17 +164,21 @@ void SixenseManager::update(float deltaTime) {
|
||||||
}
|
}
|
||||||
palm->setRawVelocity(rawVelocity); // meters/sec
|
palm->setRawVelocity(rawVelocity); // meters/sec
|
||||||
|
|
||||||
// Use a velocity sensitive filter to damp small motions and preserve large ones with
|
|
||||||
// no latency.
|
|
||||||
float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f);
|
|
||||||
palm->setRawPosition(palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter));
|
|
||||||
|
|
||||||
// adjustment for hydra controllers fit into hands
|
// adjustment for hydra controllers fit into hands
|
||||||
float sign = (i == 0) ? -1.0f : 1.0f;
|
float sign = (i == 0) ? -1.0f : 1.0f;
|
||||||
rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f));
|
rotation *= glm::angleAxis(sign * PI/4.0f, glm::vec3(0.0f, 0.0f, 1.0f));
|
||||||
|
|
||||||
palm->setRawRotation(safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter));
|
if (_lowVelocityFilter) {
|
||||||
|
// Use a velocity sensitive filter to damp small motions and preserve large ones with
|
||||||
|
// no latency.
|
||||||
|
float velocityFilter = glm::clamp(1.0f - glm::length(rawVelocity), 0.0f, 1.0f);
|
||||||
|
palm->setRawPosition(palm->getRawPosition() * velocityFilter + position * (1.0f - velocityFilter));
|
||||||
|
palm->setRawRotation(safeMix(palm->getRawRotation(), rotation, 1.0f - velocityFilter));
|
||||||
|
} else {
|
||||||
|
palm->setRawPosition(position);
|
||||||
|
palm->setRawRotation(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
// use the velocity to determine whether there's any movement (if the hand isn't new)
|
// use the velocity to determine whether there's any movement (if the hand isn't new)
|
||||||
const float MOVEMENT_DISTANCE_THRESHOLD = 0.003f;
|
const float MOVEMENT_DISTANCE_THRESHOLD = 0.003f;
|
||||||
_amountMoved += rawVelocity * deltaTime;
|
_amountMoved += rawVelocity * deltaTime;
|
||||||
|
|
|
@ -47,6 +47,7 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void setFilter(bool filter);
|
void setFilter(bool filter);
|
||||||
|
void setLowVelocityFilter(bool lowVelocityFilter) { _lowVelocityFilter = lowVelocityFilter; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef HAVE_SIXENSE
|
#ifdef HAVE_SIXENSE
|
||||||
|
@ -80,6 +81,8 @@ private:
|
||||||
bool _bumperPressed[2];
|
bool _bumperPressed[2];
|
||||||
int _oldX[2];
|
int _oldX[2];
|
||||||
int _oldY[2];
|
int _oldY[2];
|
||||||
|
|
||||||
|
bool _lowVelocityFilter;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_SixenseManager_h
|
#endif // hifi_SixenseManager_h
|
||||||
|
|
|
@ -100,6 +100,7 @@ void TV3DManager::display(Camera& whichCamera) {
|
||||||
// We only need to render the overlays to a texture once, then we just render the texture as a quad
|
// We only need to render the overlays to a texture once, then we just render the texture as a quad
|
||||||
// PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay()
|
// PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay()
|
||||||
applicationOverlay.renderOverlay(true);
|
applicationOverlay.renderOverlay(true);
|
||||||
|
const bool displayOverlays = Menu::getInstance()->isOptionChecked(MenuOption::UserInterface);
|
||||||
|
|
||||||
if (glowEnabled) {
|
if (glowEnabled) {
|
||||||
Application::getInstance()->getGlowEffect()->prepare();
|
Application::getInstance()->getGlowEffect()->prepare();
|
||||||
|
@ -128,7 +129,9 @@ void TV3DManager::display(Camera& whichCamera) {
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
Application::getInstance()->displaySide(whichCamera);
|
Application::getInstance()->displaySide(whichCamera);
|
||||||
|
|
||||||
applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov);
|
if (displayOverlays) {
|
||||||
|
applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
@ -154,7 +157,9 @@ void TV3DManager::display(Camera& whichCamera) {
|
||||||
glLoadIdentity();
|
glLoadIdentity();
|
||||||
Application::getInstance()->displaySide(whichCamera);
|
Application::getInstance()->displaySide(whichCamera);
|
||||||
|
|
||||||
applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov);
|
if (displayOverlays) {
|
||||||
|
applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
glDisable(GL_SCISSOR_TEST);
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
|
|
||||||
|
#include <PerfStat.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
|
|
||||||
#include <FBXReader.h>
|
#include <FBXReader.h>
|
||||||
|
@ -128,6 +129,7 @@ void Visage::update() {
|
||||||
if (!_active) {
|
if (!_active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
PerformanceTimer perfTimer("visage");
|
||||||
_headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2]));
|
_headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2]));
|
||||||
_headTranslation = (glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) -
|
_headTranslation = (glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) -
|
||||||
_headOrigin) * TRANSLATION_SCALE;
|
_headOrigin) * TRANSLATION_SCALE;
|
||||||
|
|
|
@ -121,7 +121,7 @@ static void maybeRelease(QOpenGLFramebufferObject* fbo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) {
|
QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) {
|
||||||
PerformanceTimer perfTimer("paintGL/glowEffect");
|
PerformanceTimer perfTimer("glowEffect");
|
||||||
|
|
||||||
QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject();
|
QOpenGLFramebufferObject* primaryFBO = Application::getInstance()->getTextureCache()->getPrimaryFramebufferObject();
|
||||||
primaryFBO->release();
|
primaryFBO->release();
|
||||||
|
|
|
@ -26,7 +26,7 @@ JointState::JointState() :
|
||||||
JointState::JointState(const JointState& other) : _constraint(NULL) {
|
JointState::JointState(const JointState& other) : _constraint(NULL) {
|
||||||
_transform = other._transform;
|
_transform = other._transform;
|
||||||
_rotation = other._rotation;
|
_rotation = other._rotation;
|
||||||
_rotationInParentFrame = other._rotationInParentFrame;
|
_rotationInConstrainedFrame = other._rotationInConstrainedFrame;
|
||||||
_animationPriority = other._animationPriority;
|
_animationPriority = other._animationPriority;
|
||||||
_fbxJoint = other._fbxJoint;
|
_fbxJoint = other._fbxJoint;
|
||||||
// DO NOT copy _constraint
|
// DO NOT copy _constraint
|
||||||
|
@ -43,7 +43,7 @@ JointState::~JointState() {
|
||||||
|
|
||||||
void JointState::setFBXJoint(const FBXJoint* joint) {
|
void JointState::setFBXJoint(const FBXJoint* joint) {
|
||||||
assert(joint != NULL);
|
assert(joint != NULL);
|
||||||
_rotationInParentFrame = joint->rotation;
|
_rotationInConstrainedFrame = joint->rotation;
|
||||||
// NOTE: JointState does not own the FBXJoint to which it points.
|
// NOTE: JointState does not own the FBXJoint to which it points.
|
||||||
_fbxJoint = joint;
|
_fbxJoint = joint;
|
||||||
if (_constraint) {
|
if (_constraint) {
|
||||||
|
@ -68,24 +68,24 @@ void JointState::copyState(const JointState& state) {
|
||||||
_animationPriority = state._animationPriority;
|
_animationPriority = state._animationPriority;
|
||||||
_transform = state._transform;
|
_transform = state._transform;
|
||||||
_rotation = extractRotation(_transform);
|
_rotation = extractRotation(_transform);
|
||||||
_rotationInParentFrame = state._rotationInParentFrame;
|
_rotationInConstrainedFrame = state._rotationInConstrainedFrame;
|
||||||
|
|
||||||
_visibleTransform = state._visibleTransform;
|
_visibleTransform = state._visibleTransform;
|
||||||
_visibleRotation = extractRotation(_visibleTransform);
|
_visibleRotation = extractRotation(_visibleTransform);
|
||||||
_visibleRotationInParentFrame = state._visibleRotationInParentFrame;
|
_visibleRotationInConstrainedFrame = state._visibleRotationInConstrainedFrame;
|
||||||
// DO NOT copy _fbxJoint or _constraint
|
// DO NOT copy _fbxJoint or _constraint
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::computeTransform(const glm::mat4& parentTransform) {
|
void JointState::computeTransform(const glm::mat4& parentTransform) {
|
||||||
glm::quat modifiedRotation = _fbxJoint->preRotation * _rotationInParentFrame * _fbxJoint->postRotation;
|
glm::quat rotationInConstrainedFrame = _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation;
|
||||||
glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(modifiedRotation) * _fbxJoint->postTransform;
|
glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(rotationInConstrainedFrame) * _fbxJoint->postTransform;
|
||||||
_transform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform;
|
_transform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform;
|
||||||
_rotation = extractRotation(_transform);
|
_rotation = extractRotation(_transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::computeVisibleTransform(const glm::mat4& parentTransform) {
|
void JointState::computeVisibleTransform(const glm::mat4& parentTransform) {
|
||||||
glm::quat modifiedRotation = _fbxJoint->preRotation * _visibleRotationInParentFrame * _fbxJoint->postRotation;
|
glm::quat rotationInConstrainedFrame = _fbxJoint->preRotation * _visibleRotationInConstrainedFrame * _fbxJoint->postRotation;
|
||||||
glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(modifiedRotation) * _fbxJoint->postTransform;
|
glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(rotationInConstrainedFrame) * _fbxJoint->postTransform;
|
||||||
_visibleTransform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform;
|
_visibleTransform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform;
|
||||||
_visibleRotation = extractRotation(_visibleTransform);
|
_visibleRotation = extractRotation(_visibleTransform);
|
||||||
}
|
}
|
||||||
|
@ -97,7 +97,7 @@ glm::quat JointState::getRotationFromBindToModelFrame() const {
|
||||||
void JointState::restoreRotation(float fraction, float priority) {
|
void JointState::restoreRotation(float fraction, float priority) {
|
||||||
assert(_fbxJoint != NULL);
|
assert(_fbxJoint != NULL);
|
||||||
if (priority == _animationPriority || _animationPriority == 0.0f) {
|
if (priority == _animationPriority || _animationPriority == 0.0f) {
|
||||||
setRotationInParentFrame(safeMix(_rotationInParentFrame, _fbxJoint->rotation, fraction));
|
setRotationInConstrainedFrame(safeMix(_rotationInConstrainedFrame, _fbxJoint->rotation, fraction));
|
||||||
_animationPriority = 0.0f;
|
_animationPriority = 0.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,11 +106,11 @@ void JointState::setRotationFromBindFrame(const glm::quat& rotation, float prior
|
||||||
// rotation is from bind- to model-frame
|
// rotation is from bind- to model-frame
|
||||||
assert(_fbxJoint != NULL);
|
assert(_fbxJoint != NULL);
|
||||||
if (priority >= _animationPriority) {
|
if (priority >= _animationPriority) {
|
||||||
glm::quat targetRotation = _rotationInParentFrame * glm::inverse(_rotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation);
|
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(_rotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation);
|
||||||
if (constrain && _constraint) {
|
if (constrain && _constraint) {
|
||||||
_constraint->softClamp(targetRotation, _rotationInParentFrame, 0.5f);
|
_constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f);
|
||||||
}
|
}
|
||||||
setRotationInParentFrame(targetRotation);
|
setRotationInConstrainedFrame(targetRotation);
|
||||||
_animationPriority = priority;
|
_animationPriority = priority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,12 +137,12 @@ void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, floa
|
||||||
_animationPriority = priority;
|
_animationPriority = priority;
|
||||||
if (!constrain || _constraint == NULL) {
|
if (!constrain || _constraint == NULL) {
|
||||||
// no constraints
|
// no constraints
|
||||||
_rotationInParentFrame = _rotationInParentFrame * glm::inverse(_rotation) * delta * _rotation;
|
_rotationInConstrainedFrame = _rotationInConstrainedFrame * glm::inverse(_rotation) * delta * _rotation;
|
||||||
_rotation = delta * _rotation;
|
_rotation = delta * _rotation;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
glm::quat targetRotation = _rotationInParentFrame * glm::inverse(_rotation) * delta * _rotation;
|
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(_rotation) * delta * _rotation;
|
||||||
setRotationInParentFrame(targetRotation);
|
setRotationInConstrainedFrame(targetRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Applies delta rotation to joint but mixes a little bit of the default pose as well.
|
/// Applies delta rotation to joint but mixes a little bit of the default pose as well.
|
||||||
|
@ -154,30 +154,30 @@ void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_animationPriority = priority;
|
_animationPriority = priority;
|
||||||
glm::quat targetRotation = _rotationInParentFrame * glm::inverse(_rotation) * delta * _rotation;
|
glm::quat targetRotation = _rotationInConstrainedFrame * glm::inverse(_rotation) * delta * _rotation;
|
||||||
if (mixFactor > 0.0f && mixFactor <= 1.0f) {
|
if (mixFactor > 0.0f && mixFactor <= 1.0f) {
|
||||||
targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor);
|
targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor);
|
||||||
}
|
}
|
||||||
if (_constraint) {
|
if (_constraint) {
|
||||||
_constraint->softClamp(targetRotation, _rotationInParentFrame, 0.5f);
|
_constraint->softClamp(targetRotation, _rotationInConstrainedFrame, 0.5f);
|
||||||
}
|
}
|
||||||
setRotationInParentFrame(targetRotation);
|
setRotationInConstrainedFrame(targetRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat JointState::computeParentRotation() const {
|
glm::quat JointState::computeParentRotation() const {
|
||||||
// R = Rp * Rpre * r * Rpost
|
// R = Rp * Rpre * r * Rpost
|
||||||
// Rp = R * (Rpre * r * Rpost)^
|
// Rp = R * (Rpre * r * Rpost)^
|
||||||
return _rotation * glm::inverse(_fbxJoint->preRotation * _rotationInParentFrame * _fbxJoint->postRotation);
|
return _rotation * glm::inverse(_fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JointState::setRotationInParentFrame(const glm::quat& targetRotation) {
|
void JointState::setRotationInConstrainedFrame(const glm::quat& targetRotation) {
|
||||||
glm::quat parentRotation = computeParentRotation();
|
glm::quat parentRotation = computeParentRotation();
|
||||||
_rotationInParentFrame = targetRotation;
|
_rotationInConstrainedFrame = targetRotation;
|
||||||
// R' = Rp * Rpre * r' * Rpost
|
// R' = Rp * Rpre * r' * Rpost
|
||||||
_rotation = parentRotation * _fbxJoint->preRotation * _rotationInParentFrame * _fbxJoint->postRotation;
|
_rotation = parentRotation * _fbxJoint->preRotation * _rotationInConstrainedFrame * _fbxJoint->postRotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
const glm::vec3& JointState::getDefaultTranslationInParentFrame() const {
|
const glm::vec3& JointState::getDefaultTranslationInConstrainedFrame() const {
|
||||||
assert(_fbxJoint != NULL);
|
assert(_fbxJoint != NULL);
|
||||||
return _fbxJoint->translation;
|
return _fbxJoint->translation;
|
||||||
}
|
}
|
||||||
|
@ -185,5 +185,5 @@ const glm::vec3& JointState::getDefaultTranslationInParentFrame() const {
|
||||||
void JointState::slaveVisibleTransform() {
|
void JointState::slaveVisibleTransform() {
|
||||||
_visibleTransform = _transform;
|
_visibleTransform = _transform;
|
||||||
_visibleRotation = _rotation;
|
_visibleRotation = _rotation;
|
||||||
_visibleRotationInParentFrame = _rotationInParentFrame;
|
_visibleRotationInConstrainedFrame = _rotationInConstrainedFrame;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,14 +66,14 @@ public:
|
||||||
void restoreRotation(float fraction, float priority);
|
void restoreRotation(float fraction, float priority);
|
||||||
|
|
||||||
/// \param rotation is from bind- to model-frame
|
/// \param rotation is from bind- to model-frame
|
||||||
/// computes and sets new _rotationInParentFrame
|
/// computes and sets new _rotationInConstrainedFrame
|
||||||
/// NOTE: the JointState's model-frame transform/rotation are NOT updated!
|
/// NOTE: the JointState's model-frame transform/rotation are NOT updated!
|
||||||
void setRotationFromBindFrame(const glm::quat& rotation, float priority, bool constrain = false);
|
void setRotationFromBindFrame(const glm::quat& rotation, float priority, bool constrain = false);
|
||||||
|
|
||||||
void setRotationInParentFrame(const glm::quat& targetRotation);
|
void setRotationInConstrainedFrame(const glm::quat& targetRotation);
|
||||||
const glm::quat& getRotationInParentFrame() const { return _rotationInParentFrame; }
|
const glm::quat& getRotationInConstrainedFrame() const { return _rotationInConstrainedFrame; }
|
||||||
|
|
||||||
const glm::vec3& getDefaultTranslationInParentFrame() const;
|
const glm::vec3& getDefaultTranslationInConstrainedFrame() const;
|
||||||
|
|
||||||
|
|
||||||
void clearTransformTranslation();
|
void clearTransformTranslation();
|
||||||
|
@ -92,11 +92,11 @@ private:
|
||||||
|
|
||||||
glm::mat4 _transform; // joint- to model-frame
|
glm::mat4 _transform; // joint- to model-frame
|
||||||
glm::quat _rotation; // joint- to model-frame
|
glm::quat _rotation; // joint- to model-frame
|
||||||
glm::quat _rotationInParentFrame; // joint- to parentJoint-frame
|
glm::quat _rotationInConstrainedFrame; // rotation in frame where angular constraints would be applied
|
||||||
|
|
||||||
glm::mat4 _visibleTransform;
|
glm::mat4 _visibleTransform;
|
||||||
glm::quat _visibleRotation;
|
glm::quat _visibleRotation;
|
||||||
glm::quat _visibleRotationInParentFrame;
|
glm::quat _visibleRotationInConstrainedFrame;
|
||||||
|
|
||||||
const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint
|
const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint
|
||||||
AngularConstraint* _constraint; // JointState owns its AngularConstraint
|
AngularConstraint* _constraint; // JointState owns its AngularConstraint
|
||||||
|
|
|
@ -460,7 +460,7 @@ void Model::reset() {
|
||||||
}
|
}
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
for (int i = 0; i < _jointStates.size(); i++) {
|
for (int i = 0; i < _jointStates.size(); i++) {
|
||||||
_jointStates[i].setRotationInParentFrame(geometry.joints.at(i).rotation);
|
_jointStates[i].setRotationInConstrainedFrame(geometry.joints.at(i).rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -688,7 +688,7 @@ bool Model::getJointState(int index, glm::quat& rotation) const {
|
||||||
if (index == -1 || index >= _jointStates.size()) {
|
if (index == -1 || index >= _jointStates.size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
rotation = _jointStates.at(index).getRotationInParentFrame();
|
rotation = _jointStates.at(index).getRotationInConstrainedFrame();
|
||||||
const glm::quat& defaultRotation = _geometry->getFBXGeometry().joints.at(index).rotation;
|
const glm::quat& defaultRotation = _geometry->getFBXGeometry().joints.at(index).rotation;
|
||||||
return glm::abs(rotation.x - defaultRotation.x) >= EPSILON ||
|
return glm::abs(rotation.x - defaultRotation.x) >= EPSILON ||
|
||||||
glm::abs(rotation.y - defaultRotation.y) >= EPSILON ||
|
glm::abs(rotation.y - defaultRotation.y) >= EPSILON ||
|
||||||
|
@ -701,7 +701,7 @@ void Model::setJointState(int index, bool valid, const glm::quat& rotation, floa
|
||||||
JointState& state = _jointStates[index];
|
JointState& state = _jointStates[index];
|
||||||
if (priority >= state._animationPriority) {
|
if (priority >= state._animationPriority) {
|
||||||
if (valid) {
|
if (valid) {
|
||||||
state.setRotationInParentFrame(rotation);
|
state.setRotationInConstrainedFrame(rotation);
|
||||||
state._animationPriority = priority;
|
state._animationPriority = priority;
|
||||||
} else {
|
} else {
|
||||||
state.restoreRotation(1.0f, priority);
|
state.restoreRotation(1.0f, priority);
|
||||||
|
@ -1488,14 +1488,19 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re
|
||||||
if (cascadedShadows) {
|
if (cascadedShadows) {
|
||||||
program->setUniform(skinLocations->shadowDistances, Application::getInstance()->getShadowDistances());
|
program->setUniform(skinLocations->shadowDistances, Application::getInstance()->getShadowDistances());
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
|
// local light uniforms
|
||||||
|
skinProgram->setUniformValue("numLocalLights", _numLocalLights);
|
||||||
|
skinProgram->setUniformArray("localLightDirections", _localLightDirections, MAX_LOCAL_LIGHTS);
|
||||||
|
skinProgram->setUniformArray("localLightColors", _localLightColors, MAX_LOCAL_LIGHTS);
|
||||||
|
} else {
|
||||||
glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]);
|
glMultMatrixf((const GLfloat*)&state.clusterMatrices[0]);
|
||||||
program->bind();
|
program->bind();
|
||||||
if (cascadedShadows) {
|
if (cascadedShadows) {
|
||||||
program->setUniform(shadowDistancesLocation, Application::getInstance()->getShadowDistances());
|
program->setUniform(shadowDistancesLocation, Application::getInstance()->getShadowDistances());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mesh.blendshapes.isEmpty()) {
|
if (mesh.blendshapes.isEmpty()) {
|
||||||
if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
|
if (!(mesh.tangents.isEmpty() || mode == SHADOW_RENDER_MODE)) {
|
||||||
activeProgram->setAttributeBuffer(tangentLocation, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3);
|
activeProgram->setAttributeBuffer(tangentLocation, GL_FLOAT, vertexCount * 2 * sizeof(glm::vec3), 3);
|
||||||
|
@ -1622,6 +1627,20 @@ void Model::renderMeshes(float alpha, RenderMode mode, bool translucent, bool re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Model::setLocalLightDirection(const glm::vec3& direction, int lightIndex) {
|
||||||
|
assert(lightIndex >= 0 && lightIndex < MAX_LOCAL_LIGHTS);
|
||||||
|
_localLightDirections[lightIndex] = direction;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::setLocalLightColor(const glm::vec3& color, int lightIndex) {
|
||||||
|
assert(lightIndex >= 0 && lightIndex < MAX_LOCAL_LIGHTS);
|
||||||
|
_localLightColors[lightIndex] = color;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Model::setNumLocalLights(int numLocalLights) {
|
||||||
|
_numLocalLights = numLocalLights;
|
||||||
|
}
|
||||||
|
|
||||||
void AnimationHandle::setURL(const QUrl& url) {
|
void AnimationHandle::setURL(const QUrl& url) {
|
||||||
if (_url != url) {
|
if (_url != url) {
|
||||||
_animation = Application::getInstance()->getAnimationCache()->getAnimation(_url = url);
|
_animation = Application::getInstance()->getAnimationCache()->getAnimation(_url = url);
|
||||||
|
@ -1768,7 +1787,7 @@ void AnimationHandle::applyFrame(float frameIndex) {
|
||||||
if (mapping != -1) {
|
if (mapping != -1) {
|
||||||
JointState& state = _model->_jointStates[mapping];
|
JointState& state = _model->_jointStates[mapping];
|
||||||
if (_priority >= state._animationPriority) {
|
if (_priority >= state._animationPriority) {
|
||||||
state.setRotationInParentFrame(safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction));
|
state.setRotationInConstrainedFrame(safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction));
|
||||||
state._animationPriority = _priority;
|
state._animationPriority = _priority;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@ class Shape;
|
||||||
typedef QSharedPointer<AnimationHandle> AnimationHandlePointer;
|
typedef QSharedPointer<AnimationHandle> AnimationHandlePointer;
|
||||||
typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
|
typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
|
||||||
|
|
||||||
|
const int MAX_LOCAL_LIGHTS = 2;
|
||||||
|
|
||||||
/// A generic 3D model displaying geometry loaded from a URL.
|
/// A generic 3D model displaying geometry loaded from a URL.
|
||||||
class Model : public QObject, public PhysicsEntity {
|
class Model : public QObject, public PhysicsEntity {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -143,6 +145,10 @@ public:
|
||||||
/// Sets blended vertices computed in a separate thread.
|
/// Sets blended vertices computed in a separate thread.
|
||||||
void setBlendedVertices(const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals);
|
void setBlendedVertices(const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals);
|
||||||
|
|
||||||
|
void setLocalLightDirection(const glm::vec3& direction, int lightIndex);
|
||||||
|
void setLocalLightColor(const glm::vec3& color, int lightIndex);
|
||||||
|
void setNumLocalLights(int numLocalLights);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QSharedPointer<NetworkGeometry> _geometry;
|
QSharedPointer<NetworkGeometry> _geometry;
|
||||||
|
|
||||||
|
@ -158,6 +164,10 @@ protected:
|
||||||
bool _showTrueJointTransforms;
|
bool _showTrueJointTransforms;
|
||||||
int _rootIndex;
|
int _rootIndex;
|
||||||
|
|
||||||
|
glm::vec3 _localLightDirections[MAX_LOCAL_LIGHTS];
|
||||||
|
glm::vec3 _localLightColors[MAX_LOCAL_LIGHTS];
|
||||||
|
int _numLocalLights;
|
||||||
|
|
||||||
QVector<JointState> _jointStates;
|
QVector<JointState> _jointStates;
|
||||||
|
|
||||||
class MeshState {
|
class MeshState {
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "ProgramObject.h"
|
#include "ProgramObject.h"
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
ProgramObject::ProgramObject(QObject* parent) : QGLShaderProgram(parent) {
|
ProgramObject::ProgramObject(QObject* parent) : QGLShaderProgram(parent) {
|
||||||
}
|
}
|
||||||
|
@ -22,3 +23,17 @@ void ProgramObject::setUniform(const char* name, const glm::vec3& value) {
|
||||||
setUniformValue(name, value.x, value.y, value.z);
|
setUniformValue(name, value.x, value.y, value.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProgramObject::setUniformArray(const char* name, const glm::vec3* values, int count) {
|
||||||
|
GLfloat* floatVal = new GLfloat[count*3];
|
||||||
|
int index = 0;
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
assert(index < count*3);
|
||||||
|
const float* valPtr = glm::value_ptr(values[i]);
|
||||||
|
floatVal[index++] = valPtr[0];
|
||||||
|
floatVal[index++] = valPtr[1];
|
||||||
|
floatVal[index++] = valPtr[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
setUniformValueArray(name, floatVal, count, 3);
|
||||||
|
delete[] floatVal;
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ public:
|
||||||
|
|
||||||
void setUniform(int location, const glm::vec3& value);
|
void setUniform(int location, const glm::vec3& value);
|
||||||
void setUniform(const char* name, const glm::vec3& value);
|
void setUniform(const char* name, const glm::vec3& value);
|
||||||
|
void setUniformArray(const char* name, const glm::vec3* values, int count);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ProgramObject_h
|
#endif // hifi_ProgramObject_h
|
||||||
|
|
|
@ -40,7 +40,6 @@ ApplicationOverlay::ApplicationOverlay() :
|
||||||
_framebufferObject(NULL),
|
_framebufferObject(NULL),
|
||||||
_textureFov(DEFAULT_OCULUS_UI_ANGULAR_SIZE * RADIANS_PER_DEGREE),
|
_textureFov(DEFAULT_OCULUS_UI_ANGULAR_SIZE * RADIANS_PER_DEGREE),
|
||||||
_alpha(1.0f),
|
_alpha(1.0f),
|
||||||
_active(true),
|
|
||||||
_crosshairTexture(0) {
|
_crosshairTexture(0) {
|
||||||
|
|
||||||
memset(_reticleActive, 0, sizeof(_reticleActive));
|
memset(_reticleActive, 0, sizeof(_reticleActive));
|
||||||
|
@ -70,8 +69,8 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) {
|
||||||
QGLWidget* glWidget = application->getGLWidget();
|
QGLWidget* glWidget = application->getGLWidget();
|
||||||
MyAvatar* myAvatar = application->getAvatar();
|
MyAvatar* myAvatar = application->getAvatar();
|
||||||
|
|
||||||
//Handle fadeing and deactivation/activation of UI
|
//Handle fading and deactivation/activation of UI
|
||||||
if (_active) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::UserInterface)) {
|
||||||
_alpha += FADE_SPEED;
|
_alpha += FADE_SPEED;
|
||||||
if (_alpha > 1.0f) {
|
if (_alpha > 1.0f) {
|
||||||
_alpha = 1.0f;
|
_alpha = 1.0f;
|
||||||
|
@ -485,7 +484,8 @@ void ApplicationOverlay::renderControllerPointers() {
|
||||||
if (palmData->getTrigger() == 1.0f) {
|
if (palmData->getTrigger() == 1.0f) {
|
||||||
if (!triggerPressed[index]) {
|
if (!triggerPressed[index]) {
|
||||||
if (bumperPressed[index]) {
|
if (bumperPressed[index]) {
|
||||||
_active = !_active;
|
Menu::getInstance()->setIsOptionChecked(MenuOption::UserInterface,
|
||||||
|
!Menu::getInstance()->isOptionChecked(MenuOption::UserInterface));
|
||||||
}
|
}
|
||||||
triggerPressed[index] = true;
|
triggerPressed[index] = true;
|
||||||
}
|
}
|
||||||
|
@ -495,7 +495,8 @@ void ApplicationOverlay::renderControllerPointers() {
|
||||||
if ((controllerButtons & BUTTON_FWD)) {
|
if ((controllerButtons & BUTTON_FWD)) {
|
||||||
if (!bumperPressed[index]) {
|
if (!bumperPressed[index]) {
|
||||||
if (triggerPressed[index]) {
|
if (triggerPressed[index]) {
|
||||||
_active = !_active;
|
Menu::getInstance()->setIsOptionChecked(MenuOption::UserInterface,
|
||||||
|
!Menu::getInstance()->isOptionChecked(MenuOption::UserInterface));
|
||||||
}
|
}
|
||||||
bumperPressed[index] = true;
|
bumperPressed[index] = true;
|
||||||
}
|
}
|
||||||
|
@ -998,6 +999,14 @@ void ApplicationOverlay::renderTexturedHemisphere() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ApplicationOverlay::resize() {
|
||||||
|
if (_framebufferObject != NULL) {
|
||||||
|
delete _framebufferObject;
|
||||||
|
_framebufferObject = NULL;
|
||||||
|
}
|
||||||
|
// _framebufferObject is recreated at the correct size the next time it is accessed via getFramebufferObject().
|
||||||
|
}
|
||||||
|
|
||||||
QOpenGLFramebufferObject* ApplicationOverlay::getFramebufferObject() {
|
QOpenGLFramebufferObject* ApplicationOverlay::getFramebufferObject() {
|
||||||
if (!_framebufferObject) {
|
if (!_framebufferObject) {
|
||||||
_framebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size());
|
_framebufferObject = new QOpenGLFramebufferObject(Application::getInstance()->getGLWidget()->size());
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov);
|
void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov);
|
||||||
void computeOculusPickRay(float x, float y, glm::vec3& direction) const;
|
void computeOculusPickRay(float x, float y, glm::vec3& direction) const;
|
||||||
void getClickLocation(int &x, int &y) const;
|
void getClickLocation(int &x, int &y) const;
|
||||||
|
void resize();
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
QOpenGLFramebufferObject* getFramebufferObject();
|
QOpenGLFramebufferObject* getFramebufferObject();
|
||||||
|
@ -68,7 +69,6 @@ private:
|
||||||
float _magSizeMult[NUMBER_OF_MAGNIFIERS];
|
float _magSizeMult[NUMBER_OF_MAGNIFIERS];
|
||||||
|
|
||||||
float _alpha;
|
float _alpha;
|
||||||
bool _active;
|
|
||||||
|
|
||||||
GLuint _crosshairTexture;
|
GLuint _crosshairTexture;
|
||||||
};
|
};
|
||||||
|
|
|
@ -665,6 +665,8 @@ void Stats::display(
|
||||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PerformanceTimer::tallyAllTimerRecords();
|
||||||
|
|
||||||
// TODO: the display of these timing details should all be moved to JavaScript
|
// TODO: the display of these timing details should all be moved to JavaScript
|
||||||
if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayTimingDetails)) {
|
if (_expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayTimingDetails)) {
|
||||||
// Timing details...
|
// Timing details...
|
||||||
|
|
|
@ -21,6 +21,8 @@
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <NodeList.h>
|
#include <NodeList.h>
|
||||||
|
|
||||||
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
#include "Application.h"
|
#include "Application.h"
|
||||||
#include "InterfaceConfig.h"
|
#include "InterfaceConfig.h"
|
||||||
#include "Menu.h"
|
#include "Menu.h"
|
||||||
|
@ -57,6 +59,8 @@ GLubyte identityIndicesRight[] = { 1, 2, 6, 1, 6, 5 };
|
||||||
GLubyte identityIndicesFront[] = { 0, 2, 1, 0, 3, 2 };
|
GLubyte identityIndicesFront[] = { 0, 2, 1, 0, 3, 2 };
|
||||||
GLubyte identityIndicesBack[] = { 4, 5, 6, 4, 6, 7 };
|
GLubyte identityIndicesBack[] = { 4, 5, 6, 4, 6, 7 };
|
||||||
|
|
||||||
|
static glm::vec3 grayColor = glm::vec3(0.3f, 0.3f, 0.3f);
|
||||||
|
|
||||||
VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree)
|
VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree)
|
||||||
: NodeData(),
|
: NodeData(),
|
||||||
_treeScale(treeScale),
|
_treeScale(treeScale),
|
||||||
|
@ -67,7 +71,10 @@ VoxelSystem::VoxelSystem(float treeScale, int maxVoxels, VoxelTree* tree)
|
||||||
_inOcclusions(false),
|
_inOcclusions(false),
|
||||||
_showCulledSharedFaces(false),
|
_showCulledSharedFaces(false),
|
||||||
_usePrimitiveRenderer(false),
|
_usePrimitiveRenderer(false),
|
||||||
_renderer(0)
|
_renderer(0),
|
||||||
|
_drawHaze(false),
|
||||||
|
_farHazeDistance(300.0f),
|
||||||
|
_hazeColor(grayColor)
|
||||||
{
|
{
|
||||||
|
|
||||||
_voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0;
|
_voxelsInReadArrays = _voxelsInWriteArrays = _voxelsUpdated = 0;
|
||||||
|
@ -373,6 +380,7 @@ void VoxelSystem::cleanupVoxelMemory() {
|
||||||
delete[] _readVoxelDirtyArray;
|
delete[] _readVoxelDirtyArray;
|
||||||
_writeVoxelDirtyArray = _readVoxelDirtyArray = NULL;
|
_writeVoxelDirtyArray = _readVoxelDirtyArray = NULL;
|
||||||
_readArraysLock.unlock();
|
_readArraysLock.unlock();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,6 +462,7 @@ void VoxelSystem::initVoxelMemory() {
|
||||||
|
|
||||||
_readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
|
_readVoxelShaderData = new VoxelShaderVBOData[_maxVoxels];
|
||||||
_memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels);
|
_memoryUsageRAM += (sizeof(VoxelShaderVBOData) * _maxVoxels);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Global Normals mode uses a technique of not including normals on any voxel vertices, and instead
|
// Global Normals mode uses a technique of not including normals on any voxel vertices, and instead
|
||||||
|
@ -521,13 +530,23 @@ void VoxelSystem::initVoxelMemory() {
|
||||||
_shadowDistancesLocation = _cascadedShadowMapProgram.uniformLocation("shadowDistances");
|
_shadowDistancesLocation = _cascadedShadowMapProgram.uniformLocation("shadowDistances");
|
||||||
_cascadedShadowMapProgram.release();
|
_cascadedShadowMapProgram.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
_renderer = new PrimitiveRenderer(_maxVoxels);
|
_renderer = new PrimitiveRenderer(_maxVoxels);
|
||||||
|
|
||||||
_initialized = true;
|
_initialized = true;
|
||||||
|
|
||||||
_writeArraysLock.unlock();
|
_writeArraysLock.unlock();
|
||||||
_readArraysLock.unlock();
|
_readArraysLock.unlock();
|
||||||
|
|
||||||
|
// fog for haze
|
||||||
|
if (_drawHaze) {
|
||||||
|
GLfloat fogColor[] = {_hazeColor.x, _hazeColor.y, _hazeColor.z, 1.0f};
|
||||||
|
glFogi(GL_FOG_MODE, GL_LINEAR);
|
||||||
|
glFogfv(GL_FOG_COLOR, fogColor);
|
||||||
|
glFogf(GL_FOG_START, 0.0f);
|
||||||
|
glFogf(GL_FOG_END, _farHazeDistance);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int VoxelSystem::parseData(const QByteArray& packet) {
|
int VoxelSystem::parseData(const QByteArray& packet) {
|
||||||
|
@ -1114,6 +1133,7 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo
|
||||||
node->setBufferIndex(nodeIndex);
|
node->setBufferIndex(nodeIndex);
|
||||||
node->setVoxelSystem(this);
|
node->setVoxelSystem(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// populate the array with points for the 8 vertices and RGB color for each added vertex
|
// populate the array with points for the 8 vertices and RGB color for each added vertex
|
||||||
updateArraysDetails(nodeIndex, startVertex, voxelScale, node->getColor());
|
updateArraysDetails(nodeIndex, startVertex, voxelScale, node->getColor());
|
||||||
}
|
}
|
||||||
|
@ -1131,11 +1151,13 @@ int VoxelSystem::updateNodeInArrays(VoxelTreeElement* node, bool reuseIndex, boo
|
||||||
|
|
||||||
void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex,
|
void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3& startVertex,
|
||||||
float voxelScale, const nodeColor& color) {
|
float voxelScale, const nodeColor& color) {
|
||||||
|
|
||||||
if (_initialized && nodeIndex <= _maxVoxels) {
|
if (_initialized && nodeIndex <= _maxVoxels) {
|
||||||
_writeVoxelDirtyArray[nodeIndex] = true;
|
_writeVoxelDirtyArray[nodeIndex] = true;
|
||||||
|
|
||||||
if (_useVoxelShader) {
|
if (_useVoxelShader) {
|
||||||
|
// write in position, scale, and color for the voxel
|
||||||
|
|
||||||
if (_writeVoxelShaderData) {
|
if (_writeVoxelShaderData) {
|
||||||
VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex];
|
VoxelShaderVBOData* writeVerticesAt = &_writeVoxelShaderData[nodeIndex];
|
||||||
writeVerticesAt->x = startVertex.x * TREE_SCALE;
|
writeVerticesAt->x = startVertex.x * TREE_SCALE;
|
||||||
|
@ -1157,6 +1179,7 @@ void VoxelSystem::updateArraysDetails(glBufferIndex nodeIndex, const glm::vec3&
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1407,6 +1430,10 @@ void VoxelSystem::render() {
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
if (!_usePrimitiveRenderer) {
|
if (!_usePrimitiveRenderer) {
|
||||||
|
if (_drawHaze) {
|
||||||
|
glEnable(GL_FOG);
|
||||||
|
}
|
||||||
|
|
||||||
PerformanceWarning warn(showWarnings, "render().. TRIANGLES...");
|
PerformanceWarning warn(showWarnings, "render().. TRIANGLES...");
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1478,6 +1505,10 @@ void VoxelSystem::render() {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_drawHaze) {
|
||||||
|
glDisable(GL_FOG);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
applyScaleAndBindProgram(texture);
|
applyScaleAndBindProgram(texture);
|
||||||
|
|
|
@ -273,7 +273,11 @@ private:
|
||||||
static unsigned short _sSwizzledOcclusionBits[64]; ///< Swizzle value of bit pairs of the value of index
|
static unsigned short _sSwizzledOcclusionBits[64]; ///< Swizzle value of bit pairs of the value of index
|
||||||
static unsigned char _sOctantIndexToBitMask[8]; ///< Map octant index to partition mask
|
static unsigned char _sOctantIndexToBitMask[8]; ///< Map octant index to partition mask
|
||||||
static unsigned char _sOctantIndexToSharedBitMask[8][8]; ///< Map octant indices to shared partition mask
|
static unsigned char _sOctantIndexToSharedBitMask[8][8]; ///< Map octant indices to shared partition mask
|
||||||
|
|
||||||
|
// haze
|
||||||
|
bool _drawHaze;
|
||||||
|
float _farHazeDistance;
|
||||||
|
glm::vec3 _hazeColor;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_VoxelSystem_h
|
#endif // hifi_VoxelSystem_h
|
||||||
|
|
|
@ -79,7 +79,7 @@ ReliableChannel* DatagramSequencer::getReliableInputChannel(int index) {
|
||||||
return channel;
|
return channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DatagramSequencer::startPacketGroup(int desiredPackets) {
|
int DatagramSequencer::notePacketGroup(int desiredPackets) {
|
||||||
// figure out how much data we have enqueued and increase the number of packets desired
|
// figure out how much data we have enqueued and increase the number of packets desired
|
||||||
int totalAvailable = 0;
|
int totalAvailable = 0;
|
||||||
foreach (ReliableChannel* channel, _reliableOutputChannels) {
|
foreach (ReliableChannel* channel, _reliableOutputChannels) {
|
||||||
|
|
|
@ -108,10 +108,10 @@ public:
|
||||||
/// Returns the intput channel at the specified index, creating it if necessary.
|
/// Returns the intput channel at the specified index, creating it if necessary.
|
||||||
ReliableChannel* getReliableInputChannel(int index = 0);
|
ReliableChannel* getReliableInputChannel(int index = 0);
|
||||||
|
|
||||||
/// Starts a packet group.
|
/// Notes that we're sending a group of packets.
|
||||||
/// \param desiredPackets the number of packets we'd like to write in the group
|
/// \param desiredPackets the number of packets we'd like to write in the group
|
||||||
/// \return the number of packets to write in the group
|
/// \return the number of packets to write in the group
|
||||||
int startPacketGroup(int desiredPackets = 1);
|
int notePacketGroup(int desiredPackets = 1);
|
||||||
|
|
||||||
/// Starts a new packet for transmission.
|
/// Starts a new packet for transmission.
|
||||||
/// \return a reference to the Bitstream to use for writing to the packet
|
/// \return a reference to the Bitstream to use for writing to the packet
|
||||||
|
|
|
@ -39,9 +39,12 @@ Endpoint::~Endpoint() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Endpoint::update() {
|
void Endpoint::update() {
|
||||||
Bitstream& out = _sequencer.startPacket();
|
int packetsToSend = _sequencer.notePacketGroup();
|
||||||
writeUpdateMessage(out);
|
for (int i = 0; i < packetsToSend; i++) {
|
||||||
_sequencer.endPacket();
|
Bitstream& out = _sequencer.startPacket();
|
||||||
|
writeUpdateMessage(out);
|
||||||
|
_sequencer.endPacket();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int Endpoint::parseData(const QByteArray& packet) {
|
int Endpoint::parseData(const QByteArray& packet) {
|
||||||
|
|
|
@ -87,7 +87,8 @@ void MetavoxelClientManager::updateClient(MetavoxelClient* client) {
|
||||||
MetavoxelClient::MetavoxelClient(const SharedNodePointer& node, MetavoxelClientManager* manager) :
|
MetavoxelClient::MetavoxelClient(const SharedNodePointer& node, MetavoxelClientManager* manager) :
|
||||||
Endpoint(node, new PacketRecord(), new PacketRecord()),
|
Endpoint(node, new PacketRecord(), new PacketRecord()),
|
||||||
_manager(manager),
|
_manager(manager),
|
||||||
_reliableDeltaChannel(NULL) {
|
_reliableDeltaChannel(NULL),
|
||||||
|
_reliableDeltaID(0) {
|
||||||
|
|
||||||
connect(_sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX),
|
connect(_sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX),
|
||||||
SIGNAL(receivedMessage(const QVariant&, Bitstream&)), SLOT(handleMessage(const QVariant&, Bitstream&)));
|
SIGNAL(receivedMessage(const QVariant&, Bitstream&)), SLOT(handleMessage(const QVariant&, Bitstream&)));
|
||||||
|
@ -139,10 +140,16 @@ void MetavoxelClient::handleMessage(const QVariant& message, Bitstream& in) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (userType == MetavoxelDeltaPendingMessage::Type) {
|
} else if (userType == MetavoxelDeltaPendingMessage::Type) {
|
||||||
if (!_reliableDeltaChannel) {
|
// check the id to make sure this is not a delta we've already processed
|
||||||
|
int id = message.value<MetavoxelDeltaPendingMessage>().id;
|
||||||
|
if (id > _reliableDeltaID) {
|
||||||
|
_reliableDeltaID = id;
|
||||||
_reliableDeltaChannel = _sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX);
|
_reliableDeltaChannel = _sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX);
|
||||||
_reliableDeltaChannel->getBitstream().copyPersistentMappings(_sequencer.getInputStream());
|
_reliableDeltaChannel->getBitstream().copyPersistentMappings(_sequencer.getInputStream());
|
||||||
_reliableDeltaLOD = getLastAcknowledgedSendRecord()->getLOD();
|
_reliableDeltaLOD = getLastAcknowledgedSendRecord()->getLOD();
|
||||||
|
PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord();
|
||||||
|
_remoteDataLOD = receiveRecord->getLOD();
|
||||||
|
_remoteData = receiveRecord->getData();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Endpoint::handleMessage(message, in);
|
Endpoint::handleMessage(message, in);
|
||||||
|
|
|
@ -74,6 +74,7 @@ private:
|
||||||
|
|
||||||
ReliableChannel* _reliableDeltaChannel;
|
ReliableChannel* _reliableDeltaChannel;
|
||||||
MetavoxelLOD _reliableDeltaLOD;
|
MetavoxelLOD _reliableDeltaLOD;
|
||||||
|
int _reliableDeltaID;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_MetavoxelClientManager_h
|
#endif // hifi_MetavoxelClientManager_h
|
||||||
|
|
|
@ -64,6 +64,10 @@ DECLARE_STREAMABLE_METATYPE(MetavoxelDeltaMessage)
|
||||||
/// A message indicating that metavoxel delta information is being sent on a reliable channel.
|
/// A message indicating that metavoxel delta information is being sent on a reliable channel.
|
||||||
class MetavoxelDeltaPendingMessage {
|
class MetavoxelDeltaPendingMessage {
|
||||||
STREAMABLE
|
STREAMABLE
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
STREAM int id;
|
||||||
};
|
};
|
||||||
|
|
||||||
DECLARE_STREAMABLE_METATYPE(MetavoxelDeltaPendingMessage)
|
DECLARE_STREAMABLE_METATYPE(MetavoxelDeltaPendingMessage)
|
||||||
|
|
|
@ -515,8 +515,6 @@ void ScriptEngine::run() {
|
||||||
|
|
||||||
qint64 now = usecTimestampNow();
|
qint64 now = usecTimestampNow();
|
||||||
float deltaTime = (float) (now - lastUpdate) / (float) USECS_PER_SECOND;
|
float deltaTime = (float) (now - lastUpdate) / (float) USECS_PER_SECOND;
|
||||||
emit update(deltaTime);
|
|
||||||
lastUpdate = now;
|
|
||||||
|
|
||||||
if (_engine.hasUncaughtException()) {
|
if (_engine.hasUncaughtException()) {
|
||||||
int line = _engine.uncaughtExceptionLineNumber();
|
int line = _engine.uncaughtExceptionLineNumber();
|
||||||
|
@ -524,6 +522,9 @@ void ScriptEngine::run() {
|
||||||
emit errorMessage("Uncaught exception at (" + _fileNameString + ") line" + QString::number(line) + ":" + _engine.uncaughtException().toString());
|
emit errorMessage("Uncaught exception at (" + _fileNameString + ") line" + QString::number(line) + ":" + _engine.uncaughtException().toString());
|
||||||
_engine.clearExceptions();
|
_engine.clearExceptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emit update(deltaTime);
|
||||||
|
lastUpdate = now;
|
||||||
}
|
}
|
||||||
emit scriptEnding();
|
emit scriptEnding();
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,12 @@
|
||||||
|
|
||||||
#include "PerfStat.h"
|
#include "PerfStat.h"
|
||||||
|
|
||||||
|
#include "SharedUtil.h"
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// PerformanceWarning
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
// Static class members initialization here!
|
// Static class members initialization here!
|
||||||
bool PerformanceWarning::_suppressShortTimings = false;
|
bool PerformanceWarning::_suppressShortTimings = false;
|
||||||
|
|
||||||
|
@ -52,14 +58,50 @@ PerformanceWarning::~PerformanceWarning() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// PerformanceTimerRecord
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
const quint64 STALE_STAT_PERIOD = 4 * USECS_PER_SECOND;
|
||||||
|
|
||||||
|
void PerformanceTimerRecord::tallyResult(const quint64& now) {
|
||||||
|
if (_numAccumulations > 0) {
|
||||||
|
_numTallies++;
|
||||||
|
_movingAverage.updateAverage(_runningTotal - _lastTotal);
|
||||||
|
_lastTotal = _runningTotal;
|
||||||
|
_numAccumulations = 0;
|
||||||
|
_expiry = now + STALE_STAT_PERIOD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// PerformanceTimer
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
QString PerformanceTimer::_fullName;
|
||||||
QMap<QString, PerformanceTimerRecord> PerformanceTimer::_records;
|
QMap<QString, PerformanceTimerRecord> PerformanceTimer::_records;
|
||||||
|
|
||||||
|
|
||||||
PerformanceTimer::~PerformanceTimer() {
|
PerformanceTimer::~PerformanceTimer() {
|
||||||
quint64 end = usecTimestampNow();
|
quint64 elapsedusec = (usecTimestampNow() - _start);
|
||||||
quint64 elapsedusec = (end - _start);
|
PerformanceTimerRecord& namedRecord = _records[_fullName];
|
||||||
PerformanceTimerRecord& namedRecord = _records[_name];
|
namedRecord.accumulateResult(elapsedusec);
|
||||||
namedRecord.recordResult(elapsedusec);
|
_fullName.resize(_fullName.size() - (_name.size() + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
void PerformanceTimer::tallyAllTimerRecords() {
|
||||||
|
QMap<QString, PerformanceTimerRecord>::iterator recordsItr = _records.begin();
|
||||||
|
QMap<QString, PerformanceTimerRecord>::const_iterator recordsEnd = _records.end();
|
||||||
|
quint64 now = usecTimestampNow();
|
||||||
|
while (recordsItr != recordsEnd) {
|
||||||
|
recordsItr.value().tallyResult(now);
|
||||||
|
if (recordsItr.value().isStale(now)) {
|
||||||
|
// purge stale records
|
||||||
|
recordsItr = _records.erase(recordsItr);
|
||||||
|
} else {
|
||||||
|
++recordsItr;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceTimer::dumpAllTimerRecords() {
|
void PerformanceTimer::dumpAllTimerRecords() {
|
||||||
|
|
|
@ -25,13 +25,13 @@
|
||||||
|
|
||||||
class PerformanceWarning {
|
class PerformanceWarning {
|
||||||
private:
|
private:
|
||||||
quint64 _start;
|
quint64 _start;
|
||||||
const char* _message;
|
const char* _message;
|
||||||
bool _renderWarningsOn;
|
bool _renderWarningsOn;
|
||||||
bool _alwaysDisplay;
|
bool _alwaysDisplay;
|
||||||
quint64* _runningTotal;
|
quint64* _runningTotal;
|
||||||
quint64* _totalCalls;
|
quint64* _totalCalls;
|
||||||
static bool _suppressShortTimings;
|
static bool _suppressShortTimings;
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PerformanceWarning(bool renderWarnings, const char* message, bool alwaysDisplay = false,
|
PerformanceWarning(bool renderWarnings, const char* message, bool alwaysDisplay = false,
|
||||||
|
@ -52,38 +52,47 @@ public:
|
||||||
|
|
||||||
class PerformanceTimerRecord {
|
class PerformanceTimerRecord {
|
||||||
public:
|
public:
|
||||||
PerformanceTimerRecord() : _runningTotal(0), _totalCalls(0) {}
|
PerformanceTimerRecord() : _runningTotal(0), _lastTotal(0), _numAccumulations(0), _numTallies(0), _expiry(0) {}
|
||||||
|
|
||||||
void recordResult(quint64 elapsed) { _runningTotal += elapsed; _totalCalls++; _movingAverage.updateAverage(elapsed); }
|
void accumulateResult(const quint64& elapsed) { _runningTotal += elapsed; ++_numAccumulations; }
|
||||||
quint64 getAverage() const { return (_totalCalls == 0) ? 0 : _runningTotal / _totalCalls; }
|
void tallyResult(const quint64& now);
|
||||||
quint64 getMovingAverage() const { return (_totalCalls == 0) ? 0 : _movingAverage.getAverage(); }
|
bool isStale(const quint64& now) const { return now > _expiry; }
|
||||||
quint64 getCount() const { return _totalCalls; }
|
quint64 getAverage() const { return (_numTallies == 0) ? 0 : _runningTotal / _numTallies; }
|
||||||
|
quint64 getMovingAverage() const { return (_numTallies == 0) ? 0 : _movingAverage.getAverage(); }
|
||||||
|
quint64 getCount() const { return _numTallies; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
quint64 _runningTotal;
|
quint64 _runningTotal;
|
||||||
quint64 _totalCalls;
|
quint64 _lastTotal;
|
||||||
SimpleMovingAverage _movingAverage;
|
quint64 _numAccumulations;
|
||||||
|
quint64 _numTallies;
|
||||||
|
quint64 _expiry;
|
||||||
|
SimpleMovingAverage _movingAverage;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PerformanceTimer {
|
class PerformanceTimer {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PerformanceTimer(const QString& name) :
|
PerformanceTimer(const QString& name) :
|
||||||
_start(usecTimestampNow()),
|
_start(0),
|
||||||
_name(name) { }
|
_name(name) {
|
||||||
|
_fullName.append("/");
|
||||||
|
_fullName.append(_name);
|
||||||
|
_start = usecTimestampNow();
|
||||||
|
}
|
||||||
|
|
||||||
quint64 elapsed() const { return (usecTimestampNow() - _start); };
|
|
||||||
|
|
||||||
~PerformanceTimer();
|
~PerformanceTimer();
|
||||||
|
|
||||||
static const PerformanceTimerRecord& getTimerRecord(const QString& name) { return _records[name]; };
|
static const PerformanceTimerRecord& getTimerRecord(const QString& name) { return _records[name]; };
|
||||||
static const QMap<QString, PerformanceTimerRecord>& getAllTimerRecords() { return _records; };
|
static const QMap<QString, PerformanceTimerRecord>& getAllTimerRecords() { return _records; };
|
||||||
|
static void tallyAllTimerRecords();
|
||||||
static void dumpAllTimerRecords();
|
static void dumpAllTimerRecords();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
quint64 _start;
|
quint64 _start;
|
||||||
QString _name;
|
QString _name;
|
||||||
static QMap<QString, PerformanceTimerRecord> _records;
|
static QString _fullName;
|
||||||
|
static QMap<QString, PerformanceTimerRecord> _records;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -14,8 +14,8 @@
|
||||||
|
|
||||||
SimpleMovingAverage::SimpleMovingAverage(int numSamplesToAverage) :
|
SimpleMovingAverage::SimpleMovingAverage(int numSamplesToAverage) :
|
||||||
_numSamples(0),
|
_numSamples(0),
|
||||||
_average(0),
|
_average(0.0f),
|
||||||
_eventDeltaAverage(0),
|
_eventDeltaAverage(0.0f),
|
||||||
WEIGHTING(1.0f / numSamplesToAverage),
|
WEIGHTING(1.0f / numSamplesToAverage),
|
||||||
ONE_MINUS_WEIGHTING(1 - WEIGHTING) {
|
ONE_MINUS_WEIGHTING(1 - WEIGHTING) {
|
||||||
|
|
||||||
|
@ -45,8 +45,8 @@ int SimpleMovingAverage::updateAverage(float sample) {
|
||||||
|
|
||||||
void SimpleMovingAverage::reset() {
|
void SimpleMovingAverage::reset() {
|
||||||
_numSamples = 0;
|
_numSamples = 0;
|
||||||
_average = 0;
|
_average = 0.0f;
|
||||||
_eventDeltaAverage = 0;
|
_eventDeltaAverage = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
float SimpleMovingAverage::getEventDeltaAverage() const {
|
float SimpleMovingAverage::getEventDeltaAverage() const {
|
||||||
|
@ -55,5 +55,5 @@ float SimpleMovingAverage::getEventDeltaAverage() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
float SimpleMovingAverage::getAverageSampleValuePerSecond() const {
|
float SimpleMovingAverage::getAverageSampleValuePerSecond() const {
|
||||||
return _average * (1 / getEventDeltaAverage());
|
return _average * (1.0f / getEventDeltaAverage());
|
||||||
}
|
}
|
||||||
|
|
|
@ -647,7 +647,8 @@ TestEndpoint::TestEndpoint(Mode mode) :
|
||||||
_mode(mode),
|
_mode(mode),
|
||||||
_highPriorityMessagesToSend(0.0f),
|
_highPriorityMessagesToSend(0.0f),
|
||||||
_reliableMessagesToSend(0.0f),
|
_reliableMessagesToSend(0.0f),
|
||||||
_reliableDeltaChannel(NULL) {
|
_reliableDeltaChannel(NULL),
|
||||||
|
_reliableDeltaID(0) {
|
||||||
|
|
||||||
connect(&_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)),
|
connect(&_sequencer, SIGNAL(receivedHighPriorityMessage(const QVariant&)),
|
||||||
SLOT(handleHighPriorityMessage(const QVariant&)));
|
SLOT(handleHighPriorityMessage(const QVariant&)));
|
||||||
|
@ -858,7 +859,7 @@ bool TestEndpoint::simulate(int iterationNumber) {
|
||||||
bytesReceived += datagram.size();
|
bytesReceived += datagram.size();
|
||||||
_remainingPipelineCapacity += datagram.size();
|
_remainingPipelineCapacity += datagram.size();
|
||||||
}
|
}
|
||||||
int packetCount = _sequencer.startPacketGroup();
|
int packetCount = _sequencer.notePacketGroup();
|
||||||
groupsSent++;
|
groupsSent++;
|
||||||
maxPacketsPerGroup = qMax(maxPacketsPerGroup, packetCount);
|
maxPacketsPerGroup = qMax(maxPacketsPerGroup, packetCount);
|
||||||
for (int i = 0; i < packetCount; i++) {
|
for (int i = 0; i < packetCount; i++) {
|
||||||
|
@ -908,7 +909,8 @@ bool TestEndpoint::simulate(int iterationNumber) {
|
||||||
// if we're sending a reliable delta, wait until it's acknowledged
|
// if we're sending a reliable delta, wait until it's acknowledged
|
||||||
if (_reliableDeltaChannel) {
|
if (_reliableDeltaChannel) {
|
||||||
Bitstream& out = _sequencer.startPacket();
|
Bitstream& out = _sequencer.startPacket();
|
||||||
out << QVariant::fromValue(MetavoxelDeltaPendingMessage());
|
MetavoxelDeltaPendingMessage msg = { _reliableDeltaID };
|
||||||
|
out << QVariant::fromValue(msg);
|
||||||
_sequencer.endPacket();
|
_sequencer.endPacket();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -932,7 +934,8 @@ bool TestEndpoint::simulate(int iterationNumber) {
|
||||||
_reliableDeltaLOD = _lod;
|
_reliableDeltaLOD = _lod;
|
||||||
|
|
||||||
_sequencer.getOutputStream().getUnderlying().device()->seek(start);
|
_sequencer.getOutputStream().getUnderlying().device()->seek(start);
|
||||||
out << QVariant::fromValue(MetavoxelDeltaPendingMessage());
|
MetavoxelDeltaPendingMessage msg = { ++_reliableDeltaID };
|
||||||
|
out << QVariant::fromValue(msg);
|
||||||
_sequencer.endPacket();
|
_sequencer.endPacket();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -1081,15 +1084,22 @@ void TestEndpoint::handleMessage(const QVariant& message, Bitstream& in) {
|
||||||
|
|
||||||
} else if (userType == MetavoxelDeltaMessage::Type) {
|
} else if (userType == MetavoxelDeltaMessage::Type) {
|
||||||
PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord();
|
PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord();
|
||||||
_data.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in,
|
_remoteData.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in,
|
||||||
_dataLOD = getLastAcknowledgedSendRecord()->getLOD());
|
_remoteDataLOD = getLastAcknowledgedSendRecord()->getLOD());
|
||||||
|
in.reset();
|
||||||
|
_data = _remoteData;
|
||||||
compareMetavoxelData();
|
compareMetavoxelData();
|
||||||
|
|
||||||
} else if (userType == MetavoxelDeltaPendingMessage::Type) {
|
} else if (userType == MetavoxelDeltaPendingMessage::Type) {
|
||||||
if (!_reliableDeltaChannel) {
|
int id = message.value<MetavoxelDeltaPendingMessage>().id;
|
||||||
|
if (id > _reliableDeltaID) {
|
||||||
|
_reliableDeltaID = id;
|
||||||
_reliableDeltaChannel = _sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX);
|
_reliableDeltaChannel = _sequencer.getReliableInputChannel(RELIABLE_DELTA_CHANNEL_INDEX);
|
||||||
_reliableDeltaChannel->getBitstream().copyPersistentMappings(_sequencer.getInputStream());
|
_reliableDeltaChannel->getBitstream().copyPersistentMappings(_sequencer.getInputStream());
|
||||||
_reliableDeltaLOD = getLastAcknowledgedSendRecord()->getLOD();
|
_reliableDeltaLOD = getLastAcknowledgedSendRecord()->getLOD();
|
||||||
|
PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord();
|
||||||
|
_remoteDataLOD = receiveRecord->getLOD();
|
||||||
|
_remoteData = receiveRecord->getData();
|
||||||
}
|
}
|
||||||
} else if (userType == QMetaType::QVariantList) {
|
} else if (userType == QMetaType::QVariantList) {
|
||||||
foreach (const QVariant& element, message.toList()) {
|
foreach (const QVariant& element, message.toList()) {
|
||||||
|
@ -1107,7 +1117,7 @@ PacketRecord* TestEndpoint::maybeCreateSendRecord() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
PacketRecord* TestEndpoint::maybeCreateReceiveRecord() const {
|
PacketRecord* TestEndpoint::maybeCreateReceiveRecord() const {
|
||||||
return new TestReceiveRecord(_dataLOD, (_mode == METAVOXEL_SERVER_MODE) ? MetavoxelData() : _data, _remoteState);
|
return new TestReceiveRecord(_remoteDataLOD, _remoteData, _remoteState);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestEndpoint::handleHighPriorityMessage(const QVariant& message) {
|
void TestEndpoint::handleHighPriorityMessage(const QVariant& message) {
|
||||||
|
@ -1127,9 +1137,10 @@ void TestEndpoint::handleHighPriorityMessage(const QVariant& message) {
|
||||||
void TestEndpoint::handleReliableMessage(const QVariant& message, Bitstream& in) {
|
void TestEndpoint::handleReliableMessage(const QVariant& message, Bitstream& in) {
|
||||||
if (message.userType() == MetavoxelDeltaMessage::Type) {
|
if (message.userType() == MetavoxelDeltaMessage::Type) {
|
||||||
PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord();
|
PacketRecord* receiveRecord = getLastAcknowledgedReceiveRecord();
|
||||||
_data.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in, _dataLOD = _reliableDeltaLOD);
|
_remoteData.readDelta(receiveRecord->getData(), receiveRecord->getLOD(), in, _remoteDataLOD = _reliableDeltaLOD);
|
||||||
_sequencer.getInputStream().persistReadMappings(in.getAndResetReadMappings());
|
_sequencer.getInputStream().persistReadMappings(in.getAndResetReadMappings());
|
||||||
in.clearPersistentMappings();
|
in.clearPersistentMappings();
|
||||||
|
_data = _remoteData;
|
||||||
compareMetavoxelData();
|
compareMetavoxelData();
|
||||||
_reliableDeltaChannel = NULL;
|
_reliableDeltaChannel = NULL;
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -79,6 +79,8 @@ private:
|
||||||
|
|
||||||
MetavoxelData _data;
|
MetavoxelData _data;
|
||||||
MetavoxelLOD _dataLOD;
|
MetavoxelLOD _dataLOD;
|
||||||
|
MetavoxelData _remoteData;
|
||||||
|
MetavoxelLOD _remoteDataLOD;
|
||||||
MetavoxelLOD _lod;
|
MetavoxelLOD _lod;
|
||||||
|
|
||||||
SharedObjectPointer _sphere;
|
SharedObjectPointer _sphere;
|
||||||
|
@ -104,6 +106,7 @@ private:
|
||||||
MetavoxelData _reliableDeltaData;
|
MetavoxelData _reliableDeltaData;
|
||||||
MetavoxelLOD _reliableDeltaLOD;
|
MetavoxelLOD _reliableDeltaLOD;
|
||||||
Bitstream::WriteMappings _reliableDeltaWriteMappings;
|
Bitstream::WriteMappings _reliableDeltaWriteMappings;
|
||||||
|
int _reliableDeltaID;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A simple shared object.
|
/// A simple shared object.
|
||||||
|
|
Loading…
Reference in a new issue