Merge pull request #6655 from samcake/graphicsMaster

Graphics: merge upstream master to upstream graphics
This commit is contained in:
Clément Brisset 2015-12-14 18:07:31 -08:00
commit a37c28871e
130 changed files with 1917 additions and 763 deletions

View file

@ -1,5 +1,7 @@
Please read the [general build guide](BUILD.md) for information on dependencies required for all platforms. Only Windows specific instructions are found in this file.
Interface can be built as 32 or 64 bit.
###Visual Studio 2013
You can use the Community or Professional editions of Visual Studio 2013.
@ -25,25 +27,26 @@ We expect nmake.exe to be located at the following path.
###Qt
You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version.
NOTE: Qt does not support 64-bit builds on Windows 7, so you must use the 32-bit version of libraries for interface.exe to run. The 32-bit version of the static library is the one linked by our CMake find modules.
* [Download the online installer](http://qt-project.org/downloads)
* When it asks you to select components, ONLY select the following:
* When it asks you to select components, ONLY select one of the following, 32- or 64-bit to match your build preference:
* Qt > Qt 5.5.1 > **msvc2013 32-bit**
* Qt > Qt 5.5.1 > **msvc2013 64-bit**
* [Download the offline installer](http://download.qt.io/official_releases/qt/5.5/5.5.1/qt-opensource-windows-x86-msvc2013-5.5.1.exe)
* Download the offline installer, 32- or 64-bit to match your build preference:
* [32-bit](http://download.qt.io/official_releases/qt/5.5/5.5.1/qt-opensource-windows-x86-msvc2013-5.5.1.exe)
* [64-bit](http://download.qt.io/official_releases/qt/5.5/5.5.1/qt-opensource-windows-x86-msvc2013_64-5.5.1.exe)
Once Qt is installed, you need to manually configure the following:
* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.5.1\msvc2013\lib\cmake` directory.
* Set the QT_CMAKE_PREFIX_PATH environment variable to your `Qt\5.5.1\msvc2013\lib\cmake` or `Qt\5.5.1\msvc2013_64\lib\cmake` directory.
* You can set an environment variable from Control Panel > System > Advanced System Settings > Environment Variables > New
###External Libraries
As it stands, Hifi/Interface is a 32-bit application, so all libraries should also be 32-bit.
All libraries should be 32- or 64-bit to match your build preference.
CMake will need to know where the headers and libraries for required external dependencies are.
We use CMake's `fixup_bundle` to find the DLLs all of our exectuable targets require, and then copy them beside the executable in a post-build step. If `fixup_bundle` is having problems finding a DLL, you can fix it manually on your end by adding the folder containing that DLL to your path. Let us know which DLL CMake had trouble finding, as it is possible a tweak to our CMake files is required.
We use CMake's `fixup_bundle` to find the DLLs all of our executable targets require, and then copy them beside the executable in a post-build step. If `fixup_bundle` is having problems finding a DLL, you can fix it manually on your end by adding the folder containing that DLL to your path. Let us know which DLL CMake had trouble finding, as it is possible a tweak to our CMake files is required.
The recommended route for CMake to find the external dependencies is to place all of the dependencies in one folder and set one ENV variable - HIFI_LIB_DIR. That ENV variable should point to a directory with the following structure:
@ -69,17 +72,23 @@ Your system may already have several versions of the OpenSSL DLL's (ssleay32.dll
QSslSocket: cannot resolve SSL_CTX_set_next_proto_select_cb
QSslSocket: cannot resolve SSL_get0_next_proto_negotiated
To prevent these problems, install OpenSSL yourself. Download the following binary packages [from this website](http://slproweb.com/products/Win32OpenSSL.html):
* Visual C++ 2008 Redistributables
* Win32 OpenSSL v1.0.1p
To prevent these problems, install OpenSSL yourself. Download one of the following binary packages [from this website](http://slproweb.com/products/Win32OpenSSL.html):
* Win32 OpenSSL v1.0.1q
* Win64 OpenSSL v1.0.1q
Install OpenSSL into the Windows system directory, to make sure that Qt uses the version that you've just installed, and not some other version.
###Build High Fidelity using Visual Studio
Follow the same build steps from the CMake section of [BUILD.md](BUILD.md), but pass a different generator to CMake.
For 32-bit builds:
cmake .. -G "Visual Studio 12"
For 64-bit builds:
cmake .. -G "Visual Studio 12 Win64"
Open %HIFI_DIR%\build\hifi.sln and compile.
###Running Interface

View file

@ -36,7 +36,12 @@ if (WIN32)
if (MSVC10)
set(WINDOW_SDK_PATH "C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1 ")
elseif (MSVC12)
set(WINDOW_SDK_PATH "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\x86 ")
if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(WINDOW_SDK_FOLDER "x64")
else()
set(WINDOW_SDK_FOLDER "x86")
endif()
set(WINDOW_SDK_PATH "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\${WINDOW_SDK_FOLDER}")
endif ()
message (WINDOW_SDK_PATH= ${WINDOW_SDK_PATH})
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${WINDOW_SDK_PATH})

View file

@ -37,6 +37,7 @@
#include <EntityScriptingInterface.h> // TODO: consider moving to scriptengine.h
#include "avatars/ScriptableAvatar.h"
#include "entities/AssignmentParentFinder.h"
#include "RecordingScriptingInterface.h"
#include "AbstractAudioInterface.h"
@ -62,6 +63,8 @@ Agent::Agent(ReceivedMessage& message) :
connect(assetThread, &QThread::started, assetClient.data(), &AssetClient::init);
assetThread->start();
DependencyManager::registerInheritance<SpatialParentFinder, AssignmentParentFinder>();
DependencyManager::set<ResourceCacheSharedItems>();
DependencyManager::set<SoundCache>();
DependencyManager::set<AudioInjectorManager>();
@ -284,6 +287,8 @@ void Agent::executeScript() {
entityScriptingInterface->setEntityTree(_entityViewer.getTree());
DependencyManager::set<AssignmentParentFinder>(_entityViewer.getTree());
// wire up our additional agent related processing to the update signal
QObject::connect(_scriptEngine.get(), &ScriptEngine::update, this, &Agent::processAgentAvatarAndAudio);
@ -384,7 +389,7 @@ void Agent::processAgentAvatarAndAudio(float deltaTime) {
int numAvailableBytes = (soundByteArray.size() - _numAvatarSoundSentBytes) > SCRIPT_AUDIO_BUFFER_BYTES
? SCRIPT_AUDIO_BUFFER_BYTES
: soundByteArray.size() - _numAvatarSoundSentBytes;
numAvailableSamples = numAvailableBytes / sizeof(int16_t);
numAvailableSamples = (int16_t)numAvailableBytes / sizeof(int16_t);
// check if the all of the _numAvatarAudioBufferSamples to be sent are silence

View file

@ -171,7 +171,7 @@ void AudioMixerClientData::sendAudioStreamStatsPackets(const SharedNodePointer&
statsPacket->writePrimitive(appendFlag);
appendFlag = 1;
int numStreamStatsRoomFor = (statsPacket->size() - sizeof(quint8) - sizeof(quint16)) / sizeof(AudioStreamStats);
int numStreamStatsRoomFor = (int)(statsPacket->size() - sizeof(quint8) - sizeof(quint16)) / sizeof(AudioStreamStats);
// calculate and pack the number of stream stats to follow
quint16 numStreamStatsToPack = std::min(numStreamStatsRemaining, numStreamStatsRoomFor);

View file

@ -293,7 +293,7 @@ int OctreeInboundPacketProcessor::sendNackPackets() {
qDebug() << "NACK Sent back to editor/client... destinationNode=" << nodeUUID;
packetsSent += nackPacketList->getNumPackets();
packetsSent += (int)nackPacketList->getNumPackets();
// send the list of nack packets
totalBytesSent += nodeList->sendPacketList(std::move(nackPacketList), *destinationNode);

View file

@ -225,6 +225,8 @@ bool OctreeQueryNode::updateCurrentViewFrustum() {
newestViewFrustum.setPosition(getCameraPosition());
newestViewFrustum.setOrientation(getCameraOrientation());
newestViewFrustum.setKeyholeRadius(getKeyholeRadius());
// Also make sure it's got the correct lens details from the camera
float originalFOV = getCameraFov();
float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND;

View file

@ -4,7 +4,7 @@ if (WIN32)
set(PLATFORM_CMAKE_ARGS "-DUSE_MSVC_RUNTIME_LIBRARY_DLL=1")
else ()
set(PLATFORM_CMAKE_ARGS "-DBUILD_SHARED_LIBS=1")
if (ANDROID)
list(APPEND PLATFORM_CMAKE_ARGS "-DCMAKE_TOOLCHAIN_FILE=${CMAKE_TOOLCHAIN_FILE}" "-DANDROID_NATIVE_API_LEVEL=19")
elseif (APPLE)
@ -14,30 +14,28 @@ endif ()
include(ExternalProject)
if (WIN32)
if (WIN32)
ExternalProject_Add(
${EXTERNAL_NAME}
# URL https://bullet.googlecode.com/files/bullet-2.82-r2704.zip
URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.82-ccd-fix.zip
URL_MD5 d95b07eb120de7dd7786361c0b5a8d9f
CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0 -DUSE_DX11=0
URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.83-ccd-and-cmake-fixes.tgz
URL_MD5 03051bf112dcc78ddd296f9cab38fd68
CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0 -DUSE_DX11=0
LOG_DOWNLOAD 1
LOG_CONFIGURE 1
LOG_BUILD 1
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
)
)
else ()
ExternalProject_Add(
${EXTERNAL_NAME}
#URL http://bullet.googlecode.com/files/bullet-2.82-r2704.tgz
URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.82-ccd-fix.tgz
URL_MD5 fb140a4983b4109aa1c825a162aa8d64
CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_DEMOS=0 -DUSE_GLUT=0
URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.83-ccd-and-cmake-fixes.tgz
URL_MD5 03051bf112dcc78ddd296f9cab38fd68
CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR> -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0
LOG_DOWNLOAD 1
LOG_CONFIGURE 1
LOG_BUILD 1
BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build
)
)
endif ()
# Hide this external target (for ide users)
@ -55,7 +53,7 @@ if (APPLE OR UNIX OR ANDROID)
else ()
set(BULLET_LIB_EXT "so")
endif ()
set(LIB_PREFIX "lib")
elseif (WIN32)
set(BULLET_LIB_EXT "lib")
@ -63,13 +61,13 @@ endif ()
if (DEFINED BULLET_LIB_EXT)
set(_BULLET_LIB_PAIRS "DYNAMICS_LIBRARY\;BulletDynamics" "COLLISION_LIBRARY\;BulletCollision" "MATH_LIBRARY\;LinearMath" "SOFTBODY_LIBRARY\;BulletSoftBody")
foreach(_LIB_PAIR ${_BULLET_LIB_PAIRS})
list(GET _LIB_PAIR 0 _LIB_VAR_NAME)
list(GET _LIB_PAIR 1 _LIB_NAME)
set(${EXTERNAL_NAME_UPPER}_${_LIB_VAR_NAME}_RELEASE ${BULLET_LIB_DIR}/${LIB_PREFIX}${_LIB_NAME}.${BULLET_LIB_EXT} CACHE FILEPATH "${_LIB_NAME} release library location")
if (WIN32)
set(${EXTERNAL_NAME_UPPER}_${_LIB_VAR_NAME}_DEBUG ${BULLET_LIB_DIR}/${LIB_PREFIX}${_LIB_NAME}_Debug.${BULLET_LIB_EXT} CACHE FILEPATH "${_LIB_NAME} debug library location")
else ()

View file

@ -8,14 +8,14 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
#set(SIXENSE_URL_MD5 "10cc8dc470d2ac1244a88cf04bc549cc")
#set(SIXENSE_NEW_LAYOUT 0)
#set(SIXENSE_URL "http://public.s3.amazonaws.com/dependencies/SixenseSDK_071615.zip")
#set(SIXENSE_URL_MD5 "752a3901f334124e9cffc2ba4136ef7d")
#set(SIXENSE_NEW_LAYOUT 1)
set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_102215.zip")
set(SIXENSE_URL_MD5 "93c3a6795cce777a0f472b09532935f1")
set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_071615.zip")
set(SIXENSE_URL_MD5 "752a3901f334124e9cffc2ba4136ef7d")
set(SIXENSE_NEW_LAYOUT 1)
#set(SIXENSE_URL "http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_102215.zip")
#set(SIXENSE_URL_MD5 "93c3a6795cce777a0f472b09532935f1")
#set(SIXENSE_NEW_LAYOUT 1)
ExternalProject_Add(
${EXTERNAL_NAME}
URL ${SIXENSE_URL}

View file

@ -15,4 +15,4 @@ macro(TARGET_BULLET)
target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS})
endif()
target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES})
endmacro()
endmacro()

View file

@ -88,4 +88,4 @@ find_package_handle_standard_args(Bullet "Could NOT find Bullet, try to set the
BULLET_INCLUDE_DIRS
BULLET_DYNAMICS_LIBRARY BULLET_COLLISION_LIBRARY BULLET_MATH_LIBRARY BULLET_SOFTBODY_LIBRARY
BULLET_LIBRARIES
)
)

View file

@ -14,7 +14,6 @@
// Goes into "paused" when the '.' key (and automatically when started in HMD), and normal when pressing any key.
// See MAIN CONTROL, below, for what "paused" actually does.
var IK_WINDOW_AFTER_GOING_ACTIVE = 3000; // milliseconds
var OVERLAY_DATA = {
text: "Paused:\npress any key to continue",
font: {size: 75},
@ -31,7 +30,6 @@ function playAwayAnimation() {
return {isAway: true, isNotAway: false, isNotMoving: false, ikOverlayAlpha: 0.0};
}
if (stopper) {
Script.clearTimeout(stopper);
stopper = false;
MyAvatar.removeAnimationStateHandler(activeAnimationHandlerId); // do it now, before making new assignment
}
@ -47,15 +45,14 @@ function stopAwayAnimation() {
// It cannot be as soon as we want to stop the away animation, because then things will look goofy as we come out of that animation.
// (Imagine an away animation that sits or kneels, and then stands back up when coming out of it. If head is at the HMD, then it won't
// want to track the standing up animation.)
// Our standard anim graph flips 'awayOutroOnDone' for one frame, but it's a trigger (not an animVar) and other folks might use different graphs.
// So... Just give us a fixed amount of time to be done with animation, before we turn ik back on.
// The anim graph will trigger awayOutroOnDone when awayOutro is finished.
var backToNormal = false;
stopper = Script.setTimeout(function () {
backToNormal = true;
stopper = false;
}, IK_WINDOW_AFTER_GOING_ACTIVE);
stopper = true;
function animateActive(state) {
if (state.ikOverlayAlpha) {
if (state.awayOutroOnDone) {
backToNormal = true;
stopper = false;
} else if (state.ikOverlayAlpha) {
// Once the right state gets reflected back to us, we don't need the hander any more.
// But we are locked against handler changes during the execution of a handler, so remove asynchronously.
Script.setTimeout(function () { MyAvatar.removeAnimationStateHandler(activeAnimationHandlerId); }, 0);
@ -63,7 +60,7 @@ function stopAwayAnimation() {
// It might be cool to "come back to life" by fading the ik overlay back in over a short time. But let's see how this goes.
return {isAway: false, isNotAway: true, ikOverlayAlpha: backToNormal ? 1.0 : 0.0}; // IWBNI we had a way of deleting an anim var.
}
activeAnimationHandlerId = MyAvatar.addAnimationStateHandler(animateActive, ['isAway', 'isNotAway', 'isNotMoving', 'ikOverlayAlpha']);
activeAnimationHandlerId = MyAvatar.addAnimationStateHandler(animateActive, ['ikOverlayAlpha', 'awayOutroOnDone']);
}
// OVERLAY

View file

@ -0,0 +1,55 @@
//
// createAvatarDetector.js
//
// Created by James B. Pollack @imgntn on 12/7/2015
// Copyright 2015 High Fidelity, Inc.
//
// Run this script if you want the rats to run away from you.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
var avatarDetector = null;
function createAvatarDetector() {
var detectorProperties = {
name: 'Hifi-Avatar-Detector',
type: 'Box',
position: MyAvatar.position,
dimensions: {
x: 1,
y: 2,
z: 1
},
collisionsWillMove: false,
ignoreForCollisions: true,
visible: false,
color: {
red: 255,
green: 0,
blue: 0
}
}
avatarDetector = Entities.addEntity(detectorProperties);
};
var updateAvatarDetector = function() {
// print('updating detector position' + JSON.stringify(MyAvatar.position))
Entities.editEntity(avatarDetector, {
position: MyAvatar.position
});
};
var cleanup = function() {
Script.update.disconnect(updateAvatarDetector);
Entities.deleteEntity(avatarDetector);
}
createAvatarDetector();
Script.scriptEnding.connect(cleanup);
Script.update.connect(updateAvatarDetector);

View file

@ -0,0 +1,471 @@
//
// ratCreator.js
//
// Created by James B. Pollack @imgntn on 12/7/2015
// Copyright 2015 High Fidelity, Inc.
//
// This script spawns some rats that have simple steering behaviors applied to them.
// Run it in the 'drylake' environment, or adjust all object locations to match your scene.
//
// Steering bevhaviors from ratSteer.js:
// The rats will move from a spawning point toward their nest.
// They will avoid avoider blocks moving across the alley
// They will avoid avatars running createAvatarDetector.js
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
Script.include('ratSteer.js');
var steer = loadSteer();
Script.include('../libraries/tween.js');
var TWEEN = loadTween();
var USE_CONSTANT_SPAWNER = true;
var RAT_SPAWNER_LOCATION = {
x: 1000.5,
y: 98,
z: 1040
};
var RAT_NEST_LOCATION = {
x: 1003.5,
y: 99,
z: 964.2
};
var RAT_DIMENSIONS = {
x: 0.22,
y: 0.32,
z: 1.14
};
var RAT_MODEL_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/models/rat_model.fbx';
var RAT_IDLE_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/idle.fbx';
var RAT_WALKING_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/walk.fbx';
var RAT_RUNNING_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/run.fbx';
var RAT_DEATH_ANIMATION_URL = 'http://hifi-content.s3.amazonaws.com/james/rat/animations/death.fbx';
var RAT_IN_NEST_DISTANCE = 4;
//how many milliseconds between rats
var RAT_SPAWN_RATE = 2500;
var RAT_SOUND_URL = 'http://hifi-public.s3.amazonaws.com/sounds/Rats_Squeaks_Active.wav';
var ratRunningSound = SoundCache.getSound(RAT_SOUND_URL);
function playRatRunningAnimation(rat) {
var animationSettings = JSON.stringify({
running: true
});
Entities.editEntity(rat, {
animationURL: RAT_RUNNING_ANIMATION_URL,
animation: {
url: RAT_RUNNING_ANIMATION_URL,
running: true,
fps: 30
},
});
}
function playRatDeathAnimation(rat) {
var animationSettings = JSON.stringify({
running: true
});
Entities.editEntity(rat, {
animationURL: RAT_DEATH_ANIMATION_URL,
animationSettings: animationSettings
});
}
var modelRatProperties = {
name: 'rat',
type: 'Model',
modelURL: RAT_MODEL_URL,
dimensions: RAT_DIMENSIONS,
position: RAT_SPAWNER_LOCATION,
shapeType: 'Box',
damping: 0.8,
angularDamping: 0.99,
friction: 0.75,
collisionsWillMove: true,
ignoreForCollisions: false,
gravity: {
x: 0,
y: -9.8,
z: 0
},
lifetime: 30,
userData: JSON.stringify({
grabbableKey: {
grabbable: false
}
})
};
var targetProperties = {
name: 'Hifi-Rat-Nest',
type: 'Box',
color: {
red: 0,
green: 255,
blue: 0
},
dimensions: {
x: 1,
y: 1,
z: 1
},
visible: false,
position: RAT_NEST_LOCATION
};
var target = Entities.addEntity(targetProperties);
function addRat() {
var rat = Entities.addEntity(modelRatProperties);
return rat;
}
//every sixth rat will play a sound
var RAT_SOUND_RATE = 6;
//spawn rate will be multiplied by this to clear any sounds hanging around
var RAT_SOUND_CLEAR_RATE = 3;
var rats = [];
var metaRats = [];
var ratCount = 0;
var AVOIDER_Y_HEIGHT = 99;
var FIRST_AVOIDER_START_POSITION = {
x: 1004,
y: AVOIDER_Y_HEIGHT,
z: 1019
};
var FIRST_AVOIDER_FINISH_POSITION = {
x: 997,
y: AVOIDER_Y_HEIGHT,
z: 1019
};
var SECOND_AVOIDER_START_POSITION = {
x: 998,
y: AVOIDER_Y_HEIGHT,
z: 998
};
var SECOND_AVOIDER_FINISH_POSITION = {
x: 1005,
y: AVOIDER_Y_HEIGHT,
z: 999
};
var THIRD_AVOIDER_START_POSITION = {
x: 1001.5,
y: 100,
z: 978
};
var THIRD_AVOIDER_FINISH_POSITION = {
x: 1005,
y: 100,
z: 974
};
cleanupLeftoverAvoidersBeforeStart();
var avoiders = [];
addAvoiderBlock(FIRST_AVOIDER_START_POSITION);
addAvoiderBlock(SECOND_AVOIDER_START_POSITION);
addAvoiderBlock(THIRD_AVOIDER_START_POSITION);
function addAvoiderBlock(position) {
var avoiderProperties = {
name: 'Hifi-Rat-Avoider',
type: 'Box',
color: {
red: 255,
green: 0,
blue: 255
},
dimensions: {
x: 1,
y: 1,
z: 1
},
position: position,
collisionsWillMove: false,
ignoreForCollisions: true,
visible: false
};
var avoider = Entities.addEntity(avoiderProperties);
avoiders.push(avoider);
}
tweenAvoider(avoiders[0], FIRST_AVOIDER_START_POSITION, FIRST_AVOIDER_FINISH_POSITION);
tweenAvoider(avoiders[1], SECOND_AVOIDER_START_POSITION, SECOND_AVOIDER_FINISH_POSITION);
tweenAvoider(avoiders[2], THIRD_AVOIDER_START_POSITION, THIRD_AVOIDER_FINISH_POSITION);
function tweenAvoider(entityID, startPosition, endPosition) {
var ANIMATION_DURATION = 4200;
var begin = {
x: startPosition.x,
y: startPosition.y,
z: startPosition.z
};
var end = endPosition;
var original = startPosition;
var tweenHead = new TWEEN.Tween(begin).to(end, ANIMATION_DURATION);
function updateTo() {
Entities.editEntity(entityID, {
position: {
x: begin.x,
y: begin.y,
z: begin.z
}
});
}
function updateBack() {
Entities.editEntity(entityID, {
position: {
x: begin.x,
y: begin.y,
z: begin.z
}
})
}
var tweenBack = new TWEEN.Tween(begin).to(original, ANIMATION_DURATION).onUpdate(updateBack);
tweenHead.onUpdate(function() {
updateTo()
});
tweenHead.chain(tweenBack);
tweenBack.chain(tweenHead);
tweenHead.start();
}
function updateTweens() {
TWEEN.update();
}
function createRatSoundInjector() {
var audioOptions = {
volume: 0.05,
loop: false
};
var injector = Audio.playSound(ratRunningSound, audioOptions);
return injector;
}
function moveRats() {
rats.forEach(function(rat) {
//remove the rat if its near the nest
checkDistanceFromNest(rat);
//see if there are avatars to run from
var avatarFlightVectors = steer.fleeAllAvatars(rat);
var averageAvatarFlight;
var i;
for (i = 0; i < avatarFlightVectors.length; i++) {
if (i === 0) {
averageAvatarFlight = avatarFlightVectors[0];
} else {
averageAvatarFlight = Vec3.sum(avatarFlightVectors[i - 1], avatarFlightVectors[i]);
}
}
averageAvatarFlight = Vec3.multiply(averageAvatarFlight, 1 / avatarFlightVectors.length);
//see if there are avoiders to flee
var avoidBlockVectors = steer.fleeAvoiderBlocks(rat);
var averageAvoiderFlight;
var j;
for (j = 0; j < avoidBlockVectors.length; j++) {
if (j === 0) {
averageAvoiderFlight = avoidBlockVectors[0];
} else {
averageAvoiderFlight = Vec3.sum(avoidBlockVectors[j - 1], avoidBlockVectors[j]);
}
};
averageAvoiderFlight = Vec3.multiply(averageAvoiderFlight, 1 / avoidBlockVectors.length);
//add all of the vectors and divide them by total to get average vector
//start by trying to go toward the nest
var seek = steer.arrive(rat, target);
var averageVector = seek;
var divisorCount = 1;
//if there are avatars to run away from
if (avatarFlightVectors.length > 0) {
divisorCount++;
averageVector = Vec3.sum(averageVector, averageAvatarFlight);
}
//or if there are avoider blocks to run away from
if (avoidBlockVectors.length > 0) {
divisorCount++;
averageVector = Vec3.sum(averageVector, averageAvoiderFlight);
}
averageVector = Vec3.multiply(averageVector, 1 / divisorCount);
var thisRatProps = Entities.getEntityProperties(rat, ["position", "rotation"]);
var ratPosition = thisRatProps.position;
var ratToNest = Vec3.subtract(RAT_NEST_LOCATION, ratPosition);
var ratRotation = Quat.rotationBetween(Vec3.UNIT_Z, ratToNest);
var eulerAngle = Quat.safeEulerAngles(ratRotation);
eulerAngle.x = 0;
eulerAngle.z = 0;
var constrainedRotation = Quat.fromVec3Degrees(eulerAngle);
Entities.editEntity(rat, {
velocity: averageVector,
rotation: constrainedRotation,
});
//have to make a 'meta' rat object to keep track of rats for updating sound injector locations. parenting sounds would make this easy.
var metaRat = getMetaRatByRat(rat);
if (metaRat !== undefined) {
if (metaRat.injector !== undefined) {
if (metaRat.injector.isPlaying === true) {
metaRat.injector.options = {
loop: true,
position: ratPosition
};
}
}
}
})
}
Script.update.connect(moveRats)
Script.update.connect(updateTweens);
function checkDistanceFromNest(rat) {
var ratProps = Entities.getEntityProperties(rat, "position");
var distance = Vec3.distance(ratProps.position, RAT_NEST_LOCATION);
if (distance < RAT_IN_NEST_DISTANCE) {
//at nest
removeRatFromScene(rat);
}
}
function removeRatFromScene(rat) {
var index = rats.indexOf(rat);
if (index > -1) {
rats.splice(index, 1);
Entities.deleteEntity(rat);
}
var metaRatIndex = findWithAttr(metaRats, 'rat', rat);
if (metaRatIndex > -1) {
metaRats[index].injector.stop();
metaRats.splice(index, 1);
}
}
function popRatFromStack(entityID) {
var index = rats.indexOf(entityID);
if (index > -1) {
rats.splice(index, 1);
}
var metaRatIndex = findWithAttr(metaRats, 'rat', entityID);
if (metaRatIndex > -1) {
metaRats[index].injector.stop();
metaRats.splice(index, 1);
}
}
function findWithAttr(array, attr, value) {
for (var i = 0; i < array.length; i += 1) {
if (array[i][attr] === value) {
return i;
}
}
}
function getMetaRatByRat(rat) {
var result = metaRats.filter(function(metaRat) {
return rat === metaRat.rat;
});
return result[0];
}
Entities.deletingEntity.connect(popRatFromStack);
function cleanupLeftoverAvoidersBeforeStart() {
//sometimes if we crash or something there could be extra avoider blocks around. clear them out.
var nearbyEntities = Entities.findEntities(RAT_SPAWNER_LOCATION, 100);
var entityIndex;
for (entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) {
var entityID = nearbyEntities[entityIndex];
var entityProps = Entities.getEntityProperties(entityID);
if (entityProps.name === 'Hifi-Rat-Avoider') {
Entities.deleteEntity(entityID);
}
}
}
function cleanup() {
while (rats.length > 0) {
Entities.deleteEntity(rats.pop());
}
while (avoiders.length > 0) {
Entities.deleteEntity(avoiders.pop());
}
Entities.deleteEntity(target);
Script.update.disconnect(moveRats);
Script.update.disconnect(updateTweens);
Entities.deletingEntity.disconnect(popRatFromStack);
Script.clearInterval(ratSpawnerInterval);
}
Script.scriptEnding.connect(cleanup);
var ratSpawnerInterval;
if (USE_CONSTANT_SPAWNER === true) {
ratSpawnerInterval = Script.setInterval(function() {
var rat = addRat();
playRatRunningAnimation(rat);
rats.push(rat);
ratCount++;
if (ratCount % RAT_SOUND_RATE === 0) {
var metaRat = {
rat: rat,
injector: createRatSoundInjector()
}
metaRats.push(metaRat);
Script.setTimeout(function() {
//if we have too many injectors hanging around there are problems
metaRat.injector.stop();
delete metaRat.injector;
}, RAT_SPAWN_RATE * RAT_SOUND_CLEAR_RATE;
}
}, RAT_SPAWN_RATE);
}

View file

@ -0,0 +1,183 @@
//
// ratSteer.js
//
// Created by James B. Pollack @imgntn on 12/7/2015
// Copyright 2015 High Fidelity, Inc.
//
// This is an example of steering behaviors that can be applied entities.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
function flee(thisEntity, target) {
var targetPosition = Entities.getEntityProperties(target, "position").position;
var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]);
var location = properties.position;
var velocity = properties.velocity;
var MAX_SPEED = 1;
var MAX_FORCE = 1;
var FLEE_RANGE = 2;
var desired = Vec3.subtract(location, targetPosition);
var d = Vec3.length(desired);
desired = Vec3.normalize(desired);
desired = Vec3.multiply(MAX_SPEED, desired);
if (d < FLEE_RANGE) {
var steer = Vec3.subtract(desired, velocity);
var steerVector = new V3(desired.x, 0, desired.z);
steer = steerVector.limit(MAX_FORCE);
return steer;
} else {
//target too far away to flee
return
}
}
function fleeAllAvatars(thisEntity) {
//print('FLEE AVATARS');
var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]);
var location = properties.position;
var velocity = properties.velocity;
var nearbyEntities = Entities.findEntities(location, 3);
var flightVectors = [];
for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) {
var entityID = nearbyEntities[entityIndex];
var entityProps = Entities.getEntityProperties(entityID);
if (entityProps.name === 'Hifi-Avatar-Detector') {
//found an avatar to flee
var MAX_SPEED = 8;
var MAX_FORCE = 8;
var FLEE_AVATAR_RANGE = 3;
var desired = Vec3.subtract(location, entityProps.position);
var d = Vec3.length(desired);
desired = Vec3.normalize(desired);
desired = Vec3.multiply(MAX_SPEED, desired);
if (d < FLEE_AVATAR_RANGE) {
var steer = Vec3.subtract(desired, velocity);
var steerVector = new V3(desired.x, 0, desired.z);
steer = steerVector.limit(MAX_FORCE);
flightVectors.push(steer);
} else {
// target too far away from this avatar to flee
}
}
}
return flightVectors;
}
function fleeAvoiderBlocks(thisEntity) {
// print('FLEE AVOIDER BLOCKS');
var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]);
var location = properties.position;
var velocity = properties.velocity;
var nearbyEntities = Entities.findEntities(location, 2);
var flightVectors = [];
for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) {
var entityID = nearbyEntities[entityIndex];
var entityProps = Entities.getEntityProperties(entityID);
if (entityProps.name === 'Hifi-Rat-Avoider') {
//found an avoiderblock to flee
var MAX_SPEED = 11;
var MAX_FORCE = 6;
var FLEE_AVOIDER_RANGE = 5;
var desired = Vec3.subtract(location, entityProps.position);
var d = Vec3.length(desired);
desired = Vec3.normalize(desired);
desired = Vec3.multiply(MAX_SPEED, desired);
if (d < FLEE_AVOIDER_RANGE) {
var steer = Vec3.subtract(desired, velocity);
var steerVector = new V3(desired.x, 0, desired.z);
steer = steerVector.limit(MAX_FORCE);
flightVectors.push(steer);
} else {
//target too far away from this avoider to flee
}
}
}
return flightVectors;
}
function arrive(thisEntity, target) {
var targetPosition = Entities.getEntityProperties(target, "position").position;
var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]);
var location = properties.position;
var velocity = properties.velocity;
var MAX_SPEED = 10;
var MAX_FORCE = 6;
var ARRIVAL_DISTANCE = 2;
var desired = Vec3.subtract(targetPosition, location);
var d = Vec3.length(desired);
desired = Vec3.normalize(desired);
if (d < ARRIVAL_DISTANCE) {
var m = scale(d, 0, ARRIVAL_DISTANCE, 0, MAX_SPEED);
} else {
desired = Vec3.multiply(MAX_SPEED, desired);
}
var steer = Vec3.subtract(desired, velocity);
var steerVector = new V3(desired.x, 0, desired.z);
steer = steerVector.limit(MAX_FORCE);
return steer;
}
function V3(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
return
}
V3.prototype.length = function() {
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
};
V3.prototype.limit = function(s) {
var len = this.length();
if (len > s && len > 0) {
this.scale(s / len);
}
return this;
};
V3.prototype.scale = function(f) {
this.x *= f;
this.y *= f;
this.z *= f;
return this;
};
var v3 = new V3();
var scale = function(value, min1, max1, min2, max2) {
return min2 + (max2 - min2) * ((value - min1) / (max1 - min1));
}
loadSteer = function() {
return {
flee: flee,
fleeAllAvatars: fleeAllAvatars,
fleeAvoiderBlocks: fleeAvoiderBlocks,
arrive: arrive
};
}

View file

@ -1002,7 +1002,8 @@ function setupModelMenus() {
menuName: "Edit",
menuItemName: "Models",
isSeparator: true,
beforeItem: "Physics"
beforeItem: "Physics",
grouping: "Advanced"
});
if (!Menu.menuItemExists("Edit", "Delete")) {
print("no delete... adding ours");
@ -1012,7 +1013,8 @@ function setupModelMenus() {
shortcutKeyEvent: {
text: "backspace"
},
afterItem: "Models"
afterItem: "Models",
grouping: "Advanced"
});
modelMenuAddedDelete = true;
} else {
@ -1023,7 +1025,8 @@ function setupModelMenus() {
menuName: "Edit",
menuItemName: "Entity List...",
shortcutKey: "CTRL+META+L",
afterItem: "Models"
afterItem: "Models",
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "Edit",
@ -1031,7 +1034,8 @@ function setupModelMenus() {
shortcutKey: "CTRL+META+L",
afterItem: "Entity List...",
isCheckable: true,
isChecked: true
isChecked: true,
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "Edit",
@ -1039,79 +1043,91 @@ function setupModelMenus() {
shortcutKey: "CTRL+META+S",
afterItem: "Allow Selecting of Large Models",
isCheckable: true,
isChecked: true
isChecked: true,
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "Edit",
menuItemName: "Allow Selecting of Lights",
shortcutKey: "CTRL+SHIFT+META+L",
afterItem: "Allow Selecting of Small Models",
isCheckable: true
isCheckable: true,
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "Edit",
menuItemName: "Select All Entities In Box",
shortcutKey: "CTRL+SHIFT+META+A",
afterItem: "Allow Selecting of Lights"
afterItem: "Allow Selecting of Lights",
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "Edit",
menuItemName: "Select All Entities Touching Box",
shortcutKey: "CTRL+SHIFT+META+T",
afterItem: "Select All Entities In Box"
afterItem: "Select All Entities In Box",
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "File",
menuItemName: "Models",
isSeparator: true,
beforeItem: "Settings"
beforeItem: "Settings",
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "File",
menuItemName: "Export Entities",
shortcutKey: "CTRL+META+E",
afterItem: "Models"
afterItem: "Models",
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "File",
menuItemName: "Import Entities",
shortcutKey: "CTRL+META+I",
afterItem: "Export Entities"
afterItem: "Export Entities",
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "File",
menuItemName: "Import Entities from URL",
shortcutKey: "CTRL+META+U",
afterItem: "Import Entities"
afterItem: "Import Entities",
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "View",
menuName: "Edit",
menuItemName: MENU_AUTO_FOCUS_ON_SELECT,
isCheckable: true,
isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true"
isChecked: Settings.getValue(SETTING_AUTO_FOCUS_ON_SELECT) == "true",
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "View",
menuName: "Edit",
menuItemName: MENU_EASE_ON_FOCUS,
afterItem: MENU_AUTO_FOCUS_ON_SELECT,
isCheckable: true,
isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true"
isChecked: Settings.getValue(SETTING_EASE_ON_FOCUS) == "true",
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "View",
menuName: "Edit",
menuItemName: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
afterItem: MENU_EASE_ON_FOCUS,
isCheckable: true,
isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true"
isChecked: Settings.getValue(SETTING_SHOW_LIGHTS_IN_EDIT_MODE) == "true",
grouping: "Advanced"
});
Menu.addMenuItem({
menuName: "View",
menuName: "Edit",
menuItemName: MENU_SHOW_ZONES_IN_EDIT_MODE,
afterItem: MENU_SHOW_LIGHTS_IN_EDIT_MODE,
isCheckable: true,
isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) == "true"
isChecked: Settings.getValue(SETTING_SHOW_ZONES_IN_EDIT_MODE) == "true",
grouping: "Advanced"
});
Entities.setLightsArePickable(false);
@ -1138,10 +1154,10 @@ function cleanupModelMenus() {
Menu.removeMenuItem("File", "Import Entities");
Menu.removeMenuItem("File", "Import Entities from URL");
Menu.removeMenuItem("View", MENU_AUTO_FOCUS_ON_SELECT);
Menu.removeMenuItem("View", MENU_EASE_ON_FOCUS);
Menu.removeMenuItem("View", MENU_SHOW_LIGHTS_IN_EDIT_MODE);
Menu.removeMenuItem("View", MENU_SHOW_ZONES_IN_EDIT_MODE);
Menu.removeMenuItem("Edit", MENU_AUTO_FOCUS_ON_SELECT);
Menu.removeMenuItem("Edit", MENU_EASE_ON_FOCUS);
Menu.removeMenuItem("Edit", MENU_SHOW_LIGHTS_IN_EDIT_MODE);
Menu.removeMenuItem("Edit", MENU_SHOW_ZONES_IN_EDIT_MODE);
}
Script.scriptEnding.connect(function() {

View file

@ -47,8 +47,9 @@ Item {
}
}
implicitHeight: label.implicitHeight * 1.5
implicitHeight: source.visible ? label.implicitHeight * 1.5 : 0
implicitWidth: label.implicitWidth + label.height * 2.5
visible: source.visible
Timer {
id: timer
@ -66,6 +67,7 @@ Item {
color: label.color
text: checkText()
size: label.height
visible: source.visible
font.pixelSize: size
function checkText() {
if (!source || source.type != 1 || !source.checkable) {
@ -89,6 +91,7 @@ Item {
verticalAlignment: Text.AlignVCenter
color: source.enabled ? hifi.colors.text : hifi.colors.disabledText
enabled: source.enabled && source.visible
visible: source.visible
function typedText() {
if (source) {
switch (source.type) {
@ -109,7 +112,7 @@ Item {
x: listView.width - width - 4
size: label.height
width: implicitWidth
visible: source.type == 2
visible: source.visible && (source.type == 2)
text: "\uF0DA"
anchors.verticalCenter: parent.verticalCenter
color: label.color

View file

@ -45,7 +45,7 @@
#include <QtNetwork/QNetworkDiskCache>
#include <gl/Config.h>
#include <QOpenGLContextWrapper.h>
#include <gl/QOpenGLContextWrapper.h>
#include <AccountManager.h>
#include <AddressManager.h>
@ -2764,6 +2764,8 @@ void Application::reloadResourceCaches() {
DependencyManager::get<TextureCache>()->refreshAll();
DependencyManager::get<NodeList>()->reset(); // Force redownload of .fst models
getMyAvatar()->resetFullAvatarURL();
}
void Application::rotationModeChanged() {
@ -3053,7 +3055,7 @@ int Application::sendNackPackets() {
}
if (nackPacketList->getNumPackets()) {
packetsSent += nackPacketList->getNumPackets();
packetsSent += (int)nackPacketList->getNumPackets();
// send the packet list
nodeList->sendPacketList(std::move(nackPacketList), *node);
@ -3077,6 +3079,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
_octreeQuery.setCameraNearClip(_viewFrustum.getNearClip());
_octreeQuery.setCameraFarClip(_viewFrustum.getFarClip());
_octreeQuery.setCameraEyeOffsetPosition(glm::vec3());
_octreeQuery.setKeyholeRadius(_viewFrustum.getKeyholeRadius());
auto lodManager = DependencyManager::get<LODManager>();
_octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale());
_octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust());
@ -3429,10 +3432,10 @@ namespace render {
// Background rendering decision
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
auto skybox = model::SkyboxPointer();
if (skyStage->getBackgroundMode() == model::SunSkyStage::NO_BACKGROUND) {
// this line intentionally left blank
} else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_DOME) {
if (/*!selfAvatarOnly &&*/ Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
if (Menu::getInstance()->isOptionChecked(MenuOption::Stars)) {
PerformanceTimer perfTimer("stars");
PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings),
"Application::payloadRender<BackgroundRenderData>() ... stars...");
@ -3498,10 +3501,9 @@ namespace render {
}
} else if (skyStage->getBackgroundMode() == model::SunSkyStage::SKY_BOX) {
PerformanceTimer perfTimer("skybox");
skybox = skyStage->getSkybox();
auto skybox = skyStage->getSkybox();
if (skybox) {
skybox->render(batch, *(qApp->getDisplayViewFrustum()));
skybox->render(batch, *(args->_viewFrustum));
}
}
}
@ -3768,6 +3770,10 @@ void Application::clearDomainOctreeDetails() {
// reset the model renderer
getEntities()->clear();
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
skyStage->setBackgroundMode(model::SunSkyStage::SKY_DOME);
}
void Application::domainChanged(const QString& domainHostname) {

View file

@ -68,16 +68,22 @@ Menu::Menu() {
dialogsManager.data(), &DialogsManager::toggleLoginDialog);
}
addDisabledActionAndSeparator(fileMenu, "Scripts");
// File Menu > Scripts section -- "Advanced" grouping
addDisabledActionAndSeparator(fileMenu, "Scripts", UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScript, Qt::CTRL | Qt::Key_O,
qApp, SLOT(loadDialog()));
qApp, SLOT(loadDialog()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, MenuOption::LoadScriptURL,
Qt::CTRL | Qt::SHIFT | Qt::Key_O, qApp, SLOT(loadScriptURLDialog()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::StopAllScripts, 0, qApp, SLOT(stopAllScripts()));
Qt::CTRL | Qt::SHIFT | Qt::Key_O, qApp, SLOT(loadScriptURLDialog()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, MenuOption::StopAllScripts, 0, qApp, SLOT(stopAllScripts()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, MenuOption::ReloadAllScripts, Qt::CTRL | Qt::Key_R,
qApp, SLOT(reloadAllScripts()));
qApp, SLOT(reloadAllScripts()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, MenuOption::RunningScripts, Qt::CTRL | Qt::Key_J,
qApp, SLOT(toggleRunningScriptsWidget()));
qApp, SLOT(toggleRunningScriptsWidget()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
auto addressManager = DependencyManager::get<AddressManager>();
@ -112,9 +118,11 @@ Menu::Menu() {
dialogsManager.data(),
SLOT(toggleAddressBar()));
addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyAddress, 0,
addressManager.data(), SLOT(copyAddress()));
addressManager.data(), SLOT(copyAddress()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu, MenuOption::CopyPath, 0,
addressManager.data(), SLOT(copyPath()));
addressManager.data(), SLOT(copyPath()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(fileMenu,
MenuOption::Quit,
@ -143,11 +151,13 @@ Menu::Menu() {
QAction::PreferencesRole);
addActionToQMenuAndActionHash(editMenu, MenuOption::Attachments, 0,
dialogsManager.data(), SLOT(editAttachments()));
dialogsManager.data(), SLOT(editAttachments()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
MenuWrapper* toolsMenu = addMenu("Tools");
addActionToQMenuAndActionHash(toolsMenu, MenuOption::ScriptEditor, Qt::ALT | Qt::Key_S,
dialogsManager.data(), SLOT(showScriptEditor()));
dialogsManager.data(), SLOT(showScriptEditor()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
auto speechRecognizer = DependencyManager::get<SpeechRecognizer>();
@ -155,13 +165,16 @@ Menu::Menu() {
Qt::CTRL | Qt::SHIFT | Qt::Key_C,
speechRecognizer->getEnabled(),
speechRecognizer.data(),
SLOT(setEnabled(bool)));
SLOT(setEnabled(bool)),
UNSPECIFIED_POSITION, "Advanced");
connect(speechRecognizer.data(), SIGNAL(enabledUpdated(bool)), speechRecognizerAction, SLOT(setChecked(bool)));
#endif
addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat,
0, // QML Qt::Key_Backslash,
dialogsManager.data(), SLOT(showIRCLink()));
dialogsManager.data(), SLOT(showIRCLink()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(toolsMenu, MenuOption::AddRemoveFriends, 0,
qApp, SLOT(showFriendsWindow()));
@ -193,22 +206,26 @@ Menu::Menu() {
MenuOption::ToolWindow,
Qt::CTRL | Qt::ALT | Qt::Key_T,
dialogsManager.data(),
SLOT(toggleToolWindow()));
SLOT(toggleToolWindow()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(toolsMenu,
MenuOption::Console,
Qt::CTRL | Qt::ALT | Qt::Key_J,
DependencyManager::get<StandAloneJSConsole>().data(),
SLOT(toggleConsole()));
SLOT(toggleConsole()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(toolsMenu,
MenuOption::ResetSensors,
0, // QML Qt::Key_Apostrophe,
qApp,
SLOT(resetSensors()));
SLOT(resetSensors()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addActionToQMenuAndActionHash(toolsMenu, MenuOption::PackageModel, 0,
qApp, SLOT(packageModel()));
qApp, SLOT(packageModel()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
addMenu(DisplayPlugin::MENU_PATH());
{
@ -220,7 +237,7 @@ Menu::Menu() {
MenuWrapper* avatarMenu = addMenu("Avatar");
QObject* avatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
MenuWrapper* inputModeMenu = addMenu(MenuOption::InputMenu);
MenuWrapper* inputModeMenu = addMenu(MenuOption::InputMenu, "Advanced");
QActionGroup* inputModeGroup = new QActionGroup(inputModeMenu);
inputModeGroup->setExclusive(false);
@ -241,17 +258,12 @@ Menu::Menu() {
avatar,
SLOT(resetSize()));
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::KeyboardMotorControl,
Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehaviorFromMenu()));
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::ScriptedMotorControl, 0, true,
avatar, SLOT(updateMotionBehaviorFromMenu()));
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::NamesAboveHeads, 0, true);
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::BlueSpeechSphere, 0, true);
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::EnableCharacterController, 0, true,
avatar, SLOT(updateMotionBehaviorFromMenu()));
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::NamesAboveHeads, 0, true,
NULL, NULL, UNSPECIFIED_POSITION, "Advanced");
MenuWrapper* viewMenu = addMenu("View");
addActionToQMenuAndActionHash(viewMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches()));
addActionToQMenuAndActionHash(viewMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches()),
QAction::NoRole, UNSPECIFIED_POSITION, "Advanced");
MenuWrapper* cameraModeMenu = viewMenu->addMenu("Camera Mode");
QActionGroup* cameraModeGroup = new QActionGroup(cameraModeMenu);
@ -275,30 +287,29 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Mirror,
0, //QML Qt::SHIFT | Qt::Key_H,
true);
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FullscreenMirror,
0, // QML Qt::Key_H,
false, qApp, SLOT(cameraMenuChanged()));
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView,
0, false, qApp, SLOT(rotationModeChanged()));
0, false, qApp, SLOT(rotationModeChanged()),
UNSPECIFIED_POSITION, "Advanced");
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::TurnWithHead, 0, false);
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::WorldAxes);
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats);
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::WorldAxes, 0, false, NULL, NULL, UNSPECIFIED_POSITION, "Developer");
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Stats, 0, false, NULL, NULL, UNSPECIFIED_POSITION, "Developer");
addActionToQMenuAndActionHash(viewMenu, MenuOption::Log,
Qt::CTRL | Qt::SHIFT | Qt::Key_L,
qApp, SLOT(toggleLogDialog()));
Qt::CTRL | Qt::SHIFT | Qt::Key_L,
qApp, SLOT(toggleLogDialog()), QAction::NoRole, UNSPECIFIED_POSITION, "Developer");
addActionToQMenuAndActionHash(viewMenu, MenuOption::AudioNetworkStats, 0,
dialogsManager.data(), SLOT(audioStatsDetails()));
dialogsManager.data(), SLOT(audioStatsDetails()), QAction::NoRole, UNSPECIFIED_POSITION, "Developer");
addActionToQMenuAndActionHash(viewMenu, MenuOption::BandwidthDetails, 0,
dialogsManager.data(), SLOT(bandwidthDetails()));
dialogsManager.data(), SLOT(bandwidthDetails()), QAction::NoRole, UNSPECIFIED_POSITION, "Developer");
addActionToQMenuAndActionHash(viewMenu, MenuOption::OctreeStats, 0,
dialogsManager.data(), SLOT(octreeStatsDetails()));
dialogsManager.data(), SLOT(octreeStatsDetails()), QAction::NoRole, UNSPECIFIED_POSITION, "Developer");
addCheckableActionToQMenuAndActionHash(viewMenu, "Advanced Menus", 0, false, this, SLOT(toggleAdvancedMenus()));
addCheckableActionToQMenuAndActionHash(viewMenu, "Developer Menus", 0, false, this, SLOT(toggleDeveloperMenus()));
MenuWrapper* developerMenu = addMenu("Developer");
MenuWrapper* developerMenu = addMenu("Developer", "Developer");
MenuWrapper* renderOptionsMenu = developerMenu->addMenu("Render");
addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::Atmosphere,
@ -447,9 +458,23 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::MeshVisible, 0, true,
avatar, SLOT(setEnableMeshVisible(bool)));
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::DisableEyelidAdjustment, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::TurnWithHead, 0, false);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ComfortMode, 0, true);
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::KeyboardMotorControl,
Qt::CTRL | Qt::SHIFT | Qt::Key_K, true, avatar, SLOT(updateMotionBehaviorFromMenu()),
UNSPECIFIED_POSITION, "Developer");
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::ScriptedMotorControl, 0, true,
avatar, SLOT(updateMotionBehaviorFromMenu()),
UNSPECIFIED_POSITION, "Developer");
addCheckableActionToQMenuAndActionHash(avatarDebugMenu, MenuOption::EnableCharacterController, 0, true,
avatar, SLOT(updateMotionBehaviorFromMenu()),
UNSPECIFIED_POSITION, "Developer");
MenuWrapper* handOptionsMenu = developerMenu->addMenu("Hands");
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false);
addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::EnableHandMouseInput, 0, false);
@ -573,6 +598,14 @@ Menu::Menu() {
#endif
}
void Menu::toggleAdvancedMenus() {
setGroupingIsVisible("Advanced", !getGroupingIsVisible("Advanced"));
}
void Menu::toggleDeveloperMenus() {
setGroupingIsVisible("Developer", !getGroupingIsVisible("Developer"));
}
void Menu::loadSettings() {
scanMenuBar(&Menu::loadAction);
}
@ -610,23 +643,36 @@ void Menu::scanMenu(QMenu& menu, settingsAction modifySetting, Settings& setting
settings.endGroup();
}
void Menu::addDisabledActionAndSeparator(MenuWrapper* destinationMenu, const QString& actionName, int menuItemLocation) {
void Menu::addDisabledActionAndSeparator(MenuWrapper* destinationMenu, const QString& actionName,
int menuItemLocation, const QString& grouping) {
QAction* actionBefore = NULL;
QAction* separator;
QAction* separatorText;
if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) {
actionBefore = destinationMenu->actions()[menuItemLocation];
}
if (actionBefore) {
QAction* separator = new QAction("",destinationMenu);
separator = new QAction("",destinationMenu);
destinationMenu->insertAction(actionBefore, separator);
separator->setSeparator(true);
QAction* separatorText = new QAction(actionName,destinationMenu);
separatorText = new QAction(actionName,destinationMenu);
separatorText->setEnabled(false);
destinationMenu->insertAction(actionBefore, separatorText);
} else {
destinationMenu->addSeparator();
(destinationMenu->addAction(actionName))->setEnabled(false);
separator = destinationMenu->addSeparator();
separatorText = destinationMenu->addAction(actionName);
separatorText->setEnabled(false);
}
if (isValidGrouping(grouping)) {
_groupingActions[grouping] << separator;
_groupingActions[grouping] << separatorText;
bool isVisible = getGroupingIsVisible(grouping);
separator->setVisible(isVisible);
separatorText->setVisible(isVisible);
}
}
@ -636,7 +682,8 @@ QAction* Menu::addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
const QObject* receiver,
const char* member,
QAction::MenuRole role,
int menuItemLocation) {
int menuItemLocation,
const QString& grouping) {
QAction* action = NULL;
QAction* actionBefore = NULL;
@ -664,6 +711,11 @@ QAction* Menu::addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
_actionHash.insert(actionName, action);
if (isValidGrouping(grouping)) {
_groupingActions[grouping] << action;
action->setVisible(getGroupingIsVisible(grouping));
}
return action;
}
@ -672,7 +724,8 @@ QAction* Menu::addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
const QString& actionName,
const QKeySequence& shortcut,
QAction::MenuRole role,
int menuItemLocation) {
int menuItemLocation,
const QString& grouping) {
QAction* actionBefore = NULL;
if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) {
@ -699,6 +752,11 @@ QAction* Menu::addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
_actionHash.insert(action->text(), action);
if (isValidGrouping(grouping)) {
_groupingActions[grouping] << action;
action->setVisible(getGroupingIsVisible(grouping));
}
return action;
}
@ -708,19 +766,29 @@ QAction* Menu::addCheckableActionToQMenuAndActionHash(MenuWrapper* destinationMe
const bool checked,
const QObject* receiver,
const char* member,
int menuItemLocation) {
int menuItemLocation,
const QString& grouping) {
QAction* action = addActionToQMenuAndActionHash(destinationMenu, actionName, shortcut, receiver, member,
QAction::NoRole, menuItemLocation);
action->setCheckable(true);
action->setChecked(checked);
if (isValidGrouping(grouping)) {
_groupingActions[grouping] << action;
action->setVisible(getGroupingIsVisible(grouping));
}
return action;
}
void Menu::removeAction(MenuWrapper* menu, const QString& actionName) {
menu->removeAction(_actionHash.value(actionName));
auto action = _actionHash.value(actionName);
menu->removeAction(action);
_actionHash.remove(actionName);
for (auto& grouping : _groupingActions) {
grouping.remove(action);
}
}
void Menu::setIsOptionChecked(const QString& menuOption, bool isChecked) {
@ -850,7 +918,7 @@ int Menu::positionBeforeSeparatorIfNeeded(MenuWrapper* menu, int requestedPositi
}
MenuWrapper* Menu::addMenu(const QString& menuName) {
MenuWrapper* Menu::addMenu(const QString& menuName, const QString& grouping) {
QStringList menuTree = menuName.split(">");
MenuWrapper* addTo = NULL;
MenuWrapper* menu = NULL;
@ -866,6 +934,14 @@ MenuWrapper* Menu::addMenu(const QString& menuName) {
addTo = menu;
}
if (isValidGrouping(grouping)) {
auto action = getMenuAction(menuName);
if (action) {
_groupingActions[grouping] << action;
action->setVisible(getGroupingIsVisible(grouping));
}
}
QMenuBar::repaint();
return menu;
}
@ -897,7 +973,7 @@ bool Menu::menuExists(const QString& menuName) {
return false;
}
void Menu::addSeparator(const QString& menuName, const QString& separatorName) {
void Menu::addSeparator(const QString& menuName, const QString& separatorName, const QString& grouping) {
MenuWrapper* menuObj = getMenu(menuName);
if (menuObj) {
addDisabledActionAndSeparator(menuObj, separatorName);
@ -952,15 +1028,16 @@ void Menu::addMenuItem(const MenuItemProperties& properties) {
QAction* menuItemAction = NULL;
if (properties.isSeparator) {
addDisabledActionAndSeparator(menuObj, properties.menuItemName, requestedPosition);
addDisabledActionAndSeparator(menuObj, properties.menuItemName, requestedPosition, properties.grouping);
} else if (properties.isCheckable) {
menuItemAction = addCheckableActionToQMenuAndActionHash(menuObj, properties.menuItemName,
properties.shortcutKeySequence, properties.isChecked,
MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()), requestedPosition);
MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()),
requestedPosition, properties.grouping);
} else {
menuItemAction = addActionToQMenuAndActionHash(menuObj, properties.menuItemName, properties.shortcutKeySequence,
MenuScriptingInterface::getInstance(), SLOT(menuItemTriggered()),
QAction::NoRole, requestedPosition);
QAction::NoRole, requestedPosition, properties.grouping);
}
if (shortcut && menuItemAction) {
connect(shortcut, SIGNAL(activated()), menuItemAction, SLOT(trigger()));
@ -975,7 +1052,7 @@ void Menu::removeMenuItem(const QString& menu, const QString& menuitem) {
removeAction(menuObj, menuitem);
QMenuBar::repaint();
}
};
}
bool Menu::menuItemExists(const QString& menu, const QString& menuitem) {
QAction* menuItemAction = _actionHash.value(menuitem);
@ -983,7 +1060,31 @@ bool Menu::menuItemExists(const QString& menu, const QString& menuitem) {
return (getMenu(menu) != NULL);
}
return false;
};
}
bool Menu::getGroupingIsVisible(const QString& grouping) {
if (grouping.isEmpty() || grouping.isNull()) {
return true;
}
if (_groupingVisible.contains(grouping)) {
return _groupingVisible[grouping];
}
return false;
}
void Menu::setGroupingIsVisible(const QString& grouping, bool isVisible) {
// NOTE: Default grouping always visible
if (grouping.isEmpty() || grouping.isNull()) {
return;
}
_groupingVisible[grouping] = isVisible;
for (auto action: _groupingActions[grouping]) {
action->setVisible(isVisible);
}
QMenuBar::repaint();
}
void Menu::addActionGroup(const QString& groupName, const QStringList& actionList, const QString& selected) {
auto menu = addMenu(groupName);
@ -1025,8 +1126,8 @@ void MenuWrapper::setEnabled(bool enabled) {
_realMenu->setEnabled(enabled);
}
void MenuWrapper::addSeparator() {
_realMenu->addSeparator();
QAction* MenuWrapper::addSeparator() {
return _realMenu->addSeparator();
}
void MenuWrapper::addAction(QAction* action) {

View file

@ -30,7 +30,7 @@ public:
QList<QAction*> actions();
MenuWrapper* addMenu(const QString& menuName);
void setEnabled(bool enabled = true);
void addSeparator();
QAction* addSeparator();
void addAction(QAction* action);
QAction* addAction(const QString& menuName);
@ -74,28 +74,33 @@ public:
const QObject* receiver = NULL,
const char* member = NULL,
QAction::MenuRole role = QAction::NoRole,
int menuItemLocation = UNSPECIFIED_POSITION);
int menuItemLocation = UNSPECIFIED_POSITION,
const QString& grouping = QString());
QAction* addActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
QAction* action,
const QString& actionName = QString(),
const QKeySequence& shortcut = 0,
QAction::MenuRole role = QAction::NoRole,
int menuItemLocation = UNSPECIFIED_POSITION);
int menuItemLocation = UNSPECIFIED_POSITION,
const QString& grouping = QString());
QAction* addCheckableActionToQMenuAndActionHash(MenuWrapper* destinationMenu,
const QString& actionName,
const QKeySequence& shortcut = 0,
const bool checked = false,
const QObject* receiver = NULL,
const char* member = NULL,
int menuItemLocation = UNSPECIFIED_POSITION);
int menuItemLocation = UNSPECIFIED_POSITION,
const QString& grouping = QString());
void removeAction(MenuWrapper* menu, const QString& actionName);
public slots:
MenuWrapper* addMenu(const QString& menuName);
MenuWrapper* addMenu(const QString& menuName, const QString& grouping = QString());
void removeMenu(const QString& menuName);
bool menuExists(const QString& menuName);
void addSeparator(const QString& menuName, const QString& separatorName);
void addSeparator(const QString& menuName, const QString& separatorName, const QString& grouping = QString());
void removeSeparator(const QString& menuName, const QString& separatorName);
void addMenuItem(const MenuItemProperties& properties);
void removeMenuItem(const QString& menuName, const QString& menuitem);
@ -105,6 +110,12 @@ public slots:
bool isOptionChecked(const QString& menuOption) const;
void setIsOptionChecked(const QString& menuOption, bool isChecked);
bool getGroupingIsVisible(const QString& grouping);
void setGroupingIsVisible(const QString& grouping, bool isVisible); /// NOTE: the "" grouping is always visible
void toggleDeveloperMenus();
void toggleAdvancedMenus();
private:
typedef void(*settingsAction)(Settings&, QAction&);
static void loadAction(Settings& settings, QAction& action);
@ -113,8 +124,10 @@ private:
void scanMenu(QMenu& menu, settingsAction modifySetting, Settings& settings);
/// helper method to have separators with labels that are also compatible with OS X
void addDisabledActionAndSeparator(MenuWrapper* destinationMenu, const QString& actionName,
int menuItemLocation = UNSPECIFIED_POSITION);
void addDisabledActionAndSeparator(MenuWrapper* destinationMenu,
const QString& actionName,
int menuItemLocation = UNSPECIFIED_POSITION,
const QString& grouping = QString());
QAction* getActionFromName(const QString& menuName, MenuWrapper* menu);
MenuWrapper* getSubMenuFromName(const QString& menuName, MenuWrapper* menu);
@ -125,6 +138,10 @@ private:
int positionBeforeSeparatorIfNeeded(MenuWrapper* menu, int requestedPosition);
QHash<QString, QAction*> _actionHash;
bool isValidGrouping(const QString& grouping) const { return grouping == "Advanced" || grouping == "Developer"; }
QHash<QString, bool> _groupingVisible;
QHash<QString, QSet<QAction*>> _groupingActions;
};
namespace MenuOption {
@ -153,7 +170,6 @@ namespace MenuOption {
const QString Back = "Back";
const QString BandwidthDetails = "Bandwidth Details";
const QString BinaryEyelidControl = "Binary Eyelid Control";
const QString BlueSpeechSphere = "Blue Sphere While Speaking";
const QString BookmarkLocation = "Bookmark Location";
const QString Bookmarks = "Bookmarks";
const QString CachesSize = "RAM Caches Size";

View file

@ -495,39 +495,6 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
}
}
}
// quick check before falling into the code below:
// (a 10 degree breadth of an almost 2 meter avatar kicks in at about 12m)
const float MIN_VOICE_SPHERE_DISTANCE = 12.0f;
if (Menu::getInstance()->isOptionChecked(MenuOption::BlueSpeechSphere)
&& distanceToTarget > MIN_VOICE_SPHERE_DISTANCE) {
PROFILE_RANGE_BATCH(batch, __FUNCTION__":renderVoiceSphere");
// render voice intensity sphere for avatars that are farther away
const float MAX_SPHERE_ANGLE = 10.0f * RADIANS_PER_DEGREE;
const float MIN_SPHERE_ANGLE = 0.5f * RADIANS_PER_DEGREE;
const float MIN_SPHERE_SIZE = 0.01f;
const float SPHERE_LOUDNESS_SCALING = 0.0005f;
const float SPHERE_COLOR[] = { 0.5f, 0.8f, 0.8f };
float height = getSkeletonHeight();
glm::vec3 delta = height * (getHead()->getCameraOrientation() * IDENTITY_UP) / 2.0f;
float angle = abs(angleBetween(toTarget + delta, toTarget - delta));
float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING;
if (renderArgs->_renderMode == RenderArgs::DEFAULT_RENDER_MODE && (sphereRadius > MIN_SPHERE_SIZE) &&
(angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) {
batch.setModelTransform(Transform());
Transform transform;
transform.setTranslation(getPosition());
transform.setScale(height);
transform.postScale(sphereRadius);
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch,
transform,
glm::vec4(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.0f - angle / MAX_SPHERE_ANGLE));
}
}
}
const float DISPLAYNAME_DISTANCE = 20.0f;

View file

@ -100,25 +100,25 @@ public:
/// Returns the distance to use as a LOD parameter.
float getLODDistance() const;
virtual bool isMyAvatar() const { return false; }
virtual bool isMyAvatar() const override { return false; }
virtual QVector<glm::quat> getJointRotations() const;
virtual glm::quat getJointRotation(int index) const;
virtual glm::vec3 getJointTranslation(int index) const;
virtual int getJointIndex(const QString& name) const;
virtual QStringList getJointNames() const;
virtual QVector<glm::quat> getJointRotations() const override;
virtual glm::quat getJointRotation(int index) const override;
virtual glm::vec3 getJointTranslation(int index) const override;
virtual int getJointIndex(const QString& name) const override;
virtual QStringList getJointNames() const override;
virtual glm::quat getAbsoluteJointRotationInObjectFrame(int index) const override;
virtual glm::vec3 getAbsoluteJointTranslationInObjectFrame(int index) const override;
virtual void setFaceModelURL(const QUrl& faceModelURL);
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData);
virtual void setBillboard(const QByteArray& billboard);
virtual void setFaceModelURL(const QUrl& faceModelURL) override;
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL) override;
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;
virtual void setBillboard(const QByteArray& billboard) override;
void setShowDisplayName(bool showDisplayName);
virtual int parseDataFromBuffer(const QByteArray& buffer);
virtual int parseDataFromBuffer(const QByteArray& buffer) override;
static void renderJointConnectingCone( gpu::Batch& batch, glm::vec3 position1, glm::vec3 position2,
float radius1, float radius2, const glm::vec4& color);
@ -144,7 +144,7 @@ public:
void scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const;
void slamPosition(const glm::vec3& position);
virtual void updateAttitude() { _skeletonModel.updateAttitude(); }
virtual void updateAttitude() override { _skeletonModel.updateAttitude(); }
// Call this when updating Avatar position with a delta. This will allow us to
// _accurately_ measure position changes and compute the resulting velocity
@ -217,7 +217,7 @@ protected:
virtual bool shouldRenderHead(const RenderArgs* renderArgs) const;
virtual void fixupModelsInScene();
virtual void updateJointMappings();
virtual void updateJointMappings() override;
render::ItemID _renderItemID;

View file

@ -986,6 +986,14 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
_headBoneSet.clear();
}
void MyAvatar::resetFullAvatarURL() {
auto lastAvatarURL = getFullAvatarURLFromPreferences();
auto lastAvatarName = getFullAvatarModelName();
useFullAvatarURL(QUrl());
useFullAvatarURL(lastAvatarURL, lastAvatarName);
}
void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName) {
if (QThread::currentThread() != thread()) {

View file

@ -196,6 +196,8 @@ public:
Q_INVOKABLE void useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName = QString());
Q_INVOKABLE const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; }
Q_INVOKABLE const QString& getFullAvatarModelName() const { return _fullAvatarModelName; }
void resetFullAvatarURL();
virtual void setAttachmentData(const QVector<AttachmentData>& attachmentData) override;

View file

@ -20,7 +20,7 @@ DeviceTracker::SingletonData::~SingletonData() {
}
int DeviceTracker::getNumDevices() {
return Singleton::get()->_devicesMap.size();
return (int)Singleton::get()->_devicesMap.size();
}
DeviceTracker::ID DeviceTracker::getDeviceID(const Name& name) {
@ -58,7 +58,7 @@ DeviceTracker::ID DeviceTracker::registerDevice(const Name& name, DeviceTracker*
}
// Good to register the device
deviceID = Singleton::get()->_devicesVector.size();
deviceID = (ID)Singleton::get()->_devicesVector.size();
Singleton::get()->_devicesMap.insert(Map::value_type(name, deviceID));
Singleton::get()->_devicesVector.push_back(device);
device->assignIDAndName(deviceID, name);

View file

@ -255,7 +255,7 @@ void Faceshift::receive(const QByteArray& buffer) {
}
case fsMsg::MSG_OUT_BLENDSHAPE_NAMES: {
const vector<string>& names = static_pointer_cast<fsMsgBlendshapeNames>(msg)->blendshape_names();
for (size_t i = 0; i < names.size(); i++) {
for (int i = 0; i < (int)names.size(); i++) {
if (names[i] == "EyeBlink_L") {
_leftBlinkIndex = i;

View file

@ -90,7 +90,7 @@ MotionTracker::Index MotionTracker::addJoint(const Semantic& semantic, Index par
// All good then allocate the joint
Index newIndex = _jointsArray.size();
Index newIndex = (Index)_jointsArray.size();
_jointsArray.push_back(JointTracker(semantic, parent));
_jointsMap.insert(JointTracker::Map::value_type(semantic, newIndex));

View file

@ -90,7 +90,7 @@ public:
virtual bool isConnected() const;
Index numJointTrackers() const { return _jointsArray.size(); }
Index numJointTrackers() const { return (Index)_jointsArray.size(); }
/// Access a Joint from it's index.
/// Index 0 is always the "Root".

View file

@ -118,7 +118,7 @@ void Stats::updateStats(bool force) {
STAT_UPDATE(avatarCount, avatarManager->size() - 1);
STAT_UPDATE(avatarRenderableCount, avatarManager->getNumberInRenderRange());
STAT_UPDATE(avatarRenderDistance, (int) round(avatarManager->getRenderDistance())); // deliberately truncating
STAT_UPDATE(serverCount, nodeList->size());
STAT_UPDATE(serverCount, (int)nodeList->size());
STAT_UPDATE(renderrate, (int)qApp->getFps());
if (qApp->getActiveDisplayPlugin()) {
STAT_UPDATE(presentrate, (int)round(qApp->getActiveDisplayPlugin()->presentRate()));
@ -270,7 +270,7 @@ void Stats::updateStats(bool force) {
if (voxelPacketsToProcess == 0) {
_resetRecentMaxPacketsSoon = true;
} else if (voxelPacketsToProcess > _recentMaxPackets) {
_recentMaxPackets = voxelPacketsToProcess;
_recentMaxPackets = (int)voxelPacketsToProcess;
}
// Server Octree Elements
@ -344,18 +344,18 @@ void Stats::setRenderDetails(const RenderDetails& details) {
STAT_UPDATE(triangles, details._trianglesRendered);
STAT_UPDATE(materialSwitches, details._materialSwitches);
if (_expanded) {
STAT_UPDATE(opaqueConsidered, details._opaque._considered);
STAT_UPDATE(opaqueConsidered, (int)details._opaque._considered);
STAT_UPDATE(opaqueOutOfView, details._opaque._outOfView);
STAT_UPDATE(opaqueTooSmall, details._opaque._tooSmall);
STAT_UPDATE(opaqueRendered, details._opaque._rendered);
STAT_UPDATE(translucentConsidered, details._translucent._considered);
STAT_UPDATE(opaqueRendered, (int)details._opaque._rendered);
STAT_UPDATE(translucentConsidered, (int)details._translucent._considered);
STAT_UPDATE(translucentOutOfView, details._translucent._outOfView);
STAT_UPDATE(translucentTooSmall, details._translucent._tooSmall);
STAT_UPDATE(translucentRendered, details._translucent._rendered);
STAT_UPDATE(otherConsidered, details._other._considered);
STAT_UPDATE(translucentRendered, (int)details._translucent._rendered);
STAT_UPDATE(otherConsidered, (int)details._other._considered);
STAT_UPDATE(otherOutOfView, details._other._outOfView);
STAT_UPDATE(otherTooSmall, details._other._tooSmall);
STAT_UPDATE(otherRendered, details._other._rendered);
STAT_UPDATE(otherRendered, (int)details._other._rendered);
}
}

View file

@ -46,10 +46,10 @@ const AnimPoseVec& AnimBlendLinearMove::evaluate(const AnimVariantMap& animVars,
evaluateAndBlendChildren(animVars, triggersOut, alpha, prevPoseIndex, nextPoseIndex, prevDeltaTime, nextDeltaTime);
} else {
float clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1));
size_t prevPoseIndex = glm::floor(clampedAlpha);
size_t nextPoseIndex = glm::ceil(clampedAlpha);
float alpha = glm::fract(clampedAlpha);
auto clampedAlpha = glm::clamp(_alpha, 0.0f, (float)(_children.size() - 1));
auto prevPoseIndex = glm::floor(clampedAlpha);
auto nextPoseIndex = glm::ceil(clampedAlpha);
auto alpha = glm::fract(clampedAlpha);
float prevDeltaTime, nextDeltaTime;
setFrameAndPhase(dt, alpha, prevPoseIndex, nextPoseIndex, &prevDeltaTime, &nextDeltaTime, triggersOut);
evaluateAndBlendChildren(animVars, triggersOut, alpha, prevPoseIndex, nextPoseIndex, prevDeltaTime, nextDeltaTime);

View file

@ -57,7 +57,7 @@ const AnimPoseVec& AnimClip::evaluate(const AnimVariantMap& animVars, float dt,
// It can be quite possible for the user to set _startFrame and _endFrame to
// values before or past valid ranges. We clamp the frames here.
int frameCount = _anim.size();
int frameCount = (int)_anim.size();
prevIndex = std::min(std::max(0, prevIndex), frameCount - 1);
nextIndex = std::min(std::max(0, nextIndex), frameCount - 1);
@ -92,8 +92,8 @@ void AnimClip::copyFromNetworkAnim() {
// by matching joints with the same name.
const FBXGeometry& geom = _networkAnim->getGeometry();
AnimSkeleton animSkeleton(geom);
const int animJointCount = animSkeleton.getNumJoints();
const int skeletonJointCount = _skeleton->getNumJoints();
const auto animJointCount = animSkeleton.getNumJoints();
const auto skeletonJointCount = _skeleton->getNumJoints();
std::vector<int> jointMap;
jointMap.reserve(animJointCount);
for (int i = 0; i < animJointCount; i++) {

View file

@ -114,7 +114,7 @@ void AnimInverseKinematics::computeTargets(const AnimVariantMap& animVars, std::
}
if (removeUnfoundJoints) {
int numVars = _targetVarVec.size();
int numVars = (int)_targetVarVec.size();
int i = 0;
while (i < numVars) {
if (_targetVarVec[i].jointIndex == -1) {
@ -145,7 +145,7 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
int numLoops = 0;
const int MAX_IK_LOOPS = 4;
do {
int lowestMovedIndex = _relativePoses.size();
int lowestMovedIndex = (int)_relativePoses.size();
for (auto& target: targets) {
IKTarget::Type targetType = target.getType();
if (targetType == IKTarget::Type::RotationOnly) {
@ -283,8 +283,8 @@ void AnimInverseKinematics::solveWithCyclicCoordinateDescent(const std::vector<I
}
// only update the absolutePoses that need it: those between lowestMovedIndex and _maxTargetIndex
for (int i = lowestMovedIndex; i <= _maxTargetIndex; ++i) {
int parentIndex = _skeleton->getParentIndex(i);
for (auto i = lowestMovedIndex; i <= _maxTargetIndex; ++i) {
auto parentIndex = _skeleton->getParentIndex((int)i);
if (parentIndex != -1) {
absolutePoses[i] = absolutePoses[parentIndex] * _relativePoses[i];
}

View file

@ -31,7 +31,7 @@ AnimSkeleton::AnimSkeleton(const std::vector<FBXJoint>& joints) {
}
int AnimSkeleton::nameToJointIndex(const QString& jointName) const {
for (size_t i = 0; i < _joints.size(); i++) {
for (int i = 0; i < (int)_joints.size(); i++) {
if (_joints[i].name == jointName) {
return i;
}
@ -40,7 +40,7 @@ int AnimSkeleton::nameToJointIndex(const QString& jointName) const {
}
int AnimSkeleton::getNumJoints() const {
return _joints.size();
return (int)_joints.size();
}
const AnimPose& AnimSkeleton::getAbsoluteBindPose(int jointIndex) const {
@ -101,7 +101,7 @@ void AnimSkeleton::buildSkeletonFromJoints(const std::vector<FBXJoint>& joints)
_relativeDefaultPoses.reserve(joints.size());
// iterate over FBXJoints and extract the bind pose information.
for (size_t i = 0; i < joints.size(); i++) {
for (int i = 0; i < (int)joints.size(); i++) {
// build relative and absolute default poses
glm::mat4 rotTransform = glm::mat4_cast(_joints[i].preRotation * _joints[i].rotation * _joints[i].postRotation);

View file

@ -50,9 +50,11 @@ QScriptValue AnimVariantMap::animVariantMapToScriptValue(QScriptEngine* engine,
if (useNames) { // copy only the requested names
for (const QString& name : names) {
auto search = _map.find(name);
if (search != _map.end()) { // scripts are allowed to request names that do not exist
if (search != _map.end()) {
setOne(name, search->second);
}
} else if (_triggers.count(name) == 1) {
target.setProperty(name, true);
} // scripts are allowed to request names that do not exist
}
} else { // copy all of them

View file

@ -234,7 +234,7 @@ bool Rig::jointStatesEmpty() {
}
int Rig::getJointStateCount() const {
return _internalPoseSet._relativePoses.size();
return (int)_internalPoseSet._relativePoses.size();
}
int Rig::indexOfJoint(const QString& jointName) const {
@ -434,7 +434,7 @@ void Rig::calcAnimAlpha(float speed, const std::vector<float>& referenceSpeeds,
void Rig::computeEyesInRootFrame(const AnimPoseVec& poses) {
// TODO: use cached eye/hips indices for these calculations
int numPoses = poses.size();
int numPoses = (int)poses.size();
int hipsIndex = _animSkeleton->nameToJointIndex(QString("Hips"));
int headIndex = _animSkeleton->nameToJointIndex(QString("Head"));
if (hipsIndex > 0 && headIndex > 0) {
@ -717,7 +717,8 @@ void Rig::updateAnimationStateHandlers() { // called on avatar update thread (wh
// This works (I tried it), but the result would be that we would still have same runtime type checks as the invokeMethod above
// (occuring within the ScriptEngine::callAnimationStateHandler invokeMethod trampoline), _plus_ another runtime check for the dynamic_cast.
// gather results in (likely from an earlier update):
// Gather results in (likely from an earlier update).
// Note: the behavior is undefined if a handler (re-)sets a trigger. Scripts should not be doing that.
_animVars.copyVariantsFrom(value.results); // If multiple handlers write the same anim var, the last registgered wins. (_map preserves order).
}
}
@ -1065,8 +1066,8 @@ glm::mat4 Rig::getJointTransform(int jointIndex) const {
}
void Rig::copyJointsIntoJointData(QVector<JointData>& jointDataVec) const {
jointDataVec.resize(getJointStateCount());
for (int i = 0; i < jointDataVec.size(); i++) {
jointDataVec.resize((int)getJointStateCount());
for (auto i = 0; i < jointDataVec.size(); i++) {
JointData& data = jointDataVec[i];
data.rotationSet |= getJointStateRotation(i, data.rotation);
// geometry offset is used here so that translations are in meters.
@ -1163,7 +1164,7 @@ void Rig::computeAvatarBoundingCapsule(
// even if they do not have legs (default robot)
totalExtents.addPoint(glm::vec3(0.0f));
int numPoses = finalPoses.size();
int numPoses = (int)finalPoses.size();
for (int i = 0; i < numPoses; i++) {
const FBXJointShapeInfo& shapeInfo = geometry.joints.at(i).shapeInfo;
AnimPose pose = finalPoses[i];

View file

@ -36,7 +36,7 @@ void SwingTwistConstraint::SwingLimitFunction::setCone(float maxAngle) {
}
void SwingTwistConstraint::SwingLimitFunction::setMinDots(const std::vector<float>& minDots) {
uint32_t numDots = minDots.size();
uint32_t numDots = (uint32_t)minDots.size();
_minDots.clear();
if (numDots == 0) {
// push two copies of MIN_MINDOT
@ -90,7 +90,7 @@ void SwingTwistConstraint::setSwingLimits(const std::vector<glm::vec3>& swungDir
};
std::vector<SwingLimitData> limits;
uint32_t numLimits = swungDirections.size();
uint32_t numLimits = (uint32_t)swungDirections.size();
limits.reserve(numLimits);
// compute the limit pairs: <theta, minDot>
@ -108,7 +108,7 @@ void SwingTwistConstraint::setSwingLimits(const std::vector<glm::vec3>& swungDir
}
std::vector<float> minDots;
numLimits = limits.size();
numLimits = (uint32_t)limits.size();
if (numLimits == 0) {
// trivial case: nearly free constraint
std::vector<float> minDots;

View file

@ -1184,11 +1184,11 @@ float AudioClient::getAudioOutputMsecsUnplayed() const {
}
qint64 AudioClient::AudioOutputIODevice::readData(char * data, qint64 maxSize) {
int samplesRequested = maxSize / sizeof(int16_t);
auto samplesRequested = maxSize / sizeof(int16_t);
int samplesPopped;
int bytesWritten;
if ((samplesPopped = _receivedAudioStream.popSamples(samplesRequested, false)) > 0) {
if ((samplesPopped = _receivedAudioStream.popSamples((int)samplesRequested, false)) > 0) {
AudioRingBuffer::ConstIterator lastPopOutput = _receivedAudioStream.getLastPopOutput();
lastPopOutput.readSamples((int16_t*)data, samplesPopped);
bytesWritten = samplesPopped * sizeof(int16_t);

View file

@ -55,7 +55,7 @@ static const float LATE_MIX_RIGHT_DEFAULT = 90.0f;
static const float WET_DRY_MIX_DEFAULT = 50.0f;
static void setOption(QScriptValue arguments, const QString name, float defaultValue, float& variable) {
variable = arguments.property(name).isNumber() ? arguments.property(name).toNumber() : defaultValue;
variable = arguments.property(name).isNumber() ? (float)arguments.property(name).toNumber() : defaultValue;
}
AudioEffectOptions::AudioEffectOptions(QScriptValue arguments) {

View file

@ -15,7 +15,8 @@
#include <QtOpenGL/QGLWidget>
#include <QtGui/QImage>
#include <QtGui/QOpenGLContext>
#include <gl/QOpenGLContextWrapper.h>
#include <gl/GLWidget.h>
#include <NumericalConstants.h>
@ -104,7 +105,7 @@ public:
// take the latest texture and present it
_context->makeCurrent();
if (QOpenGLContext::currentContext() == _context->contextHandle()) {
if (isCurrentContext(_context->contextHandle())) {
currentPlugin->present();
_context->doneCurrent();
} else {

View file

@ -66,5 +66,5 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
DependencyManager::get<DeferredLightingEffect>()->renderSolidCubeInstance(batch, getTransformToCenter(), cubeColor);
}
static const auto triCount = DependencyManager::get<GeometryCache>()->getCubeTriangleCount();
args->_details._trianglesRendered += triCount;
args->_details._trianglesRendered += (int)triCount;
}

View file

@ -455,13 +455,6 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
return false; // hmm...
}
if (_needsInitialSimulation) {
// the _model's offset will be wrong until _needsInitialSimulation is false
PerformanceTimer perfTimer("_model->simulate");
_model->simulate(0.0f);
_needsInitialSimulation = false;
}
assert(!_model->getCollisionURL().isEmpty());
if (_model->getURL().isEmpty()) {
@ -475,6 +468,14 @@ bool RenderableModelEntityItem::isReadyToComputeShape() {
if ((collisionNetworkGeometry && collisionNetworkGeometry->isLoaded()) &&
(renderNetworkGeometry && renderNetworkGeometry->isLoaded())) {
// we have both URLs AND both geometries AND they are both fully loaded.
if (_needsInitialSimulation) {
// the _model's offset will be wrong until _needsInitialSimulation is false
PerformanceTimer perfTimer("_model->simulate");
_model->simulate(0.0f);
_needsInitialSimulation = false;
}
return true;
}

View file

@ -29,7 +29,7 @@ public:
virtual ~RenderableModelEntityItem();
virtual void setDimensions(const glm::vec3& value) override;
virtual void setModelURL(const QString& url);
virtual void setModelURL(const QString& url) override;
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;

View file

@ -106,7 +106,7 @@ public:
batch.setInputBuffer(0, _particleBuffer, 0, sizeof(ParticlePrimitive));
auto numParticles = _particleBuffer->getSize() / sizeof(ParticlePrimitive);
batch.drawInstanced(numParticles, gpu::TRIANGLE_STRIP, VERTEX_PER_PARTICLE);
batch.drawInstanced((gpu::uint32)numParticles, gpu::TRIANGLE_STRIP, (gpu::uint32)VERTEX_PER_PARTICLE);
}
protected:

View file

@ -32,11 +32,18 @@
#include <PerfStat.h>
#include <render/Scene.h>
#ifdef _WIN32
#pragma warning(push)
#pragma warning( disable : 4267 )
#endif
#include <PolyVoxCore/CubicSurfaceExtractorWithNormals.h>
#include <PolyVoxCore/MarchingCubesSurfaceExtractor.h>
#include <PolyVoxCore/SurfaceMesh.h>
#include <PolyVoxCore/SimpleVolume.h>
#include <PolyVoxCore/Material.h>
#ifdef _WIN32
#pragma warning(pop)
#endif
#include "model/Geometry.h"
#include "EntityTreeRenderer.h"
@ -539,7 +546,7 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
int voxelVolumeSizeLocation = _pipeline->getProgram()->getUniforms().findLocation("voxelVolumeSize");
batch._glUniform3f(voxelVolumeSizeLocation, _voxelVolumeSize.x, _voxelVolumeSize.y, _voxelVolumeSize.z);
batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
batch.drawIndexed(gpu::TRIANGLES, (gpu::uint32)mesh->getNumIndices(), 0);
}
bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self,

View file

@ -72,5 +72,5 @@ void RenderableSphereEntityItem::render(RenderArgs* args) {
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch, modelTransform, sphereColor);
}
static const auto triCount = DependencyManager::get<GeometryCache>()->getSphereTriangleCount();
args->_details._trianglesRendered += triCount;
args->_details._trianglesRendered += (int)triCount;
}

View file

@ -620,7 +620,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
Q_ASSERT(parser.data() + parser.offset() == dataAt);
#else
const unsigned char* dataAt = parser.data() + parser.offset();
int bytesRead = parser.offset();
int bytesRead = (int)parser.offset();
#endif
auto nodeList = DependencyManager::get<NodeList>();
@ -749,7 +749,7 @@ void EntityItem::debugDump() const {
void EntityItem::adjustEditPacketForClockSkew(QByteArray& buffer, int clockSkew) {
unsigned char* dataAt = reinterpret_cast<unsigned char*>(buffer.data());
int octets = numberOfThreeBitSectionsInCode(dataAt);
int lengthOfOctcode = bytesRequiredForCodeLength(octets);
int lengthOfOctcode = (int)bytesRequiredForCodeLength(octets);
dataAt += lengthOfOctcode;
// lastEdited

View file

@ -389,7 +389,7 @@ protected:
const QByteArray getActionDataInternal() const;
void setActionDataInternal(QByteArray actionData);
virtual void locationChanged();
virtual void locationChanged() override;
EntityTypes::EntityType _type;
quint64 _lastSimulated; // last time this entity called simulate(), this includes velocity, angular velocity,
// and physics changes

View file

@ -1124,7 +1124,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
// the first part of the data is an octcode, this is a required element of the edit packet format, but we don't
// actually use it, we do need to skip it and read to the actual data we care about.
int octets = numberOfThreeBitSectionsInCode(data);
int bytesToReadOfOctcode = bytesRequiredForCodeLength(octets);
int bytesToReadOfOctcode = (int)bytesRequiredForCodeLength(octets);
// we don't actually do anything with this octcode...
dataAt += bytesToReadOfOctcode;

View file

@ -226,9 +226,16 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
while (!toProcess.empty()) {
EntityItemPointer childEntity = std::static_pointer_cast<EntityItem>(toProcess.dequeue());
if (!childEntity) {
continue;
}
BoundingBoxRelatedProperties newChildBBRelProperties(childEntity);
EntityTreeElementPointer containingElement = childEntity->getElement();
if (!containingElement) {
continue;
}
UpdateEntityOperator theChildOperator(getThisPointer(),
childEntity->getElement(),
containingElement,
childEntity, newChildBBRelProperties);
recurseTreeWithOperator(&theChildOperator);
foreach (SpatiallyNestablePointer childChild, childEntity->getChildren()) {
@ -1055,7 +1062,7 @@ int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, cons
break; // bail to prevent buffer overflow
}
QByteArray encodedID = dataByteArray.mid(processedBytes, NUM_BYTES_RFC4122_UUID);
QByteArray encodedID = dataByteArray.mid((int)processedBytes, NUM_BYTES_RFC4122_UUID);
QUuid entityID = QUuid::fromRfc4122(encodedID);
dataAt += encodedID.size();
processedBytes += encodedID.size();
@ -1074,7 +1081,7 @@ int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, cons
}
deleteEntities(entityItemIDsToDelete, true, true);
}
return processedBytes;
return (int)processedBytes;
}
EntityTreeElementPointer EntityTree::getContainingElement(const EntityItemID& entityItemID) /*const*/ {

View file

@ -58,7 +58,7 @@ public:
void createRootElement();
/// Implements our type specific root element factory
virtual OctreeElementPointer createNewElement(unsigned char* octalCode = NULL);
virtual OctreeElementPointer createNewElement(unsigned char* octalCode = NULL) override;
/// Type safe version of getRoot()
EntityTreeElementPointer getRoot() {
@ -68,15 +68,15 @@ public:
return std::static_pointer_cast<EntityTreeElement>(_rootElement);
}
virtual void eraseAllOctreeElements(bool createNewRoot = true);
virtual void eraseAllOctreeElements(bool createNewRoot = true) override;
// These methods will allow the OctreeServer to send your tree inbound edit packets of your
// own definition. Implement these to allow your octree based server to support editing
virtual bool getWantSVOfileVersions() const { return true; }
virtual PacketType expectedDataPacketType() const { return PacketType::EntityData; }
virtual bool canProcessVersion(PacketVersion thisVersion) const
virtual bool getWantSVOfileVersions() const override { return true; }
virtual PacketType expectedDataPacketType() const override { return PacketType::EntityData; }
virtual bool canProcessVersion(PacketVersion thisVersion) const override
{ return thisVersion >= VERSION_ENTITIES_USE_METERS_AND_RADIANS; }
virtual bool handlesEditPacketType(PacketType packetType) const;
virtual bool handlesEditPacketType(PacketType packetType) const override;
void fixupTerseEditLogging(EntityItemProperties& properties, QList<QString>& changedProperties);
virtual int processEditPacketData(ReceivedMessage& message, const unsigned char* editData, int maxLength,
const SharedNodePointer& senderNode) override;
@ -89,18 +89,18 @@ public:
bool* accurateResult = NULL,
bool precisionPicking = false);
virtual bool rootElementHasData() const { return true; }
virtual bool rootElementHasData() const override { return true; }
// the root at least needs to store the number of entities in the packet/buffer
virtual int minimumRequiredRootDataBytes() const { return sizeof(uint16_t); }
virtual bool suppressEmptySubtrees() const { return false; }
virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const;
virtual bool mustIncludeAllChildData() const { return false; }
virtual int minimumRequiredRootDataBytes() const override { return sizeof(uint16_t); }
virtual bool suppressEmptySubtrees() const override { return false; }
virtual void releaseSceneEncodeData(OctreeElementExtraEncodeData* extraEncodeData) const override;
virtual bool mustIncludeAllChildData() const override { return false; }
virtual bool versionHasSVOfileBreaks(PacketVersion thisVersion) const
virtual bool versionHasSVOfileBreaks(PacketVersion thisVersion) const override
{ return thisVersion >= VERSION_ENTITIES_HAS_FILE_BREAKS; }
virtual void update();
virtual void update() override;
// The newer API...
void postAddEntity(EntityItemPointer entityItem);
@ -177,8 +177,8 @@ public:
EntityTreeElementPointer getContainingElement(const EntityItemID& entityItemID) /*const*/;
void setContainingElement(const EntityItemID& entityItemID, EntityTreeElementPointer element);
void debugDumpMap();
virtual void dumpTree();
virtual void pruneTree();
virtual void dumpTree() override;
virtual void pruneTree() override;
QVector<EntityItemID> sendEntities(EntityEditPacketSender* packetSender, EntityTreePointer localTree,
float x, float y, float z);
@ -198,12 +198,12 @@ public:
void remapIDs();
bool writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues);
bool readFromMap(QVariantMap& entityDescription);
virtual bool writeToMap(QVariantMap& entityDescription, OctreeElementPointer element, bool skipDefaultValues) override;
virtual bool readFromMap(QVariantMap& entityDescription) override;
float getContentsLargestDimension();
virtual void resetEditStats() {
virtual void resetEditStats() override {
_totalEditMessages = 0;
_totalUpdates = 0;
_totalCreates = 0;
@ -214,11 +214,11 @@ public:
_totalLoggingTime = 0;
}
virtual quint64 getAverageDecodeTime() const { return _totalEditMessages == 0 ? 0 : _totalDecodeTime / _totalEditMessages; }
virtual quint64 getAverageLookupTime() const { return _totalEditMessages == 0 ? 0 : _totalLookupTime / _totalEditMessages; }
virtual quint64 getAverageUpdateTime() const { return _totalUpdates == 0 ? 0 : _totalUpdateTime / _totalUpdates; }
virtual quint64 getAverageCreateTime() const { return _totalCreates == 0 ? 0 : _totalCreateTime / _totalCreates; }
virtual quint64 getAverageLoggingTime() const { return _totalEditMessages == 0 ? 0 : _totalLoggingTime / _totalEditMessages; }
virtual quint64 getAverageDecodeTime() const override { return _totalEditMessages == 0 ? 0 : _totalDecodeTime / _totalEditMessages; }
virtual quint64 getAverageLookupTime() const override { return _totalEditMessages == 0 ? 0 : _totalLookupTime / _totalEditMessages; }
virtual quint64 getAverageUpdateTime() const override { return _totalUpdates == 0 ? 0 : _totalUpdateTime / _totalUpdates; }
virtual quint64 getAverageCreateTime() const override { return _totalCreates == 0 ? 0 : _totalCreateTime / _totalCreates; }
virtual quint64 getAverageLoggingTime() const override { return _totalEditMessages == 0 ? 0 : _totalLoggingTime / _totalEditMessages; }
void trackIncomingEntityLastEdited(quint64 lastEditedTime, int bytesRead);
quint64 getAverageEditDeltas() const

View file

@ -38,7 +38,7 @@ glm::vec3 EnvironmentData::getSunLocation(const glm::vec3& cameraPosition) const
return _sunLocation;
}
int EnvironmentData::getBroadcastData(unsigned char* destinationBuffer) const {
size_t EnvironmentData::getBroadcastData(unsigned char* destinationBuffer) const {
unsigned char* bufferStart = destinationBuffer;
memcpy(destinationBuffer, &_id, sizeof(_id));
@ -77,7 +77,7 @@ int EnvironmentData::getBroadcastData(unsigned char* destinationBuffer) const {
return destinationBuffer - bufferStart;
}
int EnvironmentData::parseData(const unsigned char* sourceBuffer, int numBytes) {
size_t EnvironmentData::parseData(const unsigned char* sourceBuffer, int numBytes) {
const unsigned char* startPosition = sourceBuffer;
memcpy(&_id, sourceBuffer, sizeof(_id));

View file

@ -54,8 +54,8 @@ public:
glm::vec3 getAtmosphereCenter(const glm::vec3& cameraPosition) const;
glm::vec3 getSunLocation(const glm::vec3& cameraPosition) const;
int getBroadcastData(unsigned char* destinationBuffer) const;
int parseData(const unsigned char* sourceBuffer, int numBytes);
size_t getBroadcastData(unsigned char* destinationBuffer) const;
size_t parseData(const unsigned char* sourceBuffer, int numBytes);
private:

View file

@ -195,8 +195,7 @@ public:
QMultiHash<int, int> newIndices;
QVector<QHash<int, int> > blendshapeIndexMaps;
QVector<QPair<int, int> > partMaterialTextures;
QHash<QString, int> texcoordSetMap;
std::map<QString, int> texcoordSetMap2;
QHash<QString, size_t> texcoordSetMap;
};
/// A single animation frame extracted from an FBX document.

View file

@ -288,7 +288,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn
#endif
}
QHash<QString, int>::iterator it = data.extracted.texcoordSetMap.find(attrib.name);
QHash<QString, size_t>::iterator it = data.extracted.texcoordSetMap.find(attrib.name);
if (it == data.extracted.texcoordSetMap.end()) {
data.extracted.texcoordSetMap.insert(attrib.name, data.attributes.size());
data.attributes.push_back(attrib);

View file

@ -15,7 +15,6 @@
#include <deque>
#include <forward_list>
#include <functional>
#include <GL/glew.h>
#include <mutex>
#include <SharedUtil.h>
@ -49,35 +48,32 @@ template <
>
class GLEscrow {
public:
static const uint64_t MAX_UNSIGNALED_TIME = USECS_PER_SECOND / 2;
struct Item {
T _value;
const T _value;
GLsync _sync;
uint64_t _created;
const uint64_t _created;
Item(T value, GLsync sync) :
_value(value), _sync(sync), _created(usecTimestampNow())
{
}
uint64_t age() {
uint64_t age() const {
return usecTimestampNow() - _created;
}
bool signaled() {
bool signaled() const {
auto result = glClientWaitSync(_sync, 0, 0);
if (GL_TIMEOUT_EXPIRED != result && GL_WAIT_FAILED != result) {
return true;
}
if (age() > (USECS_PER_SECOND / 2)) {
qWarning() << "Long unsignaled sync";
}
return false;
}
};
using Mutex = std::recursive_mutex;
using Lock = std::unique_lock<Mutex>;
using Mutex = std::mutex;
using Recycler = std::function<void(T t)>;
// deque gives us random access, double ended push & pop and size, all in constant time
using Deque = std::deque<Item>;
@ -87,9 +83,32 @@ public:
_recycler = recycler;
}
size_t depth() {
template <typename F>
void withLock(F f) {
using Lock = std::unique_lock<Mutex>;
Lock lock(_mutex);
return _submits.size();
f();
}
template <typename F>
bool tryLock(F f) {
using Lock = std::unique_lock<Mutex>;
bool result = false;
Lock lock(_mutex, std::try_to_lock_t());
if (lock.owns_lock()) {
f();
result = true;
}
return result;
}
size_t depth() {
size_t result{ 0 };
withLock([&]{
result = _submits.size();
});
return result;
}
// Submit a new resource from the producer context
@ -104,11 +123,9 @@ public:
glFlush();
}
{
Lock lock(_mutex);
withLock([&]{
_submits.push_back(Item(t, writeSync));
}
});
return cleanTrash();
}
@ -120,13 +137,13 @@ public:
// On the one hand using try_lock() reduces the chance of blocking the consumer thread,
// but if the produce thread is going fast enough, it could effectively
// starve the consumer out of ever actually getting resources.
if (_mutex.try_lock()) {
tryLock([&]{
// May be called on any thread, but must be inside a locked section
if (signaled(_submits, 0)) {
result = _submits.at(0)._value;
_submits.pop_front();
}
_mutex.unlock();
}
});
return result;
}
@ -154,37 +171,45 @@ public:
glFlush();
}
Lock lock(_mutex);
_releases.push_back(Item(t, readSync));
withLock([&]{
_releases.push_back(Item(t, readSync));
});
}
private:
size_t cleanTrash() {
size_t wastedWork{ 0 };
List trash;
{
tryLock([&]{
while (!_submits.empty()) {
const auto& item = _submits.front();
if (!item._sync || item.age() < MAX_UNSIGNALED_TIME) {
break;
}
qWarning() << "Long unsignaled sync " << item._sync << " unsignaled for " << item.age();
_trash.push_front(item);
_submits.pop_front();
}
// We only ever need one ready item available in the list, so if the
// second item is signaled (implying the first is as well, remove the first
// item. Iterate until the SECOND item in the list is not in the ready state
// The signaled function takes care of checking against the deque size
while (signaled(_submits, 1)) {
pop(_submits);
_trash.push_front(_submits.front());
_submits.pop_front();
++wastedWork;
}
// Stuff in the release queue can be cleared out as soon as it's signaled
while (signaled(_releases, 0)) {
pop(_releases);
_trash.push_front(_releases.front());
_releases.pop_front();
}
{
// FIXME I don't think this lock should be necessary, only the submitting thread
// touches the trash
Lock lock(_mutex);
trash.swap(_trash);
}
}
trash.swap(_trash);
});
// FIXME maybe doing a timing on the deleters and warn if it's taking excessive time?
// although we are out of the lock, so it shouldn't be blocking anything
std::for_each(trash.begin(), trash.end(), [&](typename List::const_reference item) {
@ -198,14 +223,6 @@ private:
return wastedWork;
}
// May be called on any thread, but must be inside a locked section
void pop(Deque& deque) {
Lock lock(_mutex);
auto& item = deque.front();
_trash.push_front(item);
deque.pop_front();
}
// May be called on any thread, but must be inside a locked section
bool signaled(Deque& deque, size_t i) {
if (i >= deque.size()) {

View file

@ -76,3 +76,6 @@ void OffscreenGLCanvas::doneCurrent() {
_context->doneCurrent();
}
QObject* OffscreenGLCanvas::getContextObject() {
return _context;
}

View file

@ -29,7 +29,8 @@ public:
QOpenGLContext* getContext() {
return _context;
}
QObject* getContextObject();
protected:
std::once_flag _reportOnce;
QOpenGLContext* _context;

View file

@ -8,25 +8,24 @@
#include "OffscreenQmlSurface.h"
#include "OglplusHelpers.h"
#include <QWidget>
#include <QtQml>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QQuickItem>
#include <QQuickWindow>
#include <QQuickRenderControl>
#include <QWaitCondition>
#include <QMutex>
#include <QtWidgets/QWidget>
#include <QtQml/QtQml>
#include <QtQml/QQmlEngine>
#include <QtQml/QQmlComponent>
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickWindow>
#include <QtQuick/QQuickRenderControl>
#include <QtCore/QWaitCondition>
#include <QtCore/QMutex>
#include <shared/NsightHelpers.h>
#include <PerfStat.h>
#include <DependencyManager.h>
#include <NumericalConstants.h>
#include "GLEscrow.h"
#include "OffscreenGLCanvas.h"
#include "GLEscrow.h"
// FIXME move to threaded rendering with Qt 5.5
//#define QML_THREADED
// Time between receiving a request to render the offscreen UI actually triggering
// the render. Could possibly be increased depending on the framerate we expect to
@ -56,13 +55,10 @@ private:
Q_DECLARE_LOGGING_CATEGORY(offscreenFocus)
Q_LOGGING_CATEGORY(offscreenFocus, "hifi.offscreen.focus")
#ifdef QML_THREADED
static const QEvent::Type INIT = QEvent::Type(QEvent::User + 1);
static const QEvent::Type RENDER = QEvent::Type(QEvent::User + 2);
static const QEvent::Type RESIZE = QEvent::Type(QEvent::User + 3);
static const QEvent::Type STOP = QEvent::Type(QEvent::User + 4);
static const QEvent::Type UPDATE = QEvent::Type(QEvent::User + 5);
#endif
class OffscreenQmlRenderer : public OffscreenGLCanvas {
friend class OffscreenQmlSurface;
@ -70,22 +66,30 @@ public:
OffscreenQmlRenderer(OffscreenQmlSurface* surface, QOpenGLContext* shareContext) : _surface(surface) {
OffscreenGLCanvas::create(shareContext);
#ifdef QML_THREADED
_renderControl = new QMyQuickRenderControl();
// Create a QQuickWindow that is associated with out render control. Note that this
// window never gets created or shown, meaning that it will never get an underlying
// native (platform) window.
QQuickWindow::setDefaultAlphaBuffer(true);
// Weirdness... QQuickWindow NEEDS to be created on the rendering thread, or it will refuse to render
// because it retains an internal 'context' object that retains the thread it was created on,
// regardless of whether you later move it to another thread.
_quickWindow = new QQuickWindow(_renderControl);
_quickWindow->setColor(QColor(255, 255, 255, 0));
_quickWindow->setFlags(_quickWindow->flags() | static_cast<Qt::WindowFlags>(Qt::WA_TranslucentBackground));
// Qt 5.5
_renderControl->prepareThread(_renderThread);
_context->moveToThread(&_thread);
_renderControl->prepareThread(&_thread);
getContextObject()->moveToThread(&_thread);
moveToThread(&_thread);
_thread.setObjectName("QML Thread");
_thread.start();
post(INIT);
#else
init();
#endif
}
#ifdef QML_THREADED
bool event(QEvent *e)
{
bool event(QEvent *e) {
switch (int(e->type())) {
case INIT:
{
@ -120,7 +124,6 @@ public:
QCoreApplication::postEvent(this, new QEvent(type));
}
#endif
private:
@ -143,27 +146,9 @@ private:
void init() {
_renderControl = new QMyQuickRenderControl();
connect(_renderControl, &QQuickRenderControl::renderRequested, _surface, &OffscreenQmlSurface::requestRender);
connect(_renderControl, &QQuickRenderControl::sceneChanged, _surface, &OffscreenQmlSurface::requestUpdate);
// Create a QQuickWindow that is associated with out render control. Note that this
// window never gets created or shown, meaning that it will never get an underlying
// native (platform) window.
QQuickWindow::setDefaultAlphaBuffer(true);
// Weirdness... QQuickWindow NEEDS to be created on the rendering thread, or it will refuse to render
// because it retains an internal 'context' object that retains the thread it was created on,
// regardless of whether you later move it to another thread.
_quickWindow = new QQuickWindow(_renderControl);
_quickWindow->setColor(QColor(255, 255, 255, 0));
_quickWindow->setFlags(_quickWindow->flags() | static_cast<Qt::WindowFlags>(Qt::WA_TranslucentBackground));
#ifdef QML_THREADED
// However, because we want to use synchronous events with the quickwindow, we need to move it back to the main
// thread after it's created.
_quickWindow->moveToThread(qApp->thread());
#endif
if (!makeCurrent()) {
qWarning("Failed to make context current on render thread");
return;
@ -189,17 +174,15 @@ private:
doneCurrent();
#ifdef QML_THREADED
_context->moveToThread(QCoreApplication::instance()->thread());
getContextObject()->moveToThread(QCoreApplication::instance()->thread());
_cond.wakeOne();
#endif
}
void resize(const QSize& newSize) {
void resize() {
// Update our members
if (_quickWindow) {
_quickWindow->setGeometry(QRect(QPoint(), newSize));
_quickWindow->contentItem()->setSize(newSize);
_quickWindow->setGeometry(QRect(QPoint(), _newSize));
_quickWindow->contentItem()->setSize(_newSize);
}
// Qt bug in 5.4 forces this check of pixel ratio,
@ -209,7 +192,7 @@ private:
pixelRatio = _renderControl->_renderWindow->devicePixelRatio();
}
uvec2 newOffscreenSize = toGlm(newSize * pixelRatio);
uvec2 newOffscreenSize = toGlm(_newSize * pixelRatio);
_textures.setSize(newOffscreenSize);
if (newOffscreenSize == _size) {
return;
@ -222,7 +205,7 @@ private:
return;
}
qDebug() << "Offscreen UI resizing to " << newSize.width() << "x" << newSize.height() << " with pixel ratio " << pixelRatio;
qDebug() << "Offscreen UI resizing to " << _newSize.width() << "x" << _newSize.height() << " with pixel ratio " << pixelRatio;
setupFbo();
doneCurrent();
}
@ -237,54 +220,44 @@ private:
return;
}
//Q_ASSERT(toGlm(_quickWindow->geometry().size()) == _size);
//Q_ASSERT(toGlm(_quickWindow->geometry().size()) == _textures._size);
_renderControl->sync();
#ifdef QML_THREADED
_cond.wakeOne();
lock->unlock();
#endif
using namespace oglplus;
_quickWindow->setRenderTarget(GetName(*_fbo), QSize(_size.x, _size.y));
TexturePtr texture = _textures.getNextTexture();
_fbo->Bind(Framebuffer::Target::Draw);
_fbo->AttachTexture(Framebuffer::Target::Draw, FramebufferAttachment::Color, *texture, 0);
_fbo->Complete(Framebuffer::Target::Draw);
//Context::Clear().ColorBuffer();
{
_renderControl->render();
// FIXME The web browsers seem to be leaving GL in an error state.
// Need a debug context with sync logging to figure out why.
// for now just clear the errors
glGetError();
PROFILE_RANGE("qml_render")
TexturePtr texture = _textures.getNextTexture();
_fbo->Bind(Framebuffer::Target::Draw);
_fbo->AttachTexture(Framebuffer::Target::Draw, FramebufferAttachment::Color, *texture, 0);
_fbo->Complete(Framebuffer::Target::Draw);
{
_renderControl->render();
// FIXME The web browsers seem to be leaving GL in an error state.
// Need a debug context with sync logging to figure out why.
// for now just clear the errors
glGetError();
}
// FIXME probably unecessary
DefaultFramebuffer().Bind(Framebuffer::Target::Draw);
_quickWindow->resetOpenGLState();
_escrow.submit(GetName(*texture));
}
// FIXME probably unecessary
DefaultFramebuffer().Bind(Framebuffer::Target::Draw);
_quickWindow->resetOpenGLState();
_escrow.submit(GetName(*texture));
_lastRenderTime = usecTimestampNow();
}
void aboutToQuit() {
#ifdef QML_THREADED
QMutexLocker lock(&_quitMutex);
_quit = true;
#endif
}
void stop() {
#ifdef QML_THREADED
QMutexLocker lock(&_quitMutex);
QMutexLocker lock(&_mutex);
post(STOP);
_cond.wait(&_mutex);
#else
cleanup();
#endif
}
bool allowNewFrame(uint8_t fps) {
@ -297,13 +270,12 @@ private:
QQuickWindow* _quickWindow{ nullptr };
QMyQuickRenderControl* _renderControl{ nullptr };
#ifdef QML_THREADED
QThread _thread;
QMutex _mutex;
QWaitCondition _cond;
QMutex _quitMutex;
#endif
QSize _newSize;
bool _quit;
FramebufferPtr _fbo;
RenderbufferPtr _depthStencil;
@ -346,9 +318,7 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
}
void OffscreenQmlSurface::resize(const QSize& newSize) {
#ifdef QML_THREADED
QMutexLocker _locker(&(_renderer->_mutex));
#endif
if (!_renderer || !_renderer->_quickWindow) {
QSize currentSize = _renderer->_quickWindow->geometry().size();
if (newSize == currentSize) {
@ -362,11 +332,12 @@ void OffscreenQmlSurface::resize(const QSize& newSize) {
_rootItem->setSize(newSize);
}
#ifdef QML_THREADED
{
QMutexLocker _locker(&(_renderer->_mutex));
_renderer->_newSize = newSize;
}
_renderer->post(RESIZE);
#else
_renderer->resize(newSize);
#endif
}
QQuickItem* OffscreenQmlSurface::getRootItem() {
@ -466,11 +437,7 @@ void OffscreenQmlSurface::updateQuick() {
}
if (_render) {
#ifdef QML_THREADED
_renderer->post(RENDER);
#else
_renderer->render(nullptr);
#endif
_render = false;
}

View file

@ -16,13 +16,6 @@
#if defined(NSIGHT_FOUND)
#include "nvToolsExt.h"
ProfileRange::ProfileRange(const char *name) {
nvtxRangePush(name);
}
ProfileRange::~ProfileRange() {
nvtxRangePop();
}
ProfileRangeBatch::ProfileRangeBatch(gpu::Batch& batch, const char *name) : _batch(batch) {
_batch.pushProfileRange(name);
}

View file

@ -15,6 +15,8 @@
#include <mutex>
#include <functional>
#include <shared/NsightHelpers.h>
#include "Framebuffer.h"
#include "Pipeline.h"
#include "Query.h"
@ -22,18 +24,6 @@
#include "Texture.h"
#include "Transform.h"
#if defined(NSIGHT_FOUND)
class ProfileRange {
public:
ProfileRange(const char *name);
~ProfileRange();
};
#define PROFILE_RANGE(name) ProfileRange profileRangeThis(name);
#else
#define PROFILE_RANGE(name)
#endif
class QDebug;
namespace gpu {

View file

@ -118,7 +118,7 @@ GLBackend::GLFramebuffer* GLBackend::syncGPUObject(const Framebuffer& framebuffe
// Last but not least, define where we draw
if (!colorBuffers.empty()) {
glDrawBuffers(colorBuffers.size(), colorBuffers.data());
glDrawBuffers((GLsizei)colorBuffers.size(), colorBuffers.data());
} else {
glDrawBuffer( GL_NONE );
}
@ -253,7 +253,7 @@ void GLBackend::do_clearFramebuffer(Batch& batch, size_t paramOffset) {
}
if (!drawBuffers.empty()) {
glDrawBuffers(drawBuffers.size(), drawBuffers.data());
glDrawBuffers((GLsizei)drawBuffers.size(), drawBuffers.data());
glClearColor(color.x, color.y, color.z, color.w);
glmask |= GL_COLOR_BUFFER_BIT;
@ -291,7 +291,7 @@ void GLBackend::do_clearFramebuffer(Batch& batch, size_t paramOffset) {
if (_output._framebuffer && !drawBuffers.empty()) {
auto glFramebuffer = syncGPUObject(*_output._framebuffer);
if (glFramebuffer) {
glDrawBuffers(glFramebuffer->_colorBuffers.size(), glFramebuffer->_colorBuffers.data());
glDrawBuffers((GLsizei)glFramebuffer->_colorBuffers.size(), glFramebuffer->_colorBuffers.data());
}
}
@ -301,13 +301,13 @@ void GLBackend::do_clearFramebuffer(Batch& batch, size_t paramOffset) {
void GLBackend::do_blit(Batch& batch, size_t paramOffset) {
auto srcframebuffer = batch._framebuffers.get(batch._params[paramOffset]._uint);
Vec4i srcvp;
for (size_t i = 0; i < 4; ++i) {
for (auto i = 0; i < 4; ++i) {
srcvp[i] = batch._params[paramOffset + 1 + i]._int;
}
auto dstframebuffer = batch._framebuffers.get(batch._params[paramOffset + 5]._uint);
Vec4i dstvp;
for (size_t i = 0; i < 4; ++i) {
for (auto i = 0; i < 4; ++i) {
dstvp[i] = batch._params[paramOffset + 6 + i]._int;
}

View file

@ -357,7 +357,7 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
object->_storageStamp = texture.getStamp();
object->_contentStamp = texture.getDataStamp();
object->_size = texture.getSize();
object->_size = (GLuint)texture.getSize();
}
glBindTexture(GL_TEXTURE_2D, boundTex);
@ -435,7 +435,7 @@ GLBackend::GLTexture* GLBackend::syncGPUObject(const Texture& texture) {
object->_storageStamp = texture.getStamp();
object->_contentStamp = texture.getDataStamp();
object->_size = texture.getSize();
object->_size = (GLuint)texture.getSize();
}
glBindTexture(GL_TEXTURE_CUBE_MAP, boundTex);

View file

@ -106,6 +106,7 @@ public:
bool setAttribute(Slot slot, Frequency frequency = PER_VERTEX);
bool setAttribute(Slot slot, Slot channel, Frequency frequency = PER_VERTEX);
bool hasAttribute(Slot slot) const { return (_attributes.find(slot) != _attributes.end()); }
protected:
AttributeMap _attributes;

View file

@ -99,7 +99,7 @@ bool Texture::Storage::assignMipData(uint16 level, const Element& format, Size s
// The bytes assigned here are supposed to contain all the faces bytes of the mip.
// For tex1D, 2D, 3D there is only one face
// For Cube, we expect the 6 faces in the order X+, X-, Y+, Y-, Z+, Z-
int sizePerFace = size / mip.size();
auto sizePerFace = size / mip.size();
auto faceBytes = bytes;
Size allocated = 0;
for (auto& face : mip) {

View file

@ -135,7 +135,7 @@ TransformCamera getTransformCamera() {
<@func transformClipToEyeDir(cameraTransform, clipPos, eyeDir)@>
{ // transformClipToEyeDir
<$eyeDir$> = vec3(<$cameraTransform$>._projectionInverse * vec4(<$clipPos$>.xyz, 0.0));
<$eyeDir$> = vec3(<$cameraTransform$>._projectionInverse * vec4(<$clipPos$>.xyz, 1.0)); // Must be 1.0 here
}
<@endfunc@>

View file

@ -334,7 +334,7 @@ void NetworkGeometry::modelParseSuccess(FBXGeometry* geometry) {
_meshes.emplace_back(buildNetworkMesh(mesh, _textureBaseUrl));
}
QHash<QString, int> fbxMatIDToMatID;
QHash<QString, size_t> fbxMatIDToMatID;
foreach(const FBXMaterial& material, _geometry->materials) {
fbxMatIDToMatID[material.materialID] = _materials.size();
_materials.emplace_back(buildNetworkMaterial(material, _textureBaseUrl));
@ -348,7 +348,7 @@ void NetworkGeometry::modelParseSuccess(FBXGeometry* geometry) {
NetworkShape* networkShape = new NetworkShape();
networkShape->_meshID = meshID;
networkShape->_partID = partID;
networkShape->_materialID = fbxMatIDToMatID[part.materialID];
networkShape->_materialID = (int)fbxMatIDToMatID[part.materialID];
_shapes.emplace_back(networkShape);
partID++;
}

View file

@ -92,7 +92,7 @@ void Mesh::setPartBuffer(const BufferView& buffer) {
_partBuffer = buffer;
}
const Box Mesh::evalPartBound(int partNum) const {
Box Mesh::evalPartBound(int partNum) const {
Box box;
if (partNum < _partBuffer.getNum<Part>()) {
const Part& part = _partBuffer.get<Part>(partNum);
@ -111,7 +111,7 @@ const Box Mesh::evalPartBound(int partNum) const {
return box;
}
const Box Mesh::evalPartBounds(int partStart, int partEnd, Boxes& bounds) const {
Box Mesh::evalPartBounds(int partStart, int partEnd, Boxes& bounds) const {
Box totalBound;
auto part = _partBuffer.cbegin<Part>() + partStart;
auto partItEnd = _partBuffer.cbegin<Part>() + partEnd;

View file

@ -46,11 +46,11 @@ public:
// Vertex buffer
void setVertexBuffer(const BufferView& buffer);
const BufferView& getVertexBuffer() const { return _vertexBuffer; }
uint getNumVertices() const { return _vertexBuffer.getNumElements(); }
size_t getNumVertices() const { return _vertexBuffer.getNumElements(); }
bool hasVertexData() const { return _vertexBuffer._buffer.get() != nullptr; }
// Attribute Buffers
int getNumAttributes() const { return _attributeBuffers.size(); }
size_t getNumAttributes() const { return _attributeBuffers.size(); }
void addAttribute(Slot slot, const BufferView& buffer);
const BufferView getAttributeBuffer(int attrib) const;
@ -63,7 +63,7 @@ public:
// Index Buffer
void setIndexBuffer(const BufferView& buffer);
const BufferView& getIndexBuffer() const { return _indexBuffer; }
uint getNumIndices() const { return _indexBuffer.getNumElements(); }
size_t getNumIndices() const { return _indexBuffer.getNumElements(); }
// Access vertex position value
const Vec3& getPos3(Index index) const { return _vertexBuffer.get<Vec3>(index); }
@ -104,13 +104,13 @@ public:
void setPartBuffer(const BufferView& buffer);
const BufferView& getPartBuffer() const { return _partBuffer; }
uint getNumParts() const { return _partBuffer.getNumElements(); }
size_t getNumParts() const { return _partBuffer.getNumElements(); }
// evaluate the bounding box of A part
const Box evalPartBound(int partNum) const;
Box evalPartBound(int partNum) const;
// evaluate the bounding boxes of the parts in the range [start, end[ and fill the bounds parameter
// the returned box is the bounding box of ALL the evaluated part bounds.
const Box evalPartBounds(int partStart, int partEnd, Boxes& bounds) const;
Box evalPartBounds(int partStart, int partEnd, Boxes& bounds) const;
static gpu::Primitive topologyToPrimitive(Topology topo) { return static_cast<gpu::Primitive>(topo); }

View file

@ -71,22 +71,12 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& frustum) const {
void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Skybox& skybox) {
// Create the static shared elements used to render the skybox
static gpu::BufferPointer theBuffer;
static gpu::Stream::FormatPointer theFormat;
static gpu::BufferPointer theConstants;
static gpu::PipelinePointer thePipeline;
const int SKYBOX_SKYMAP_SLOT = 0;
const int SKYBOX_CONSTANTS_SLOT = 0;
static std::once_flag once;
std::call_once(once, [&] {
{
const float CLIP = 1.0f;
const glm::vec2 vertices[4] = { { -CLIP, -CLIP }, { CLIP, -CLIP }, { -CLIP, CLIP }, { CLIP, CLIP } };
theBuffer = std::make_shared<gpu::Buffer>(sizeof(vertices), (const gpu::Byte*) vertices);
theFormat = std::make_shared<gpu::Stream::Format>();
theFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ));
}
{
auto skyVS = gpu::Shader::createVertex(std::string(Skybox_vert));
auto skyFS = gpu::Shader::createPixel(std::string(Skybox_frag));
@ -115,8 +105,6 @@ void Skybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, const Sky
batch.setProjectionTransform(projMat);
batch.setViewTransform(viewTransform);
batch.setModelTransform(Transform()); // only for Mac
batch.setInputBuffer(gpu::Stream::POSITION, theBuffer, 0, 8);
batch.setInputFormat(theFormat);
gpu::TexturePointer skymap;
if (skybox.getCubemap() && skybox.getCubemap()->isDefined()) {

View file

@ -11,21 +11,26 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
<@include gpu/Inputs.slh@>
<@include gpu/Transform.slh@>
<$declareStandardTransform()$>
out vec3 _normal;
void main(void) {
void main(void) {
const float depth = 0.0;
const vec4 UNIT_QUAD[4] = vec4[4](
vec4(-1.0, -1.0, depth, 1.0),
vec4(1.0, -1.0, depth, 1.0),
vec4(-1.0, 1.0, depth, 1.0),
vec4(1.0, 1.0, depth, 1.0)
);
vec4 inPosition = UNIT_QUAD[gl_VertexID];
// standard transform
TransformCamera cam = getTransformCamera();
vec3 clipDir = vec3(inPosition.xy, 0.0);
vec3 eyeDir;
<$transformClipToEyeDir(cam, clipDir, eyeDir)$>
<$transformEyeToWorldDir(cam, eyeDir, _normal)$>

View file

@ -131,7 +131,7 @@ public:
void (*linkedDataCreateCallback)(Node *);
int size() const { return _nodeHash.size(); }
size_t size() const { return _nodeHash.size(); }
SharedNodePointer nodeWithUUID(const QUuid& nodeUUID);

View file

@ -259,7 +259,7 @@ bool PacketSender::nonThreadedProcess() {
}
}
int packetsLeft = _packets.size();
auto packetsLeft = _packets.size();
// Now that we know how many packets to send this call to process, just send them.
while ((packetsSentThisCall < packetsToSendThisCall) && (packetsLeft > 0)) {

View file

@ -50,7 +50,7 @@ public:
bool hasPacketsToSend() const { return _packets.size() > 0; }
/// how many packets are there in the send queue waiting to be sent
int packetsToSendCount() const { return _packets.size(); }
size_t packetsToSendCount() const { return _packets.size(); }
/// If you're running in non-threaded mode, call this to give us a hint as to how frequently you will call process.
/// This has no effect in threaded mode. This is only considered a hint in non-threaded mode.

View file

@ -44,7 +44,7 @@ public:
}
/// How many received packets waiting are to be processed
int packetsToProcessCount() const { return _packets.size(); }
int packetsToProcessCount() const { return (int)_packets.size(); }
float getIncomingPPS() const { return _incomingPPS.getAverage(); }
float getProcessedPPS() const { return _processedPPS.getAverage(); }

View file

@ -41,7 +41,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::EntityAdd:
case PacketType::EntityEdit:
case PacketType::EntityData:
return VERSION_ENTITITES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP;
return VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP;
case PacketType::AvatarData:
case PacketType::BulkAvatarData:
return 17;

View file

@ -161,6 +161,6 @@ const PacketVersion VERSION_ENTITIES_KEYLIGHT_PROPERTIES_GROUP_BIS = 48;
const PacketVersion VERSION_ENTITIES_PARTICLES_ADDITIVE_BLENDING = 49;
const PacketVersion VERSION_ENTITIES_POLYLINE_TEXTURE = 50;
const PacketVersion VERSION_ENTITIES_HAVE_PARENTS = 51;
const PacketVersion VERSION_ENTITITES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52;
const PacketVersion VERSION_ENTITIES_REMOVED_START_AUTOMATICALLY_FROM_ANIMATION_PROPERTY_GROUP = 52;
#endif // hifi_PacketHeaders_h

View file

@ -129,7 +129,7 @@ QByteArray PacketList::getMessage() const {
}
QByteArray data;
data.reserve(sizeBytes);
data.reserve((int)sizeBytes);
for (auto& packet : _packets) {
data.append(packet->getPayload(), packet->getPayloadSize());

View file

@ -39,7 +39,7 @@ public:
bool isReliable() const { return _isReliable; }
bool isOrdered() const { return _isOrdered; }
int getNumPackets() const { return _packets.size() + (_currentPacket ? 1 : 0); }
size_t getNumPackets() const { return _packets.size() + (_currentPacket ? 1 : 0); }
size_t getDataSize() const;
size_t getMessageSize() const;
QByteArray getMessage() const;

View file

@ -32,7 +32,7 @@ public:
JurisdictionListener(NodeType_t type = NodeType::EntityServer);
virtual bool process();
virtual bool process() override;
NodeToJurisdictionMap* getJurisdictions() { return &_jurisdictions; }

View file

@ -278,7 +278,7 @@ std::unique_ptr<NLPacket> JurisdictionMap::packIntoPacket() {
packet->write(reinterpret_cast<char*>(_rootOctalCode), bytes);
// if and only if there's a root jurisdiction, also include the end nodes
int endNodeCount = _endNodes.size();
int endNodeCount = (int)_endNodes.size();
packet->writePrimitive(endNodeCount);
for (int i=0; i < endNodeCount; i++) {

View file

@ -52,7 +52,7 @@ public:
unsigned char* getRootOctalCode() const { return _rootOctalCode; }
unsigned char* getEndNodeOctalCode(int index) const { return _endNodes[index]; }
int getEndNodeCount() const { return _endNodes.size(); }
int getEndNodeCount() const { return (int)_endNodes.size(); }
void copyContents(unsigned char* rootCodeIn, const std::vector<unsigned char*>& endNodesIn);

View file

@ -32,7 +32,7 @@ public:
void setJurisdiction(JurisdictionMap* map) { _jurisdictionMap = map; }
virtual bool process();
virtual bool process() override;
NodeType_t getNodeType() const { return _nodeType; }
void setNodeType(NodeType_t type) { _nodeType = type; }

View file

@ -479,12 +479,12 @@ void Octree::readBitstreamToTree(const unsigned char * bitstream, unsigned long
}
}
int octalCodeBytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInStream);
auto octalCodeBytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInStream);
int theseBytesRead = 0;
theseBytesRead += octalCodeBytes;
theseBytesRead += (int)octalCodeBytes;
int lowerLevelBytes = readElementData(bitstreamRootElement, bitstreamAt + octalCodeBytes,
bufferSizeBytes - (bytesRead + octalCodeBytes), args);
bufferSizeBytes - (bytesRead + (int)octalCodeBytes), args);
theseBytesRead += lowerLevelBytes;
@ -921,7 +921,7 @@ int Octree::encodeTreeBitstream(OctreeElementPointer element,
}
} else {
roomForOctalCode = packetData->startSubTree(element->getOctalCode());
codeLength = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(element->getOctalCode()));
codeLength = (int)bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(element->getOctalCode()));
}
// If the octalcode couldn't fit, then we can return, because no nodes below us will fit...

View file

@ -149,7 +149,7 @@ void OctreeEditPacketSender::queuePendingPacketToNodes(std::unique_ptr<NLPacket>
_pendingPacketsLock.lock();
_preServerSingleMessagePackets.push_back(std::move(packet));
// if we've saved MORE than our max, then clear out the oldest packet...
int allPendingMessages = _preServerSingleMessagePackets.size() + _preServerEdits.size();
int allPendingMessages = (int)(_preServerSingleMessagePackets.size() + _preServerEdits.size());
if (allPendingMessages > _maxPendingMessages) {
_preServerSingleMessagePackets.pop_front();
}
@ -210,7 +210,7 @@ void OctreeEditPacketSender::queueOctreeEditMessage(PacketType type, QByteArray&
_preServerEdits.push_back(messagePair);
// if we've saved MORE than out max, then clear out the oldest packet...
int allPendingMessages = _preServerSingleMessagePackets.size() + _preServerEdits.size();
int allPendingMessages = (int)(_preServerSingleMessagePackets.size() + _preServerEdits.size());
if (allPendingMessages > _maxPendingMessages) {
_preServerEdits.pop_front();
}

View file

@ -56,6 +56,7 @@ void OctreeHeadlessViewer::queryOctree() {
_octreeQuery.setCameraNearClip(_viewFrustum.getNearClip());
_octreeQuery.setCameraFarClip(_viewFrustum.getFarClip());
_octreeQuery.setCameraEyeOffsetPosition(glm::vec3());
_octreeQuery.setKeyholeRadius(_viewFrustum.getKeyholeRadius());
_octreeQuery.setOctreeSizeScale(getVoxelSizeScale());
_octreeQuery.setBoundaryLevelAdjust(getBoundaryLevelAdjust());

View file

@ -149,7 +149,7 @@ bool OctreePacketData::startSubTree(const unsigned char* octcode) {
int possibleStartAt = _bytesInUse;
int length = 0;
if (octcode) {
length = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(octcode));
length = (int)bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(octcode));
success = append(octcode, length); // handles checking compression
} else {
// NULL case, means root node, which is 0

View file

@ -63,6 +63,9 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) {
// desired boundaryLevelAdjust
memcpy(destinationBuffer, &_boundaryLevelAdjust, sizeof(_boundaryLevelAdjust));
destinationBuffer += sizeof(_boundaryLevelAdjust);
memcpy(destinationBuffer, &_keyholeRadius, sizeof(_keyholeRadius));
destinationBuffer += sizeof(_keyholeRadius);
return destinationBuffer - bufferStart;
}
@ -104,6 +107,12 @@ int OctreeQuery::parseData(ReceivedMessage& message) {
memcpy(&_boundaryLevelAdjust, sourceBuffer, sizeof(_boundaryLevelAdjust));
sourceBuffer += sizeof(_boundaryLevelAdjust);
auto bytesRead = sourceBuffer - startPosition;
auto bytesLeft = message.getSize() - bytesRead;
if (bytesLeft >= (int)sizeof(_keyholeRadius)) {
memcpy(&_keyholeRadius, sourceBuffer, sizeof(_keyholeRadius));
sourceBuffer += sizeof(_keyholeRadius);
}
return sourceBuffer - startPosition;
}

View file

@ -58,6 +58,7 @@ public:
float getCameraNearClip() const { return _cameraNearClip; }
float getCameraFarClip() const { return _cameraFarClip; }
const glm::vec3& getCameraEyeOffsetPosition() const { return _cameraEyeOffsetPosition; }
float getKeyholeRadius() const { return _keyholeRadius; }
glm::vec3 calculateCameraDirection() const;
@ -69,6 +70,7 @@ public:
void setCameraNearClip(float nearClip) { _cameraNearClip = nearClip; }
void setCameraFarClip(float farClip) { _cameraFarClip = farClip; }
void setCameraEyeOffsetPosition(const glm::vec3& eyeOffsetPosition) { _cameraEyeOffsetPosition = eyeOffsetPosition; }
void setKeyholeRadius(float keyholeRadius) { _keyholeRadius = keyholeRadius; }
// related to Octree Sending strategies
int getMaxQueryPacketsPerSecond() const { return _maxQueryPPS; }
@ -88,6 +90,7 @@ protected:
float _cameraAspectRatio = 1.0f;
float _cameraNearClip = 0.0f;
float _cameraFarClip = 0.0f;
float _keyholeRadius { 0.0f };
glm::vec3 _cameraEyeOffsetPosition = glm::vec3(0.0f);
// octree server sending items

View file

@ -123,14 +123,14 @@ void OctreeSceneStats::copyFromOther(const OctreeSceneStats& other) {
// Now copy the values from the other
if (other._jurisdictionRoot) {
int bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(other._jurisdictionRoot));
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(other._jurisdictionRoot));
_jurisdictionRoot = new unsigned char[bytes];
memcpy(_jurisdictionRoot, other._jurisdictionRoot, bytes);
}
for (size_t i = 0; i < other._jurisdictionEndNodes.size(); i++) {
unsigned char* endNodeCode = other._jurisdictionEndNodes[i];
if (endNodeCode) {
int bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
unsigned char* endNodeCodeCopy = new unsigned char[bytes];
memcpy(endNodeCodeCopy, endNodeCode, bytes);
_jurisdictionEndNodes.push_back(endNodeCodeCopy);
@ -178,7 +178,7 @@ void OctreeSceneStats::sceneStarted(bool isFullScene, bool isMoving, OctreeEleme
if (jurisdictionMap) {
unsigned char* jurisdictionRoot = jurisdictionMap->getRootOctalCode();
if (jurisdictionRoot) {
int bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(jurisdictionRoot));
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(jurisdictionRoot));
_jurisdictionRoot = new unsigned char[bytes];
memcpy(_jurisdictionRoot, jurisdictionRoot, bytes);
}
@ -187,7 +187,7 @@ void OctreeSceneStats::sceneStarted(bool isFullScene, bool isMoving, OctreeEleme
for (int i = 0; i < jurisdictionMap->getEndNodeCount(); i++) {
unsigned char* endNodeCode = jurisdictionMap->getEndNodeOctalCode(i);
if (endNodeCode) {
int bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
unsigned char* endNodeCodeCopy = new unsigned char[bytes];
memcpy(endNodeCodeCopy, endNodeCode, bytes);
_jurisdictionEndNodes.push_back(endNodeCodeCopy);
@ -418,18 +418,18 @@ int OctreeSceneStats::packIntoPacket() {
// add the root jurisdiction
if (_jurisdictionRoot) {
// copy the
int bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_jurisdictionRoot));
int bytes = (int)bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(_jurisdictionRoot));
_statsPacket->writePrimitive(bytes);
_statsPacket->write(reinterpret_cast<char*>(_jurisdictionRoot), bytes);
// if and only if there's a root jurisdiction, also include the end elements
int endNodeCount = _jurisdictionEndNodes.size();
int endNodeCount = (int)_jurisdictionEndNodes.size();
_statsPacket->writePrimitive(endNodeCount);
for (int i=0; i < endNodeCount; i++) {
unsigned char* endNodeCode = _jurisdictionEndNodes[i];
int bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
auto bytes = bytesRequiredForCodeLength(numberOfThreeBitSectionsInCode(endNodeCode));
_statsPacket->writePrimitive(bytes);
_statsPacket->write(reinterpret_cast<char*>(endNodeCode), bytes);
}

View file

@ -51,7 +51,7 @@ public slots:
bool hasPacketsToSend() const { return _packetSender->hasPacketsToSend(); }
/// how many packets are there in the send queue waiting to be sent
int packetsToSendCount() const { return _packetSender->packetsToSendCount(); }
int packetsToSendCount() const { return (int)_packetSender->packetsToSendCount(); }
/// returns the packets per second send rate of this object over its lifetime
float getLifetimePPS() const { return _packetSender->getLifetimePPS(); }

View file

@ -43,7 +43,7 @@ public:
virtual void updateShapeIfNecessary() = 0;
// overrides from btCharacterControllerInterface
virtual void setWalkDirection(const btVector3 &walkDirection) { assert(false); }
virtual void setWalkDirection(const btVector3 &walkDirection) override { assert(false); }
virtual void setVelocityForTimeInterval(const btVector3 &velocity, btScalar timeInterval) override { assert(false); }
virtual void reset(btCollisionWorld* collisionWorld) override { }
virtual void warp(const btVector3& origin) override { }
@ -57,7 +57,7 @@ public:
virtual void playerStep(btCollisionWorld *collisionWorld, btScalar dt) override;
virtual bool canJump() const override { assert(false); return false; } // never call this
virtual void jump() override;
virtual bool onGround() const;
virtual bool onGround() const override;
void preSimulation();
void postSimulation();

View file

@ -271,7 +271,7 @@ void MeshMassProperties::computeMassProperties(const VectorOfPoints& points, con
// create some variables to hold temporary results
#ifndef NDEBUG
uint32_t numPoints = points.size();
uint32_t numPoints = (uint32_t)points.size();
#endif
const btVector3 p0(0.0f, 0.0f, 0.0f);
btMatrix3x3 tetraInertia;
@ -280,7 +280,7 @@ void MeshMassProperties::computeMassProperties(const VectorOfPoints& points, con
btVector3 center;
// loop over triangles
uint32_t numTriangles = triangleIndices.size() / 3;
uint32_t numTriangles = (uint32_t)triangleIndices.size() / 3;
for (uint32_t i = 0; i < numTriangles; ++i) {
uint32_t t = 3 * i;
#ifndef NDEBUG

View file

@ -123,7 +123,7 @@ void Procedural::parse(const QJsonObject& proceduralData) {
_parsedChannels = channels.toArray();
size_t channelCount = std::min(MAX_PROCEDURAL_TEXTURE_CHANNELS, (size_t)_parsedChannels.size());
for (size_t i = 0; i < channelCount; ++i) {
QString url = _parsedChannels.at(i).toString();
QString url = _parsedChannels.at((int)i).toString();
_channels[i] = textureCache->getTexture(QUrl(url));
}
}
@ -238,7 +238,7 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm
gpuTexture->setSampler(sampler);
gpuTexture->autoGenerateMips(-1);
}
batch.setResourceTexture(i, gpuTexture);
batch.setResourceTexture((gpu::uint32)i, gpuTexture);
}
}
}

View file

@ -48,7 +48,7 @@ public:
batch.setIndexBuffer(gpu::UINT16, _indexBuffer, 0);
auto numIndices = _indexBuffer->getSize() / sizeof(uint16_t);
batch.drawIndexed(gpu::LINES, numIndices);
batch.drawIndexed(gpu::LINES, (int)numIndices);
}
gpu::PipelinePointer _pipeline;
@ -326,7 +326,7 @@ void AnimDebugDraw::update() {
for (auto& iter : _absolutePoses) {
AnimSkeleton::ConstPointer& skeleton = std::get<0>(iter.second);
numVerts += skeleton->getNumJoints() * VERTICES_PER_BONE;
for (int i = 0; i < skeleton->getNumJoints(); i++) {
for (auto i = 0; i < skeleton->getNumJoints(); i++) {
auto parentIndex = skeleton->getParentIndex(i);
if (parentIndex >= 0) {
numVerts += VERTICES_PER_LINK;
@ -336,9 +336,9 @@ void AnimDebugDraw::update() {
// count marker verts from shared DebugDraw singleton
auto markerMap = DebugDraw::getInstance().getMarkerMap();
numVerts += markerMap.size() * VERTICES_PER_BONE;
numVerts += (int)markerMap.size() * VERTICES_PER_BONE;
auto myAvatarMarkerMap = DebugDraw::getInstance().getMyAvatarMarkerMap();
numVerts += myAvatarMarkerMap.size() * VERTICES_PER_BONE;
numVerts += (int)myAvatarMarkerMap.size() * VERTICES_PER_BONE;
// allocate verts!
data._vertexBuffer->resize(sizeof(Vertex) * numVerts);

View file

@ -316,7 +316,7 @@ void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radi
void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color,
float intensity, const glm::quat& orientation, float exponent, float cutoff) {
unsigned int lightID = _pointLights.size() + _spotLights.size() + _globalLights.size();
unsigned int lightID = (unsigned int)(_pointLights.size() + _spotLights.size() + _globalLights.size());
if (lightID >= _allocatedLights.size()) {
_allocatedLights.push_back(std::make_shared<model::Light>());
}

View file

@ -93,28 +93,28 @@ void GeometryCache::ShapeData::setupBatch(gpu::Batch& batch) const {
void GeometryCache::ShapeData::draw(gpu::Batch& batch) const {
if (_indexCount) {
setupBatch(batch);
batch.drawIndexed(gpu::TRIANGLES, _indexCount, _indexOffset);
batch.drawIndexed(gpu::TRIANGLES, (gpu::uint32)_indexCount, (gpu::uint32)_indexOffset);
}
}
void GeometryCache::ShapeData::drawWire(gpu::Batch& batch) const {
if (_wireIndexCount) {
setupBatch(batch);
batch.drawIndexed(gpu::LINES, _wireIndexCount, _wireIndexOffset);
batch.drawIndexed(gpu::LINES, (gpu::uint32)_wireIndexCount, (gpu::uint32)_wireIndexOffset);
}
}
void GeometryCache::ShapeData::drawInstances(gpu::Batch& batch, size_t count) const {
if (_indexCount) {
setupBatch(batch);
batch.drawIndexedInstanced(count, gpu::TRIANGLES, _indexCount, _indexOffset);
batch.drawIndexedInstanced((gpu::uint32)count, gpu::TRIANGLES, (gpu::uint32)_indexCount, (gpu::uint32)_indexOffset);
}
}
void GeometryCache::ShapeData::drawWireInstances(gpu::Batch& batch, size_t count) const {
if (_wireIndexCount) {
setupBatch(batch);
batch.drawIndexedInstanced(count, gpu::LINES, _wireIndexCount, _wireIndexOffset);
batch.drawIndexedInstanced((gpu::uint32)count, gpu::LINES, (gpu::uint32)_wireIndexCount, (gpu::uint32)_wireIndexOffset);
}
}
@ -235,7 +235,7 @@ size_t GeometryCache::getCubeTriangleCount() {
void GeometryCache::buildShapes() {
auto vertexBuffer = std::make_shared<gpu::Buffer>();
auto indexBuffer = std::make_shared<gpu::Buffer>();
uint16_t startingIndex = 0;
size_t startingIndex = 0;
// Cube
startingIndex = _shapeVertices->getSize() / SHAPE_VERTEX_STRIDE;
@ -324,7 +324,7 @@ void GeometryCache::buildShapes() {
20, 21, 22, 22, 23, 20 // back
};
for (auto& index : indices) {
index += startingIndex;
index += (uint16_t)startingIndex;
}
IndexVector wireIndices{
@ -334,7 +334,7 @@ void GeometryCache::buildShapes() {
};
for (size_t i = 0; i < wireIndices.size(); ++i) {
indices[i] += startingIndex;
indices[i] += (uint16_t)startingIndex;
}
shapeData.setupIndices(_shapeIndices, indices, wireIndices);
@ -375,7 +375,7 @@ void GeometryCache::buildShapes() {
for (size_t j = 0; j < VERTICES_PER_TRIANGLE; ++j) {
auto triangleVertexIndex = j;
auto vertexIndex = triangleStartIndex + triangleVertexIndex;
indices.push_back(vertexIndex + startingIndex);
indices.push_back((uint16_t)(vertexIndex + startingIndex));
}
}
@ -385,7 +385,7 @@ void GeometryCache::buildShapes() {
};
for (size_t i = 0; i < wireIndices.size(); ++i) {
wireIndices[i] += startingIndex;
wireIndices[i] += (uint16_t)startingIndex;
}
shapeData.setupIndices(_shapeIndices, indices, wireIndices);
@ -411,7 +411,7 @@ void GeometryCache::buildShapes() {
// Spheres use the same values for vertices and normals
vertices.push_back(vertex);
vertices.push_back(vertex);
indices.push_back(vertexIndex + startingIndex);
indices.push_back((uint16_t)(vertexIndex + startingIndex));
}
}
}
@ -445,7 +445,7 @@ void GeometryCache::buildShapes() {
auto vertexIndex = triangleStartIndex + triangleVertexIndex;
vertices.push_back(glm::normalize(originalVertices[vertexIndex]));
vertices.push_back(faceNormal);
indices.push_back(vertexIndex + startingIndex);
indices.push_back((uint16_t)(vertexIndex + startingIndex));
}
}
}
@ -465,8 +465,8 @@ void GeometryCache::buildShapes() {
});
IndexVector wireIndices;
// Only two indices
wireIndices.push_back(0 + startingIndex);
wireIndices.push_back(1 + startingIndex);
wireIndices.push_back(0 + (uint16_t)startingIndex);
wireIndices.push_back(1 + (uint16_t)startingIndex);
shapeData.setupIndices(_shapeIndices, IndexVector(), wireIndices);
}

View file

@ -25,7 +25,7 @@ namespace render {
// Return opaque for lack of a better idea
return ItemKey::Builder::opaqueShape();
}
template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) {
if (payload) {
return payload->getBound();
@ -39,55 +39,40 @@ namespace render {
using namespace render;
MeshPartPayload::MeshPartPayload(Model* model, int meshIndex, int partIndex, int shapeIndex,
glm::vec3 position, glm::quat orientation) :
model(model),
meshIndex(meshIndex),
partIndex(partIndex),
_shapeID(shapeIndex),
_modelPosition(position),
_modelOrientation(orientation) {
initCache();
MeshPartPayload::MeshPartPayload(model::MeshPointer mesh, int partIndex, model::MaterialPointer material, const Transform& transform, const Transform& offsetTransform) {
updateMeshPart(mesh, partIndex);
updateMaterial(material);
updateTransform(transform, offsetTransform);
}
void MeshPartPayload::initCache() {
const std::vector<std::unique_ptr<NetworkMesh>>& networkMeshes = model->_geometry->getMeshes();
const NetworkMesh& networkMesh = *(networkMeshes.at(meshIndex).get());
_drawMesh = networkMesh._mesh;
const FBXGeometry& geometry = model->_geometry->getFBXGeometry();
const FBXMesh& mesh = geometry.meshes.at(meshIndex);
_hasColorAttrib = !mesh.colors.isEmpty();
_isBlendShaped = !mesh.blendshapes.isEmpty();
_isSkinned = !mesh.clusterIndices.isEmpty();
_drawPart = _drawMesh->getPartBuffer().get<model::Mesh::Part>(partIndex);
auto networkMaterial = model->_geometry->getShapeMaterial(_shapeID);
if (networkMaterial) {
_drawMaterial = networkMaterial->_material;
};
void MeshPartPayload::updateMeshPart(model::MeshPointer drawMesh, int partIndex) {
_drawMesh = drawMesh;
if (_drawMesh) {
auto vertexFormat = _drawMesh->getVertexFormat();
_hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR);
_drawPart = _drawMesh->getPartBuffer().get<model::Mesh::Part>(partIndex);
_localBound = _drawMesh->evalPartBound(partIndex);
}
}
void MeshPartPayload::updateModelLocation(glm::vec3 position, glm::quat orientation) {
_modelPosition = position;
_modelOrientation = orientation;
void MeshPartPayload::updateTransform(const Transform& transform, const Transform& offsetTransform) {
_transform = transform;
_offsetTransform = offsetTransform;
Transform::mult(_drawTransform, _transform, _offsetTransform);
_worldBound = _localBound;
_worldBound.transform(_drawTransform);
}
void MeshPartPayload::updateMaterial(model::MaterialPointer drawMaterial) {
_drawMaterial = drawMaterial;
}
render::ItemKey MeshPartPayload::getKey() const {
ItemKey::Builder builder;
builder.withTypeShape();
if (!model->isVisible()) {
builder.withInvisible();
}
if (_isBlendShaped || _isSkinned) {
builder.withDeformed();
}
if (_drawMaterial) {
auto matKey = _drawMaterial->getKey();
if (matKey.isTransparent() || matKey.isTransparentMap()) {
@ -99,9 +84,7 @@ render::ItemKey MeshPartPayload::getKey() const {
}
render::Item::Bound MeshPartPayload::getBound() const {
// NOTE: we can't cache this bounds because we need to handle the case of a moving
// entity or mesh part.
return model->getPartBounds(meshIndex, partIndex, _modelPosition, _modelOrientation);
return _worldBound;
}
void MeshPartPayload::drawCall(gpu::Batch& batch) const {
@ -109,22 +92,12 @@ void MeshPartPayload::drawCall(gpu::Batch& batch) const {
}
void MeshPartPayload::bindMesh(gpu::Batch& batch) const {
if (!_isBlendShaped) {
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
batch.setInputFormat((_drawMesh->getVertexFormat()));
batch.setInputStream(0, _drawMesh->getVertexStream());
} else {
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
batch.setInputFormat((_drawMesh->getVertexFormat()));
batch.setInputFormat((_drawMesh->getVertexFormat()));
batch.setInputStream(0, _drawMesh->getVertexStream());
batch.setInputBuffer(0, model->_blendedVertexBuffers[meshIndex], 0, sizeof(glm::vec3));
batch.setInputBuffer(1, model->_blendedVertexBuffers[meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3));
batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2));
}
// TODO: Get rid of that extra call
if (!_hasColorAttrib) {
batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
@ -215,31 +188,208 @@ void MeshPartPayload::bindMaterial(gpu::Batch& batch, const ModelRender::Locatio
}
void MeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const {
// Still relying on the raw data from the model
const Model::MeshState& state = model->_meshStates.at(meshIndex);
Transform transform;
if (state.clusterBuffer) {
if (model->_cauterizeBones) {
batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer);
} else {
batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer);
}
} else {
if (model->_cauterizeBones) {
transform = Transform(state.cauterizedClusterMatrices[0]);
} else {
transform = Transform(state.clusterMatrices[0]);
}
}
transform.preTranslate(_modelPosition);
batch.setModelTransform(transform);
batch.setModelTransform(_drawTransform);
}
void MeshPartPayload::render(RenderArgs* args) const {
PerformanceTimer perfTimer("MeshPartPayload::render");
if (!model->_readyWhenAdded || !model->_isVisible) {
gpu::Batch& batch = *(args->_batch);
auto mode = args->_renderMode;
auto alphaThreshold = args->_alphaThreshold; //translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME
model::MaterialKey drawMaterialKey;
if (_drawMaterial) {
drawMaterialKey = _drawMaterial->getKey();
}
bool translucentMesh = drawMaterialKey.isTransparent() || drawMaterialKey.isTransparentMap();
bool hasTangents = drawMaterialKey.isNormalMap();
bool hasSpecular = drawMaterialKey.isGlossMap();
bool hasLightmap = drawMaterialKey.isLightmapMap();
bool isSkinned = false;
bool wireframe = false;
if (wireframe) {
translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false;
}
ModelRender::Locations* locations = nullptr;
ModelRender::pickPrograms(batch, mode, translucentMesh, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe,
args, locations);
// Bind the model transform and the skinCLusterMatrices if needed
bindTransform(batch, locations);
//Bind the index buffer and vertex buffer and Blend shapes if needed
bindMesh(batch);
// apply material properties
bindMaterial(batch, locations);
// TODO: We should be able to do that just in the renderTransparentJob
if (translucentMesh && locations->lightBufferUnit >= 0) {
PerformanceTimer perfTimer("DLE->setupTransparent()");
DependencyManager::get<DeferredLightingEffect>()->setupTransparent(args, locations->lightBufferUnit);
}
if (args) {
args->_details._materialSwitches++;
}
// Draw!
{
PerformanceTimer perfTimer("batch.drawIndexed()");
drawCall(batch);
}
if (args) {
const int INDICES_PER_TRIANGLE = 3;
args->_details._trianglesRendered += _drawPart._numIndices / INDICES_PER_TRIANGLE;
}
}
namespace render {
template <> const ItemKey payloadGetKey(const ModelMeshPartPayload::Pointer& payload) {
if (payload) {
return payload->getKey();
}
// Return opaque for lack of a better idea
return ItemKey::Builder::opaqueShape();
}
template <> const Item::Bound payloadGetBound(const ModelMeshPartPayload::Pointer& payload) {
if (payload) {
return payload->getBound();
}
return render::Item::Bound();
}
template <> void payloadRender(const ModelMeshPartPayload::Pointer& payload, RenderArgs* args) {
return payload->render(args);
}
}
using namespace render;
ModelMeshPartPayload::ModelMeshPartPayload(Model* model, int _meshIndex, int partIndex, int shapeIndex, const Transform& transform, const Transform& offsetTransform) :
_model(model),
_meshIndex(_meshIndex),
_shapeID(shapeIndex) {
auto& modelMesh = _model->_geometry->getMeshes().at(_meshIndex)->_mesh;
updateMeshPart(modelMesh, partIndex);
updateTransform(transform, offsetTransform);
initCache();
}
void ModelMeshPartPayload::initCache() {
if (_drawMesh) {
auto vertexFormat = _drawMesh->getVertexFormat();
_hasColorAttrib = vertexFormat->hasAttribute(gpu::Stream::COLOR);
_isSkinned = vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_WEIGHT) && vertexFormat->hasAttribute(gpu::Stream::SKIN_CLUSTER_INDEX);
const FBXGeometry& geometry = _model->_geometry->getFBXGeometry();
const FBXMesh& mesh = geometry.meshes.at(_meshIndex);
_isBlendShaped = !mesh.blendshapes.isEmpty();
}
auto networkMaterial = _model->_geometry->getShapeMaterial(_shapeID);
if (networkMaterial) {
_drawMaterial = networkMaterial->_material;
};
}
void ModelMeshPartPayload::notifyLocationChanged() {
_model->_needsUpdateClusterMatrices = true;
}
render::ItemKey ModelMeshPartPayload::getKey() const {
ItemKey::Builder builder;
builder.withTypeShape();
if (!_model->isVisible()) {
builder.withInvisible();
}
if (_isBlendShaped || _isSkinned) {
builder.withDeformed();
}
if (_drawMaterial) {
auto matKey = _drawMaterial->getKey();
if (matKey.isTransparent() || matKey.isTransparentMap()) {
builder.withTransparent();
}
}
return builder.build();
}
render::Item::Bound ModelMeshPartPayload::getBound() const {
// NOTE: we can't cache this bounds because we need to handle the case of a moving
// entity or mesh part.
return _model->getPartBounds(_meshIndex, _partIndex, _transform.getTranslation(), _transform.getRotation());
}
void ModelMeshPartPayload::bindMesh(gpu::Batch& batch) const {
if (!_isBlendShaped) {
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
batch.setInputFormat((_drawMesh->getVertexFormat()));
batch.setInputStream(0, _drawMesh->getVertexStream());
} else {
batch.setIndexBuffer(gpu::UINT32, (_drawMesh->getIndexBuffer()._buffer), 0);
batch.setInputFormat((_drawMesh->getVertexFormat()));
batch.setInputBuffer(0, _model->_blendedVertexBuffers[_meshIndex], 0, sizeof(glm::vec3));
batch.setInputBuffer(1, _model->_blendedVertexBuffers[_meshIndex], _drawMesh->getNumVertices() * sizeof(glm::vec3), sizeof(glm::vec3));
batch.setInputStream(2, _drawMesh->getVertexStream().makeRangedStream(2));
}
// TODO: Get rid of that extra call
if (!_hasColorAttrib) {
batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}
}
void ModelMeshPartPayload::bindTransform(gpu::Batch& batch, const ModelRender::Locations* locations) const {
// Still relying on the raw data from the model
const Model::MeshState& state = _model->_meshStates.at(_meshIndex);
Transform transform;
if (state.clusterBuffer) {
if (_model->_cauterizeBones) {
batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.cauterizedClusterBuffer);
} else {
batch.setUniformBuffer(ModelRender::SKINNING_GPU_SLOT, state.clusterBuffer);
}
} else {
if (_model->_cauterizeBones) {
transform = Transform(state.cauterizedClusterMatrices[0]);
} else {
transform = Transform(state.clusterMatrices[0]);
}
}
// transform.preTranslate(_modelPosition);
transform.preTranslate(_transform.getTranslation());
batch.setModelTransform(transform);
}
void ModelMeshPartPayload::render(RenderArgs* args) const {
PerformanceTimer perfTimer("ModelMeshPartPayload::render");
if (!_model->_readyWhenAdded || !_model->_isVisible) {
return; // bail asap
}
@ -248,25 +398,25 @@ void MeshPartPayload::render(RenderArgs* args) const {
auto alphaThreshold = args->_alphaThreshold; //translucent ? TRANSPARENT_ALPHA_THRESHOLD : OPAQUE_ALPHA_THRESHOLD; // FIX ME
const FBXGeometry& geometry = model->_geometry->getFBXGeometry();
const std::vector<std::unique_ptr<NetworkMesh>>& networkMeshes = model->_geometry->getMeshes();
const FBXGeometry& geometry = _model->_geometry->getFBXGeometry();
const std::vector<std::unique_ptr<NetworkMesh>>& networkMeshes = _model->_geometry->getMeshes();
// guard against partially loaded meshes
if (meshIndex >= (int)networkMeshes.size() || meshIndex >= (int)geometry.meshes.size() || meshIndex >= (int)model->_meshStates.size() ) {
if (_meshIndex >= (int)networkMeshes.size() || _meshIndex >= (int)geometry.meshes.size() || _meshIndex >= (int)_model->_meshStates.size() ) {
return;
}
// Back to model to update the cluster matrices right now
model->updateClusterMatrices(_modelPosition, _modelOrientation);
_model->updateClusterMatrices(_transform.getTranslation(), _transform.getRotation());
const FBXMesh& mesh = geometry.meshes.at(meshIndex);
const FBXMesh& mesh = geometry.meshes.at(_meshIndex);
// if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown
// to false to rebuild out mesh groups.
if (meshIndex < 0 || meshIndex >= (int)networkMeshes.size() || meshIndex > geometry.meshes.size()) {
model->_meshGroupsKnown = false; // regenerate these lists next time around.
model->_readyWhenAdded = false; // in case any of our users are using scenes
model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid
if (_meshIndex < 0 || _meshIndex >= (int)networkMeshes.size() || _meshIndex > geometry.meshes.size()) {
_model->_meshGroupsKnown = false; // regenerate these lists next time around.
_model->_readyWhenAdded = false; // in case any of our users are using scenes
_model->invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid
return; // FIXME!
}
@ -276,13 +426,7 @@ void MeshPartPayload::render(RenderArgs* args) const {
// sanity check
return; // FIXME!
}
// guard against partially loaded meshes
if (partIndex >= mesh.parts.size()) {
return;
}
model::MaterialKey drawMaterialKey;
if (_drawMaterial) {
drawMaterialKey = _drawMaterial->getKey();
@ -293,12 +437,12 @@ void MeshPartPayload::render(RenderArgs* args) const {
bool hasSpecular = drawMaterialKey.isGlossMap();
bool hasLightmap = drawMaterialKey.isLightmapMap();
bool isSkinned = _isSkinned;
bool wireframe = model->isWireframe();
bool wireframe = _model->isWireframe();
// render the part bounding box
#ifdef DEBUG_BOUNDING_PARTS
{
AABox partBounds = getPartBounds(meshIndex, partIndex);
AABox partBounds = getPartBounds(_meshIndex, partIndex);
bool inView = args->_viewFrustum->boxInFrustum(partBounds) != ViewFrustum::OUTSIDE;
glm::vec4 cubeColor;

Some files were not shown because too many files have changed in this diff Show more