Merge branch 'master' of github.com:highfidelity/hifi into feat/create/native-windows

This commit is contained in:
Thijs Wenker 2018-07-06 20:06:50 +02:00
commit eea95161ab
55 changed files with 298 additions and 178 deletions

View file

@ -39,7 +39,7 @@ Go to `Control Panel > System > Advanced System Settings > Environment Variables
### Step 6. Installing OpenSSL via vcpkg ### Step 6. Installing OpenSSL via vcpkg
* In the vcpkg directory, install the 64 bit OpenSSL package with the command `vcpkg install openssl:x64-windows` * In the vcpkg directory, install the 64 bit OpenSSL package with the command `.\vcpkg install openssl:x64-windows`
* Once the build completes you should have a file `ssl.h` in `${VCPKG_ROOT}/installed/x64-windows/include/openssl` * Once the build completes you should have a file `ssl.h` in `${VCPKG_ROOT}/installed/x64-windows/include/openssl`
### Step 7. Running CMake to Generate Build Files ### Step 7. Running CMake to Generate Build Files

View file

@ -4,7 +4,7 @@ android {
compileSdkVersion 26 compileSdkVersion 26
//buildToolsVersion '27.0.3' //buildToolsVersion '27.0.3'
def appVersionCode = Integer.valueOf(RELEASE_NUMBER ?: 1) def appVersionCode = Integer.valueOf(VERSION_CODE ?: 1)
def appVersionName = RELEASE_NUMBER ?: "1.0" def appVersionName = RELEASE_NUMBER ?: "1.0"
defaultConfig { defaultConfig {

View file

@ -37,6 +37,7 @@ task clean(type: Delete) {
ext { ext {
RELEASE_NUMBER = project.hasProperty('RELEASE_NUMBER') ? project.getProperty('RELEASE_NUMBER') : '0' RELEASE_NUMBER = project.hasProperty('RELEASE_NUMBER') ? project.getProperty('RELEASE_NUMBER') : '0'
VERSION_CODE = project.hasProperty('VERSION_CODE') ? project.getProperty('VERSION_CODE') : '0'
RELEASE_TYPE = project.hasProperty('RELEASE_TYPE') ? project.getProperty('RELEASE_TYPE') : 'DEV' RELEASE_TYPE = project.hasProperty('RELEASE_TYPE') ? project.getProperty('RELEASE_TYPE') : 'DEV'
STABLE_BUILD = project.hasProperty('STABLE_BUILD') ? project.getProperty('STABLE_BUILD') : '0' STABLE_BUILD = project.hasProperty('STABLE_BUILD') ? project.getProperty('STABLE_BUILD') : '0'
EXEC_SUFFIX = Os.isFamily(Os.FAMILY_WINDOWS) ? '.exe' : '' EXEC_SUFFIX = Os.isFamily(Os.FAMILY_WINDOWS) ? '.exe' : ''

View file

@ -17,6 +17,9 @@ EntityTreeHeadlessViewer::EntityTreeHeadlessViewer()
} }
EntityTreeHeadlessViewer::~EntityTreeHeadlessViewer() { EntityTreeHeadlessViewer::~EntityTreeHeadlessViewer() {
if (_simulation) {
_simulation->setEntityTree(nullptr); // Break shared_ptr cycle.
}
} }
void EntityTreeHeadlessViewer::init() { void EntityTreeHeadlessViewer::init() {

View file

@ -69,9 +69,6 @@ EntityScriptServer::EntityScriptServer(ReceivedMessage& message) : ThreadedAssig
DependencyManager::set<AudioInjectorManager>(); DependencyManager::set<AudioInjectorManager>();
DependencyManager::set<ScriptCache>(); DependencyManager::set<ScriptCache>();
DependencyManager::set<ScriptEngines>(ScriptEngine::ENTITY_SERVER_SCRIPT);
DependencyManager::set<EntityScriptServerServices>();
// Needed to ensure the creation of the DebugDraw instance on the main thread // Needed to ensure the creation of the DebugDraw instance on the main thread
@ -254,6 +251,9 @@ void EntityScriptServer::handleEntityScriptCallMethodPacket(QSharedPointer<Recei
void EntityScriptServer::run() { void EntityScriptServer::run() {
DependencyManager::set<ScriptEngines>(ScriptEngine::ENTITY_SERVER_SCRIPT);
DependencyManager::set<EntityScriptServerServices>();
// make sure we request our script once the agent connects to the domain // make sure we request our script once the agent connects to the domain
auto nodeList = DependencyManager::get<NodeList>(); auto nodeList = DependencyManager::get<NodeList>();
@ -571,6 +571,8 @@ void EntityScriptServer::aboutToFinish() {
entityScriptingInterface->setPacketSender(nullptr); entityScriptingInterface->setPacketSender(nullptr);
} }
DependencyManager::destroy<AssignmentParentFinder>();
DependencyManager::get<ResourceManager>()->cleanup(); DependencyManager::get<ResourceManager>()->cleanup();
DependencyManager::destroy<PluginManager>(); DependencyManager::destroy<PluginManager>();

View file

@ -90,7 +90,7 @@ macro(SET_PACKAGING_PARAMETERS)
# for the second parent of HEAD (not HEAD) since that is the # for the second parent of HEAD (not HEAD) since that is the
# SHA of the commit merged to master for the build # SHA of the commit merged to master for the build
if (PR_BUILD) if (PR_BUILD)
set(_GIT_LOG_FORMAT "%p") set(_GIT_LOG_FORMAT "%p %h")
else () else ()
set(_GIT_LOG_FORMAT "%h") set(_GIT_LOG_FORMAT "%h")
endif () endif ()

View file

@ -412,7 +412,7 @@ SharedNodePointer DomainGatekeeper::processAgentConnectRequest(const NodeConnect
} else if (verifyUserSignature(username, usernameSignature, nodeConnection.senderSockAddr)) { } else if (verifyUserSignature(username, usernameSignature, nodeConnection.senderSockAddr)) {
// they sent us a username and the signature verifies it // they sent us a username and the signature verifies it
getGroupMemberships(username); getGroupMemberships(username);
verifiedUsername = username; verifiedUsername = username.toLower();
} else { } else {
// they sent us a username, but it didn't check out // they sent us a username, but it didn't check out
requestUserPublicKey(username); requestUserPublicKey(username);
@ -993,7 +993,7 @@ void DomainGatekeeper::getDomainOwnerFriendsListJSONCallback(QNetworkReply* requ
_domainOwnerFriends.clear(); _domainOwnerFriends.clear();
QJsonArray friends = jsonObject["data"].toObject()["friends"].toArray(); QJsonArray friends = jsonObject["data"].toObject()["friends"].toArray();
for (int i = 0; i < friends.size(); i++) { for (int i = 0; i < friends.size(); i++) {
_domainOwnerFriends += friends.at(i).toString(); _domainOwnerFriends += friends.at(i).toString().toLower();
} }
} else { } else {
qDebug() << "getDomainOwnerFriendsList api call returned:" << QJsonDocument(jsonObject).toJson(QJsonDocument::Compact); qDebug() << "getDomainOwnerFriendsList api call returned:" << QJsonDocument(jsonObject).toJson(QJsonDocument::Compact);

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 KiB

After

Width:  |  Height:  |  Size: 229 KiB

View file

@ -69,6 +69,7 @@ Item {
id: stack id: stack
initialItem: inputConfiguration initialItem: inputConfiguration
property alias messageVisible: imageMessageBox.visible property alias messageVisible: imageMessageBox.visible
property string selectedPlugin: ""
Rectangle { Rectangle {
id: inputConfiguration id: inputConfiguration
anchors { anchors {
@ -274,6 +275,8 @@ Item {
} else { } else {
box.label = ""; box.label = "";
} }
stack.selectedPlugin = selectedDevice;
} }
Timer { Timer {

View file

@ -28,6 +28,7 @@ Flickable {
onPluginNameChanged: { onPluginNameChanged: {
if (page !== null) { if (page !== null) {
page.pluginName = flick.pluginName; page.pluginName = flick.pluginName;
page.displayConfiguration();
} }
} }

View file

@ -89,6 +89,7 @@ StackView {
property bool keyboardEnabled: false property bool keyboardEnabled: false
property bool punctuationMode: false property bool punctuationMode: false
property bool keyboardRaised: false
width: parent.width width: parent.width
height: parent.height height: parent.height
@ -210,6 +211,8 @@ StackView {
QQC2.TextField { QQC2.TextField {
id: addressLine id: addressLine
focus: true
width: addressLineContainer.width - addressLineContainer.anchors.leftMargin - addressLineContainer.anchors.rightMargin; width: addressLineContainer.width - addressLineContainer.anchors.leftMargin - addressLineContainer.anchors.rightMargin;
anchors { anchors {
left: addressLineContainer.left; left: addressLineContainer.left;
@ -236,24 +239,20 @@ StackView {
color: hifi.colors.text color: hifi.colors.text
background: Item {} background: Item {}
QQC2.Label { }
T.TextField {
id: control
padding: 6 // numbers taken from Qt\5.9.2\Src\qtquickcontrols2\src\imports\controls\TextField.qml QQC2.Label {
leftPadding: padding + 4 font: addressLine.font
}
font: parent.font x: addressLine.x
y: addressLine.y
leftPadding: addressLine.leftPadding
topPadding: addressLine.topPadding
x: control.leftPadding text: addressLine.placeholderText2
y: control.topPadding verticalAlignment: "AlignVCenter"
color: 'gray'
text: parent.placeholderText2 visible: addressLine.text === ''
verticalAlignment: "AlignVCenter"
color: 'gray'
visible: parent.text === ''
}
} }
Rectangle { Rectangle {

View file

@ -2723,7 +2723,7 @@ void Application::initializeDisplayPlugins() {
setDisplayPlugin(defaultDisplayPlugin); setDisplayPlugin(defaultDisplayPlugin);
// Now set the desired plugin if it's not the same as the default plugin // Now set the desired plugin if it's not the same as the default plugin
if (!targetDisplayPlugin && (targetDisplayPlugin != defaultDisplayPlugin)) { if (targetDisplayPlugin && (targetDisplayPlugin != defaultDisplayPlugin)) {
setDisplayPlugin(targetDisplayPlugin); setDisplayPlugin(targetDisplayPlugin);
} }
@ -6998,7 +6998,9 @@ void Application::showAssetServerWidget(QString filePath) {
DependencyManager::get<OffscreenUi>()->show(url, "AssetServer", startUpload); DependencyManager::get<OffscreenUi>()->show(url, "AssetServer", startUpload);
} else { } else {
static const QUrl url("hifi/dialogs/TabletAssetServer.qml"); static const QUrl url("hifi/dialogs/TabletAssetServer.qml");
tablet->pushOntoStack(url); if (!tablet->isPathLoaded(url)) {
tablet->pushOntoStack(url);
}
} }
} }

View file

@ -256,8 +256,6 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView, addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::CenterPlayerInView,
0, true, qApp, SLOT(rotationModeChanged())); 0, true, qApp, SLOT(rotationModeChanged()));
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Overlays, 0, true);
// View > Enter First Person Mode in HMD // View > Enter First Person Mode in HMD
addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPersonHMD, 0, true); addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::FirstPersonHMD, 0, true);
@ -818,6 +816,9 @@ Menu::Menu() {
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::VerboseLogging, 0, false, addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::VerboseLogging, 0, false,
qApp, SLOT(updateVerboseLogging())); qApp, SLOT(updateVerboseLogging()));
// Developer > Show Overlays
addCheckableActionToQMenuAndActionHash(developerMenu, MenuOption::Overlays, 0, true);
#if 0 /// -------------- REMOVED FOR NOW -------------- #if 0 /// -------------- REMOVED FOR NOW --------------
addDisabledActionAndSeparator(navigateMenu, "History"); addDisabledActionAndSeparator(navigateMenu, "History");
QAction* backAction = addActionToQMenuAndActionHash(navigateMenu, MenuOption::Back, 0, addressManager.data(), SLOT(goBack())); QAction* backAction = addActionToQMenuAndActionHash(navigateMenu, MenuOption::Back, 0, addressManager.data(), SLOT(goBack()));

View file

@ -3348,7 +3348,7 @@ void MyAvatar::FollowHelper::prePhysicsUpdate(MyAvatar& myAvatar, const glm::mat
if (!isActive(Rotation) && (shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { if (!isActive(Rotation) && (shouldActivateRotation(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) {
activate(Rotation); activate(Rotation);
} }
if (!isActive(Horizontal) && shouldActivateHorizontal(myAvatar, desiredBodyMatrix, currentBodyMatrix)) { if (!isActive(Horizontal) && (shouldActivateHorizontal(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) {
activate(Horizontal); activate(Horizontal);
} }
if (!isActive(Vertical) && (shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) { if (!isActive(Vertical) && (shouldActivateVertical(myAvatar, desiredBodyMatrix, currentBodyMatrix) || hasDriveInput)) {

View file

@ -46,7 +46,7 @@ static AnimPose computeHipsInSensorFrame(MyAvatar* myAvatar, bool isFlying) {
} }
glm::mat4 hipsMat; glm::mat4 hipsMat;
if (myAvatar->getCenterOfGravityModelEnabled()) { if (myAvatar->getCenterOfGravityModelEnabled() && !isFlying) {
// then we use center of gravity model // then we use center of gravity model
hipsMat = myAvatar->deriveBodyUsingCgModel(); hipsMat = myAvatar->deriveBodyUsingCgModel();
} else { } else {
@ -109,6 +109,11 @@ void MySkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
AnimPose avatarToRigPose(glm::vec3(1.0f), Quaternions::Y_180, glm::vec3(0.0f)); AnimPose avatarToRigPose(glm::vec3(1.0f), Quaternions::Y_180, glm::vec3(0.0f));
glm::mat4 rigToAvatarMatrix = Matrices::Y_180;
glm::mat4 avatarToWorldMatrix = createMatFromQuatAndPos(myAvatar->getWorldOrientation(), myAvatar->getWorldPosition());
glm::mat4 sensorToWorldMatrix = myAvatar->getSensorToWorldMatrix();
params.rigToSensorMatrix = glm::inverse(sensorToWorldMatrix) * avatarToWorldMatrix * rigToAvatarMatrix;
// input action is the highest priority source for head orientation. // input action is the highest priority source for head orientation.
auto avatarHeadPose = myAvatar->getControllerPoseInAvatarFrame(controller::Action::HEAD); auto avatarHeadPose = myAvatar->getControllerPoseInAvatarFrame(controller::Action::HEAD);
if (avatarHeadPose.isValid()) { if (avatarHeadPose.isValid()) {

View file

@ -1244,7 +1244,8 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
bool leftArmEnabled, bool rightArmEnabled, float dt, bool leftArmEnabled, bool rightArmEnabled, float dt,
const AnimPose& leftHandPose, const AnimPose& rightHandPose, const AnimPose& leftHandPose, const AnimPose& rightHandPose,
const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo, const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo) { const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo,
const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix) {
const bool ENABLE_POLE_VECTORS = false; const bool ENABLE_POLE_VECTORS = false;
const float ELBOW_POLE_VECTOR_BLEND_FACTOR = 0.95f; const float ELBOW_POLE_VECTOR_BLEND_FACTOR = 0.95f;
@ -1271,19 +1272,20 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
int elbowJointIndex = _animSkeleton->nameToJointIndex("LeftForeArm"); int elbowJointIndex = _animSkeleton->nameToJointIndex("LeftForeArm");
if (ENABLE_POLE_VECTORS && !leftArmEnabled && handJointIndex >= 0 && armJointIndex >= 0 && elbowJointIndex >= 0) { if (ENABLE_POLE_VECTORS && !leftArmEnabled && handJointIndex >= 0 && armJointIndex >= 0 && elbowJointIndex >= 0) {
glm::vec3 poleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, hipsIndex, true); glm::vec3 poleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, hipsIndex, true);
glm::vec3 sensorPoleVector = transformVectorFast(rigToSensorMatrix, poleVector);
// smooth toward desired pole vector from previous pole vector... to reduce jitter // smooth toward desired pole vector from previous pole vector... to reduce jitter
if (!_prevLeftHandPoleVectorValid) { if (!_prevLeftHandPoleVectorValid) {
_prevLeftHandPoleVectorValid = true; _prevLeftHandPoleVectorValid = true;
_prevLeftHandPoleVector = poleVector; _prevLeftHandPoleVector = sensorPoleVector;
} }
glm::quat deltaRot = rotationBetween(_prevLeftHandPoleVector, poleVector); glm::quat deltaRot = rotationBetween(_prevLeftHandPoleVector, sensorPoleVector);
glm::quat smoothDeltaRot = safeMix(deltaRot, Quaternions::IDENTITY, ELBOW_POLE_VECTOR_BLEND_FACTOR); glm::quat smoothDeltaRot = safeMix(deltaRot, Quaternions::IDENTITY, ELBOW_POLE_VECTOR_BLEND_FACTOR);
_prevLeftHandPoleVector = smoothDeltaRot * _prevLeftHandPoleVector; _prevLeftHandPoleVector = smoothDeltaRot * _prevLeftHandPoleVector;
_animVars.set("leftHandPoleVectorEnabled", true); _animVars.set("leftHandPoleVectorEnabled", true);
_animVars.set("leftHandPoleReferenceVector", Vectors::UNIT_X); _animVars.set("leftHandPoleReferenceVector", Vectors::UNIT_X);
_animVars.set("leftHandPoleVector", _prevLeftHandPoleVector); _animVars.set("leftHandPoleVector", transformVectorFast(sensorToRigMatrix, _prevLeftHandPoleVector));
} else { } else {
_prevLeftHandPoleVectorValid = false; _prevLeftHandPoleVectorValid = false;
_animVars.set("leftHandPoleVectorEnabled", false); _animVars.set("leftHandPoleVectorEnabled", false);
@ -1318,19 +1320,20 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
int elbowJointIndex = _animSkeleton->nameToJointIndex("RightForeArm"); int elbowJointIndex = _animSkeleton->nameToJointIndex("RightForeArm");
if (ENABLE_POLE_VECTORS && !rightArmEnabled && handJointIndex >= 0 && armJointIndex >= 0 && elbowJointIndex >= 0) { if (ENABLE_POLE_VECTORS && !rightArmEnabled && handJointIndex >= 0 && armJointIndex >= 0 && elbowJointIndex >= 0) {
glm::vec3 poleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, hipsIndex, false); glm::vec3 poleVector = calculateElbowPoleVector(handJointIndex, elbowJointIndex, armJointIndex, hipsIndex, false);
glm::vec3 sensorPoleVector = transformVectorFast(rigToSensorMatrix, poleVector);
// smooth toward desired pole vector from previous pole vector... to reduce jitter // smooth toward desired pole vector from previous pole vector... to reduce jitter
if (!_prevRightHandPoleVectorValid) { if (!_prevRightHandPoleVectorValid) {
_prevRightHandPoleVectorValid = true; _prevRightHandPoleVectorValid = true;
_prevRightHandPoleVector = poleVector; _prevRightHandPoleVector = sensorPoleVector;
} }
glm::quat deltaRot = rotationBetween(_prevRightHandPoleVector, poleVector); glm::quat deltaRot = rotationBetween(_prevRightHandPoleVector, sensorPoleVector);
glm::quat smoothDeltaRot = safeMix(deltaRot, Quaternions::IDENTITY, ELBOW_POLE_VECTOR_BLEND_FACTOR); glm::quat smoothDeltaRot = safeMix(deltaRot, Quaternions::IDENTITY, ELBOW_POLE_VECTOR_BLEND_FACTOR);
_prevRightHandPoleVector = smoothDeltaRot * _prevRightHandPoleVector; _prevRightHandPoleVector = smoothDeltaRot * _prevRightHandPoleVector;
_animVars.set("rightHandPoleVectorEnabled", true); _animVars.set("rightHandPoleVectorEnabled", true);
_animVars.set("rightHandPoleReferenceVector", -Vectors::UNIT_X); _animVars.set("rightHandPoleReferenceVector", -Vectors::UNIT_X);
_animVars.set("rightHandPoleVector", _prevRightHandPoleVector); _animVars.set("rightHandPoleVector", transformVectorFast(sensorToRigMatrix, _prevRightHandPoleVector));
} else { } else {
_prevRightHandPoleVectorValid = false; _prevRightHandPoleVectorValid = false;
_animVars.set("rightHandPoleVectorEnabled", false); _animVars.set("rightHandPoleVectorEnabled", false);
@ -1345,7 +1348,8 @@ void Rig::updateHands(bool leftHandEnabled, bool rightHandEnabled, bool hipsEnab
} }
} }
void Rig::updateFeet(bool leftFootEnabled, bool rightFootEnabled, const AnimPose& leftFootPose, const AnimPose& rightFootPose) { void Rig::updateFeet(bool leftFootEnabled, bool rightFootEnabled, const AnimPose& leftFootPose, const AnimPose& rightFootPose,
const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix) {
const float KNEE_POLE_VECTOR_BLEND_FACTOR = 0.95f; const float KNEE_POLE_VECTOR_BLEND_FACTOR = 0.95f;
@ -1360,19 +1364,20 @@ void Rig::updateFeet(bool leftFootEnabled, bool rightFootEnabled, const AnimPose
int kneeJointIndex = _animSkeleton->nameToJointIndex("LeftLeg"); int kneeJointIndex = _animSkeleton->nameToJointIndex("LeftLeg");
int upLegJointIndex = _animSkeleton->nameToJointIndex("LeftUpLeg"); int upLegJointIndex = _animSkeleton->nameToJointIndex("LeftUpLeg");
glm::vec3 poleVector = calculateKneePoleVector(footJointIndex, kneeJointIndex, upLegJointIndex, hipsIndex, leftFootPose); glm::vec3 poleVector = calculateKneePoleVector(footJointIndex, kneeJointIndex, upLegJointIndex, hipsIndex, leftFootPose);
glm::vec3 sensorPoleVector = transformVectorFast(rigToSensorMatrix, poleVector);
// smooth toward desired pole vector from previous pole vector... to reduce jitter // smooth toward desired pole vector from previous pole vector... to reduce jitter, but in sensor space.
if (!_prevLeftFootPoleVectorValid) { if (!_prevLeftFootPoleVectorValid) {
_prevLeftFootPoleVectorValid = true; _prevLeftFootPoleVectorValid = true;
_prevLeftFootPoleVector = poleVector; _prevLeftFootPoleVector = sensorPoleVector;
} }
glm::quat deltaRot = rotationBetween(_prevLeftFootPoleVector, poleVector); glm::quat deltaRot = rotationBetween(_prevLeftFootPoleVector, sensorPoleVector);
glm::quat smoothDeltaRot = safeMix(deltaRot, Quaternions::IDENTITY, KNEE_POLE_VECTOR_BLEND_FACTOR); glm::quat smoothDeltaRot = safeMix(deltaRot, Quaternions::IDENTITY, KNEE_POLE_VECTOR_BLEND_FACTOR);
_prevLeftFootPoleVector = smoothDeltaRot * _prevLeftFootPoleVector; _prevLeftFootPoleVector = smoothDeltaRot * _prevLeftFootPoleVector;
_animVars.set("leftFootPoleVectorEnabled", true); _animVars.set("leftFootPoleVectorEnabled", true);
_animVars.set("leftFootPoleReferenceVector", Vectors::UNIT_Z); _animVars.set("leftFootPoleReferenceVector", Vectors::UNIT_Z);
_animVars.set("leftFootPoleVector", _prevLeftFootPoleVector); _animVars.set("leftFootPoleVector", transformVectorFast(sensorToRigMatrix, _prevLeftFootPoleVector));
} else { } else {
_animVars.unset("leftFootPosition"); _animVars.unset("leftFootPosition");
_animVars.unset("leftFootRotation"); _animVars.unset("leftFootRotation");
@ -1390,19 +1395,20 @@ void Rig::updateFeet(bool leftFootEnabled, bool rightFootEnabled, const AnimPose
int kneeJointIndex = _animSkeleton->nameToJointIndex("RightLeg"); int kneeJointIndex = _animSkeleton->nameToJointIndex("RightLeg");
int upLegJointIndex = _animSkeleton->nameToJointIndex("RightUpLeg"); int upLegJointIndex = _animSkeleton->nameToJointIndex("RightUpLeg");
glm::vec3 poleVector = calculateKneePoleVector(footJointIndex, kneeJointIndex, upLegJointIndex, hipsIndex, rightFootPose); glm::vec3 poleVector = calculateKneePoleVector(footJointIndex, kneeJointIndex, upLegJointIndex, hipsIndex, rightFootPose);
glm::vec3 sensorPoleVector = transformVectorFast(rigToSensorMatrix, poleVector);
// smooth toward desired pole vector from previous pole vector... to reduce jitter // smooth toward desired pole vector from previous pole vector... to reduce jitter
if (!_prevRightFootPoleVectorValid) { if (!_prevRightFootPoleVectorValid) {
_prevRightFootPoleVectorValid = true; _prevRightFootPoleVectorValid = true;
_prevRightFootPoleVector = poleVector; _prevRightFootPoleVector = sensorPoleVector;
} }
glm::quat deltaRot = rotationBetween(_prevRightFootPoleVector, poleVector); glm::quat deltaRot = rotationBetween(_prevRightFootPoleVector, sensorPoleVector);
glm::quat smoothDeltaRot = safeMix(deltaRot, Quaternions::IDENTITY, KNEE_POLE_VECTOR_BLEND_FACTOR); glm::quat smoothDeltaRot = safeMix(deltaRot, Quaternions::IDENTITY, KNEE_POLE_VECTOR_BLEND_FACTOR);
_prevRightFootPoleVector = smoothDeltaRot * _prevRightFootPoleVector; _prevRightFootPoleVector = smoothDeltaRot * _prevRightFootPoleVector;
_animVars.set("rightFootPoleVectorEnabled", true); _animVars.set("rightFootPoleVectorEnabled", true);
_animVars.set("rightFootPoleReferenceVector", Vectors::UNIT_Z); _animVars.set("rightFootPoleReferenceVector", Vectors::UNIT_Z);
_animVars.set("rightFootPoleVector", _prevRightFootPoleVector); _animVars.set("rightFootPoleVector", transformVectorFast(sensorToRigMatrix, _prevRightFootPoleVector));
} else { } else {
_animVars.unset("rightFootPosition"); _animVars.unset("rightFootPosition");
_animVars.unset("rightFootRotation"); _animVars.unset("rightFootRotation");
@ -1434,9 +1440,9 @@ void Rig::updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm
glm::quat deltaQuat = desiredQuat * glm::inverse(headQuat); glm::quat deltaQuat = desiredQuat * glm::inverse(headQuat);
// limit swing rotation of the deltaQuat by a 30 degree cone. // limit swing rotation of the deltaQuat by a 25 degree cone.
// TODO: use swing twist decomposition constraint instead, for off axis rotation clamping. // TODO: use swing twist decomposition constraint instead, for off axis rotation clamping.
const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE; const float MAX_ANGLE = 25.0f * RADIANS_PER_DEGREE;
if (fabsf(glm::angle(deltaQuat)) > MAX_ANGLE) { if (fabsf(glm::angle(deltaQuat)) > MAX_ANGLE) {
deltaQuat = glm::angleAxis(glm::clamp(glm::angle(deltaQuat), -MAX_ANGLE, MAX_ANGLE), glm::axis(deltaQuat)); deltaQuat = glm::angleAxis(glm::clamp(glm::angle(deltaQuat), -MAX_ANGLE, MAX_ANGLE), glm::axis(deltaQuat));
} }
@ -1546,16 +1552,18 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo
bool spine2Enabled = params.primaryControllerFlags[PrimaryControllerType_Spine2] & (uint8_t)ControllerFlags::Enabled; bool spine2Enabled = params.primaryControllerFlags[PrimaryControllerType_Spine2] & (uint8_t)ControllerFlags::Enabled;
bool leftArmEnabled = params.secondaryControllerFlags[SecondaryControllerType_LeftArm] & (uint8_t)ControllerFlags::Enabled; bool leftArmEnabled = params.secondaryControllerFlags[SecondaryControllerType_LeftArm] & (uint8_t)ControllerFlags::Enabled;
bool rightArmEnabled = params.secondaryControllerFlags[SecondaryControllerType_RightArm] & (uint8_t)ControllerFlags::Enabled; bool rightArmEnabled = params.secondaryControllerFlags[SecondaryControllerType_RightArm] & (uint8_t)ControllerFlags::Enabled;
glm::mat4 sensorToRigMatrix = glm::inverse(params.rigToSensorMatrix);
updateHead(headEnabled, hipsEnabled, params.primaryControllerPoses[PrimaryControllerType_Head]); updateHead(headEnabled, hipsEnabled, params.primaryControllerPoses[PrimaryControllerType_Head]);
updateHands(leftHandEnabled, rightHandEnabled, hipsEnabled, hipsEstimated, leftArmEnabled, rightArmEnabled, dt, updateHands(leftHandEnabled, rightHandEnabled, hipsEnabled, hipsEstimated, leftArmEnabled, rightArmEnabled, dt,
params.primaryControllerPoses[PrimaryControllerType_LeftHand], params.primaryControllerPoses[PrimaryControllerType_RightHand], params.primaryControllerPoses[PrimaryControllerType_LeftHand], params.primaryControllerPoses[PrimaryControllerType_RightHand],
params.hipsShapeInfo, params.spineShapeInfo, params.spine1ShapeInfo, params.spine2ShapeInfo); params.hipsShapeInfo, params.spineShapeInfo, params.spine1ShapeInfo, params.spine2ShapeInfo,
params.rigToSensorMatrix, sensorToRigMatrix);
updateFeet(leftFootEnabled, rightFootEnabled, updateFeet(leftFootEnabled, rightFootEnabled,
params.primaryControllerPoses[PrimaryControllerType_LeftFoot], params.primaryControllerPoses[PrimaryControllerType_RightFoot]); params.primaryControllerPoses[PrimaryControllerType_LeftFoot], params.primaryControllerPoses[PrimaryControllerType_RightFoot],
params.rigToSensorMatrix, sensorToRigMatrix);
if (headEnabled) { if (headEnabled) {
// Blend IK chains toward the joint limit centers, this should stablize head and hand ik. // Blend IK chains toward the joint limit centers, this should stablize head and hand ik.

View file

@ -75,6 +75,7 @@ public:
}; };
struct ControllerParameters { struct ControllerParameters {
glm::mat4 rigToSensorMatrix;
AnimPose primaryControllerPoses[NumPrimaryControllerTypes]; // rig space AnimPose primaryControllerPoses[NumPrimaryControllerTypes]; // rig space
uint8_t primaryControllerFlags[NumPrimaryControllerTypes]; uint8_t primaryControllerFlags[NumPrimaryControllerTypes];
AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space AnimPose secondaryControllerPoses[NumSecondaryControllerTypes]; // rig space
@ -231,8 +232,10 @@ protected:
bool leftArmEnabled, bool rightArmEnabled, float dt, bool leftArmEnabled, bool rightArmEnabled, float dt,
const AnimPose& leftHandPose, const AnimPose& rightHandPose, const AnimPose& leftHandPose, const AnimPose& rightHandPose,
const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo, const FBXJointShapeInfo& hipsShapeInfo, const FBXJointShapeInfo& spineShapeInfo,
const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo); const FBXJointShapeInfo& spine1ShapeInfo, const FBXJointShapeInfo& spine2ShapeInfo,
void updateFeet(bool leftFootEnabled, bool rightFootEnabled, const AnimPose& leftFootPose, const AnimPose& rightFootPose); const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix);
void updateFeet(bool leftFootEnabled, bool rightFootEnabled, const AnimPose& leftFootPose, const AnimPose& rightFootPose,
const glm::mat4& rigToSensorMatrix, const glm::mat4& sensorToRigMatrix);
void updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::vec3& lookAt, const glm::vec3& saccade); void updateEyeJoint(int index, const glm::vec3& modelTranslation, const glm::quat& modelRotation, const glm::vec3& lookAt, const glm::vec3& saccade);
void calcAnimAlpha(float speed, const std::vector<float>& referenceSpeeds, float* alphaOut) const; void calcAnimAlpha(float speed, const std::vector<float>& referenceSpeeds, float* alphaOut) const;
@ -359,16 +362,16 @@ protected:
int _nextStateHandlerId { 0 }; int _nextStateHandlerId { 0 };
QMutex _stateMutex; QMutex _stateMutex;
glm::vec3 _prevRightFootPoleVector { Vectors::UNIT_Z }; glm::vec3 _prevRightFootPoleVector { Vectors::UNIT_Z }; // sensor space
bool _prevRightFootPoleVectorValid { false }; bool _prevRightFootPoleVectorValid { false };
glm::vec3 _prevLeftFootPoleVector { Vectors::UNIT_Z }; glm::vec3 _prevLeftFootPoleVector { Vectors::UNIT_Z }; // sensor space
bool _prevLeftFootPoleVectorValid { false }; bool _prevLeftFootPoleVectorValid { false };
glm::vec3 _prevRightHandPoleVector { -Vectors::UNIT_Z }; glm::vec3 _prevRightHandPoleVector { -Vectors::UNIT_Z }; // sensor space
bool _prevRightHandPoleVectorValid { false }; bool _prevRightHandPoleVectorValid { false };
glm::vec3 _prevLeftHandPoleVector { -Vectors::UNIT_Z }; glm::vec3 _prevLeftHandPoleVector { -Vectors::UNIT_Z }; // sensor space
bool _prevLeftHandPoleVectorValid { false }; bool _prevLeftHandPoleVectorValid { false };
int _rigId; int _rigId;

View file

@ -220,30 +220,44 @@ void Head::calculateMouthShapes(float deltaTime) {
void Head::applyEyelidOffset(glm::quat headOrientation) { void Head::applyEyelidOffset(glm::quat headOrientation) {
// Adjusts the eyelid blendshape coefficients so that the eyelid follows the iris as the head pitches. // Adjusts the eyelid blendshape coefficients so that the eyelid follows the iris as the head pitches.
bool isBlinking = (_rightEyeBlinkVelocity != 0.0f && _rightEyeBlinkVelocity != 0.0f);
if (disableEyelidAdjustment) { if (disableEyelidAdjustment || isBlinking) {
return; return;
} }
glm::quat eyeRotation = rotationBetween(headOrientation * IDENTITY_FORWARD, getLookAtPosition() - _eyePosition); const float EYE_PITCH_TO_COEFFICIENT = 3.5f; // Empirically determined
eyeRotation = eyeRotation * glm::angleAxis(safeEulerAngles(headOrientation).y, IDENTITY_UP); // Rotation w.r.t. head const float MAX_EYELID_OFFSET = 1.5f;
float eyePitch = safeEulerAngles(eyeRotation).x; const float BLINK_DOWN_MULTIPLIER = 0.25f;
const float OPEN_DOWN_MULTIPLIER = 0.3f;
const float BROW_UP_MULTIPLIER = 0.5f;
const float EYE_PITCH_TO_COEFFICIENT = 1.6f; // Empirically determined glm::vec3 lookAt = glm::normalize(getLookAtPosition() - _eyePosition);
const float MAX_EYELID_OFFSET = 0.8f; // So that don't fully close eyes when looking way down glm::vec3 headUp = headOrientation * Vectors::UNIT_Y;
float eyelidOffset = glm::clamp(-eyePitch * EYE_PITCH_TO_COEFFICIENT, -1.0f, MAX_EYELID_OFFSET); float eyePitch = (PI / 2.0f) - acos(glm::dot(lookAt, headUp));
float eyelidOffset = glm::clamp(abs(eyePitch * EYE_PITCH_TO_COEFFICIENT), 0.0f, MAX_EYELID_OFFSET);
for (int i = 0; i < 2; i++) { float blinkUpCoefficient = -eyelidOffset;
const int LEFT_EYE = 8; float blinkDownCoefficient = BLINK_DOWN_MULTIPLIER * eyelidOffset;
float eyeCoefficient = _transientBlendshapeCoefficients[i] - _transientBlendshapeCoefficients[LEFT_EYE + i];
eyeCoefficient = glm::clamp(eyelidOffset + eyeCoefficient * (1.0f - eyelidOffset), -1.0f, 1.0f); float openUpCoefficient = eyelidOffset;
if (eyeCoefficient > 0.0f) { float openDownCoefficient = OPEN_DOWN_MULTIPLIER * eyelidOffset;
_transientBlendshapeCoefficients[i] = eyeCoefficient;
_transientBlendshapeCoefficients[LEFT_EYE + i] = 0.0f; float browsUpCoefficient = BROW_UP_MULTIPLIER * eyelidOffset;
float browsDownCoefficient = 0.0f;
} else { bool isLookingUp = (eyePitch > 0);
_transientBlendshapeCoefficients[i] = 0.0f;
_transientBlendshapeCoefficients[LEFT_EYE + i] = -eyeCoefficient; if (isLookingUp) {
for (int i = 0; i < 2; i++) {
_transientBlendshapeCoefficients[EYE_BLINK_INDICES[i]] = blinkUpCoefficient;
_transientBlendshapeCoefficients[EYE_OPEN_INDICES[i]] = openUpCoefficient;
_transientBlendshapeCoefficients[BROWS_U_INDICES[i]] = browsUpCoefficient;
}
} else {
for (int i = 0; i < 2; i++) {
_transientBlendshapeCoefficients[EYE_BLINK_INDICES[i]] = blinkDownCoefficient;
_transientBlendshapeCoefficients[EYE_OPEN_INDICES[i]] = openDownCoefficient;
_transientBlendshapeCoefficients[BROWS_U_INDICES[i]] = browsDownCoefficient;
} }
} }
} }

View file

@ -17,7 +17,6 @@
#include <QtCore/QJsonArray> #include <QtCore/QJsonArray>
#include <QVector> #include <QVector>
#include <FaceshiftConstants.h>
#include <GLMHelpers.h> #include <GLMHelpers.h>
#include <shared/JSONHelpers.h> #include <shared/JSONHelpers.h>
@ -33,7 +32,7 @@ HeadData::HeadData(AvatarData* owningAvatar) :
_summedBlendshapeCoefficients(QVector<float>(0, 0.0f)), _summedBlendshapeCoefficients(QVector<float>(0, 0.0f)),
_owningAvatar(owningAvatar) _owningAvatar(owningAvatar)
{ {
computeBlendshapesLookupMap();
} }
glm::quat HeadData::getRawOrientation() const { glm::quat HeadData::getRawOrientation() const {
@ -71,16 +70,10 @@ void HeadData::setOrientation(const glm::quat& orientation) {
setHeadOrientation(orientation); setHeadOrientation(orientation);
} }
//Lazily construct a lookup map from the blendshapes void HeadData::computeBlendshapesLookupMap(){
static const QMap<QString, int>& getBlendshapesLookupMap() { for (int i = 0; i < NUM_FACESHIFT_BLENDSHAPES; i++) {
static std::once_flag once; _blendshapeLookupMap[FACESHIFT_BLENDSHAPES[i]] = i;
static QMap<QString, int> blendshapeLookupMap; }
std::call_once(once, [&] {
for (int i = 0; i < NUM_FACESHIFT_BLENDSHAPES; i++) {
blendshapeLookupMap[FACESHIFT_BLENDSHAPES[i]] = i;
}
});
return blendshapeLookupMap;
} }
int HeadData::getNumSummedBlendshapeCoefficients() const { int HeadData::getNumSummedBlendshapeCoefficients() const {
@ -108,11 +101,10 @@ const QVector<float>& HeadData::getSummedBlendshapeCoefficients() {
} }
void HeadData::setBlendshape(QString name, float val) { void HeadData::setBlendshape(QString name, float val) {
const auto& blendshapeLookupMap = getBlendshapesLookupMap();
//Check to see if the named blendshape exists, and then set its value if it does //Check to see if the named blendshape exists, and then set its value if it does
auto it = blendshapeLookupMap.find(name); auto it = _blendshapeLookupMap.find(name);
if (it != blendshapeLookupMap.end()) { if (it != _blendshapeLookupMap.end()) {
if (_blendshapeCoefficients.size() <= it.value()) { if (_blendshapeCoefficients.size() <= it.value()) {
_blendshapeCoefficients.resize(it.value() + 1); _blendshapeCoefficients.resize(it.value() + 1);
} }
@ -123,6 +115,18 @@ void HeadData::setBlendshape(QString name, float val) {
} }
} }
int HeadData::getBlendshapeIndex(const QString& name) {
auto it = _blendshapeLookupMap.find(name);
int index = it != _blendshapeLookupMap.end() ? it.value() : -1;
return index;
}
void HeadData::getBlendshapeIndices(const std::vector<QString>& blendShapeNames, std::vector<int>& indexes) {
for (auto& name : blendShapeNames) {
indexes.push_back(getBlendshapeIndex(name));
}
}
static const QString JSON_AVATAR_HEAD_ROTATION = QStringLiteral("rotation"); static const QString JSON_AVATAR_HEAD_ROTATION = QStringLiteral("rotation");
static const QString JSON_AVATAR_HEAD_BLENDSHAPE_COEFFICIENTS = QStringLiteral("blendShapes"); static const QString JSON_AVATAR_HEAD_BLENDSHAPE_COEFFICIENTS = QStringLiteral("blendShapes");
static const QString JSON_AVATAR_HEAD_LEAN_FORWARD = QStringLiteral("leanForward"); static const QString JSON_AVATAR_HEAD_LEAN_FORWARD = QStringLiteral("leanForward");
@ -131,10 +135,9 @@ static const QString JSON_AVATAR_HEAD_LOOKAT = QStringLiteral("lookAt");
QJsonObject HeadData::toJson() const { QJsonObject HeadData::toJson() const {
QJsonObject headJson; QJsonObject headJson;
const auto& blendshapeLookupMap = getBlendshapesLookupMap();
QJsonObject blendshapesJson; QJsonObject blendshapesJson;
for (auto name : blendshapeLookupMap.keys()) { for (auto name : _blendshapeLookupMap.keys()) {
auto index = blendshapeLookupMap[name]; auto index = _blendshapeLookupMap[name];
float value = 0.0f; float value = 0.0f;
if (index < _blendshapeCoefficients.size()) { if (index < _blendshapeCoefficients.size()) {
value += _blendshapeCoefficients[index]; value += _blendshapeCoefficients[index];

View file

@ -20,6 +20,7 @@
#include <glm/gtc/quaternion.hpp> #include <glm/gtc/quaternion.hpp>
#include <SharedUtil.h> #include <SharedUtil.h>
#include <FaceshiftConstants.h>
// degrees // degrees
const float MIN_HEAD_YAW = -180.0f; const float MIN_HEAD_YAW = -180.0f;
@ -55,6 +56,8 @@ public:
void setOrientation(const glm::quat& orientation); void setOrientation(const glm::quat& orientation);
void setBlendshape(QString name, float val); void setBlendshape(QString name, float val);
int getBlendshapeIndex(const QString& name);
void getBlendshapeIndices(const std::vector<QString>& blendShapeNames, std::vector<int>& indexes);
const QVector<float>& getBlendshapeCoefficients() const { return _blendshapeCoefficients; } const QVector<float>& getBlendshapeCoefficients() const { return _blendshapeCoefficients; }
const QVector<float>& getSummedBlendshapeCoefficients(); const QVector<float>& getSummedBlendshapeCoefficients();
int getNumSummedBlendshapeCoefficients() const; int getNumSummedBlendshapeCoefficients() const;
@ -114,6 +117,7 @@ protected:
QVector<float> _blendshapeCoefficients; QVector<float> _blendshapeCoefficients;
QVector<float> _transientBlendshapeCoefficients; QVector<float> _transientBlendshapeCoefficients;
QVector<float> _summedBlendshapeCoefficients; QVector<float> _summedBlendshapeCoefficients;
QMap<QString, int> _blendshapeLookupMap;
AvatarData* _owningAvatar; AvatarData* _owningAvatar;
private: private:
@ -122,6 +126,7 @@ private:
HeadData& operator= (const HeadData&); HeadData& operator= (const HeadData&);
void setHeadOrientation(const glm::quat& orientation); void setHeadOrientation(const glm::quat& orientation);
void computeBlendshapesLookupMap();
}; };
#endif // hifi_HeadData_h #endif // hifi_HeadData_h

View file

@ -100,7 +100,7 @@ void SimpleEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
} }
} else if (entity->isMovingRelativeToParent()) { } else if (entity->isMovingRelativeToParent()) {
SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity);
if (itr != _simpleKinematicEntities.end()) { if (itr == _simpleKinematicEntities.end()) {
_simpleKinematicEntities.insert(entity); _simpleKinematicEntities.insert(entity);
entity->setLastSimulated(usecTimestampNow()); entity->setLastSimulated(usecTimestampNow());
} }
@ -118,7 +118,7 @@ void SimpleEntitySimulation::changeEntityInternal(EntityItemPointer entity) {
if (entity->isMovingRelativeToParent()) { if (entity->isMovingRelativeToParent()) {
SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity); SetOfEntities::iterator itr = _simpleKinematicEntities.find(entity);
if (itr != _simpleKinematicEntities.end()) { if (itr == _simpleKinematicEntities.end()) {
_simpleKinematicEntities.insert(entity); _simpleKinematicEntities.insert(entity);
entity->setLastSimulated(usecTimestampNow()); entity->setLastSimulated(usecTimestampNow());
} }

View file

@ -48,12 +48,12 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
return; return;
} }
// check the program cache // check the program cache
// pick the program version // pick the program version
// check the program cache // check the program cache
// pick the program version // pick the program version
#ifdef GPU_STEREO_CAMERA_BUFFER #ifdef GPU_STEREO_CAMERA_BUFFER
GLuint glprogram = pipelineObject->_program->getProgram((GLShader::Version) isStereo()); GLuint glprogram = pipelineObject->_program->getProgram((GLShader::Version)isStereo());
#else #else
GLuint glprogram = pipelineObject->_program->getProgram(); GLuint glprogram = pipelineObject->_program->getProgram();
#endif #endif
@ -85,10 +85,11 @@ void GLBackend::do_setPipeline(const Batch& batch, size_t paramOffset) {
} else { } else {
cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBufferIdentity._buffer); cameraCorrectionBuffer = syncGPUObject(*_pipeline._cameraCorrectionBufferIdentity._buffer);
} }
// Invalidate uniform buffer cache slot
_uniform._buffers[_pipeline._cameraCorrectionLocation].reset();
glBindBufferRange(GL_UNIFORM_BUFFER, _pipeline._cameraCorrectionLocation, cameraCorrectionBuffer->_id, 0, sizeof(CameraCorrection)); glBindBufferRange(GL_UNIFORM_BUFFER, _pipeline._cameraCorrectionLocation, cameraCorrectionBuffer->_id, 0, sizeof(CameraCorrection));
} }
(void) CHECK_GL_ERROR(); (void)CHECK_GL_ERROR();
_pipeline._invalidProgram = false; _pipeline._invalidProgram = false;
} }
} }
@ -97,7 +98,7 @@ void GLBackend::updatePipeline() {
if (_pipeline._invalidProgram) { if (_pipeline._invalidProgram) {
// doing it here is aproblem for calls to glUniform.... so will do it on assing... // doing it here is aproblem for calls to glUniform.... so will do it on assing...
glUseProgram(_pipeline._program); glUseProgram(_pipeline._program);
(void) CHECK_GL_ERROR(); (void)CHECK_GL_ERROR();
_pipeline._invalidProgram = false; _pipeline._invalidProgram = false;
} }
@ -106,12 +107,12 @@ void GLBackend::updatePipeline() {
// first reset to default what should be // first reset to default what should be
// the fields which were not to default and are default now // the fields which were not to default and are default now
resetPipelineState(_pipeline._state->_signature); resetPipelineState(_pipeline._state->_signature);
// Update the signature cache with what's going to be touched // Update the signature cache with what's going to be touched
_pipeline._stateSignatureCache |= _pipeline._state->_signature; _pipeline._stateSignatureCache |= _pipeline._state->_signature;
// And perform // And perform
for (auto command: _pipeline._state->_commands) { for (auto command : _pipeline._state->_commands) {
command->run(this); command->run(this);
} }
} else { } else {
@ -142,8 +143,8 @@ void GLBackend::releaseUniformBuffer(uint32_t slot) {
if (buf) { if (buf) {
auto* object = Backend::getGPUObject<GLBuffer>(*buf); auto* object = Backend::getGPUObject<GLBuffer>(*buf);
if (object) { if (object) {
glBindBufferBase(GL_UNIFORM_BUFFER, slot, 0); // RELEASE glBindBufferBase(GL_UNIFORM_BUFFER, slot, 0); // RELEASE
(void) CHECK_GL_ERROR(); (void)CHECK_GL_ERROR();
} }
buf.reset(); buf.reset();
} }
@ -157,8 +158,9 @@ void GLBackend::resetUniformStage() {
void GLBackend::do_setUniformBuffer(const Batch& batch, size_t paramOffset) { void GLBackend::do_setUniformBuffer(const Batch& batch, size_t paramOffset) {
GLuint slot = batch._params[paramOffset + 3]._uint; GLuint slot = batch._params[paramOffset + 3]._uint;
if (slot >(GLuint)MAX_NUM_UNIFORM_BUFFERS) { if (slot > (GLuint)MAX_NUM_UNIFORM_BUFFERS) {
qCDebug(gpugllogging) << "GLBackend::do_setUniformBuffer: Trying to set a uniform Buffer at slot #" << slot << " which doesn't exist. MaxNumUniformBuffers = " << getMaxNumUniformBuffers(); qCDebug(gpugllogging) << "GLBackend::do_setUniformBuffer: Trying to set a uniform Buffer at slot #" << slot
<< " which doesn't exist. MaxNumUniformBuffers = " << getMaxNumUniformBuffers();
return; return;
} }
BufferPointer uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); BufferPointer uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint);
@ -169,7 +171,7 @@ void GLBackend::do_setUniformBuffer(const Batch& batch, size_t paramOffset) {
releaseUniformBuffer(slot); releaseUniformBuffer(slot);
return; return;
} }
// check cache before thinking // check cache before thinking
if (_uniform._buffers[slot] == uniformBuffer) { if (_uniform._buffers[slot] == uniformBuffer) {
return; return;
@ -181,7 +183,7 @@ void GLBackend::do_setUniformBuffer(const Batch& batch, size_t paramOffset) {
glBindBufferRange(GL_UNIFORM_BUFFER, slot, object->_buffer, rangeStart, rangeSize); glBindBufferRange(GL_UNIFORM_BUFFER, slot, object->_buffer, rangeStart, rangeSize);
_uniform._buffers[slot] = uniformBuffer; _uniform._buffers[slot] = uniformBuffer;
(void) CHECK_GL_ERROR(); (void)CHECK_GL_ERROR();
} else { } else {
releaseUniformBuffer(slot); releaseUniformBuffer(slot);
return; return;
@ -195,8 +197,8 @@ void GLBackend::releaseResourceTexture(uint32_t slot) {
if (object) { if (object) {
GLuint target = object->_target; GLuint target = object->_target;
glActiveTexture(GL_TEXTURE0 + slot); glActiveTexture(GL_TEXTURE0 + slot);
glBindTexture(target, 0); // RELEASE glBindTexture(target, 0); // RELEASE
(void) CHECK_GL_ERROR(); (void)CHECK_GL_ERROR();
} }
tex.reset(); tex.reset();
} }
@ -212,11 +214,11 @@ void GLBackend::resetResourceStage() {
} }
} }
void GLBackend::do_setResourceBuffer(const Batch& batch, size_t paramOffset) { void GLBackend::do_setResourceBuffer(const Batch& batch, size_t paramOffset) {
GLuint slot = batch._params[paramOffset + 1]._uint; GLuint slot = batch._params[paramOffset + 1]._uint;
if (slot >= (GLuint)MAX_NUM_RESOURCE_BUFFERS) { if (slot >= (GLuint)MAX_NUM_RESOURCE_BUFFERS) {
qCDebug(gpugllogging) << "GLBackend::do_setResourceBuffer: Trying to set a resource Buffer at slot #" << slot << " which doesn't exist. MaxNumResourceBuffers = " << getMaxNumResourceBuffers(); qCDebug(gpugllogging) << "GLBackend::do_setResourceBuffer: Trying to set a resource Buffer at slot #" << slot
<< " which doesn't exist. MaxNumResourceBuffers = " << getMaxNumResourceBuffers();
return; return;
} }
@ -237,7 +239,7 @@ void GLBackend::do_setResourceBuffer(const Batch& batch, size_t paramOffset) {
// If successful bind then cache it // If successful bind then cache it
if (bindResourceBuffer(slot, resourceBuffer)) { if (bindResourceBuffer(slot, resourceBuffer)) {
_resource._buffers[slot] = resourceBuffer; _resource._buffers[slot] = resourceBuffer;
} else { // else clear slot and cache } else { // else clear slot and cache
releaseResourceBuffer(slot); releaseResourceBuffer(slot);
return; return;
} }
@ -245,8 +247,9 @@ void GLBackend::do_setResourceBuffer(const Batch& batch, size_t paramOffset) {
void GLBackend::do_setResourceTexture(const Batch& batch, size_t paramOffset) { void GLBackend::do_setResourceTexture(const Batch& batch, size_t paramOffset) {
GLuint slot = batch._params[paramOffset + 1]._uint; GLuint slot = batch._params[paramOffset + 1]._uint;
if (slot >= (GLuint) MAX_NUM_RESOURCE_TEXTURES) { if (slot >= (GLuint)MAX_NUM_RESOURCE_TEXTURES) {
qCDebug(gpugllogging) << "GLBackend::do_setResourceTexture: Trying to set a resource Texture at slot #" << slot << " which doesn't exist. MaxNumResourceTextures = " << getMaxNumResourceTextures(); qCDebug(gpugllogging) << "GLBackend::do_setResourceTexture: Trying to set a resource Texture at slot #" << slot
<< " which doesn't exist. MaxNumResourceTextures = " << getMaxNumResourceTextures();
return; return;
} }
@ -265,11 +268,14 @@ void GLBackend::bindResourceTexture(uint32_t slot, const TexturePointer& resourc
void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, size_t paramOffset) { void GLBackend::do_setResourceFramebufferSwapChainTexture(const Batch& batch, size_t paramOffset) {
GLuint slot = batch._params[paramOffset + 1]._uint; GLuint slot = batch._params[paramOffset + 1]._uint;
if (slot >= (GLuint)MAX_NUM_RESOURCE_TEXTURES) { if (slot >= (GLuint)MAX_NUM_RESOURCE_TEXTURES) {
qCDebug(gpugllogging) << "GLBackend::do_setResourceFramebufferSwapChainTexture: Trying to set a resource Texture at slot #" << slot << " which doesn't exist. MaxNumResourceTextures = " << getMaxNumResourceTextures(); qCDebug(gpugllogging)
<< "GLBackend::do_setResourceFramebufferSwapChainTexture: Trying to set a resource Texture at slot #" << slot
<< " which doesn't exist. MaxNumResourceTextures = " << getMaxNumResourceTextures();
return; return;
} }
auto swapChain = std::static_pointer_cast<FramebufferSwapChain>(batch._swapChains.get(batch._params[paramOffset + 0]._uint)); auto swapChain =
std::static_pointer_cast<FramebufferSwapChain>(batch._swapChains.get(batch._params[paramOffset + 0]._uint));
if (!swapChain) { if (!swapChain) {
releaseResourceTexture(slot); releaseResourceTexture(slot);

View file

@ -168,7 +168,9 @@ void GLBackend::TransformStageState::update(size_t commandIndex, const StereoSta
void GLBackend::TransformStageState::bindCurrentCamera(int eye) const { void GLBackend::TransformStageState::bindCurrentCamera(int eye) const {
if (_currentCameraOffset != INVALID_OFFSET) { if (_currentCameraOffset != INVALID_OFFSET) {
glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _cameraBuffer, _currentCameraOffset + eye * _cameraUboSize, sizeof(CameraBufferElement)); static_assert(TRANSFORM_CAMERA_SLOT >= MAX_NUM_UNIFORM_BUFFERS, "TransformCamera may overlap pipeline uniform buffer slots. Invalidate uniform buffer slot cache for safety (call _uniform._buffers[TRANSFORM_CAMERA_SLOT].reset()).");
glBindBufferRange(GL_UNIFORM_BUFFER, TRANSFORM_CAMERA_SLOT, _cameraBuffer, _currentCameraOffset + eye * _cameraUboSize,
sizeof(CameraBufferElement));
} }
} }

View file

@ -475,13 +475,16 @@ void DomainHandler::processDomainServerConnectionDeniedPacket(QSharedPointer<Rec
} }
} }
void DomainHandler::sentCheckInPacket() { bool DomainHandler::checkInPacketTimeout() {
++_checkInPacketsSinceLastReply; ++_checkInPacketsSinceLastReply;
if (_checkInPacketsSinceLastReply >= MAX_SILENT_DOMAIN_SERVER_CHECK_INS) { if (_checkInPacketsSinceLastReply > MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
// we haven't heard back from DS in MAX_SILENT_DOMAIN_SERVER_CHECK_INS // we haven't heard back from DS in MAX_SILENT_DOMAIN_SERVER_CHECK_INS
// so emit our signal that says that // so emit our signal that says that
qCDebug(networking) << "Limit of silent domain checkins reached"; qCDebug(networking) << "Limit of silent domain checkins reached";
emit limitOfSilentDomainCheckInsReached(); emit limitOfSilentDomainCheckInsReached();
return true;
} else {
return false;
} }
} }

View file

@ -96,7 +96,7 @@ public:
void softReset(); void softReset();
int getCheckInPacketsSinceLastReply() const { return _checkInPacketsSinceLastReply; } int getCheckInPacketsSinceLastReply() const { return _checkInPacketsSinceLastReply; }
void sentCheckInPacket(); bool checkInPacketTimeout();
void clearPendingCheckins() { _checkInPacketsSinceLastReply = 0; } void clearPendingCheckins() { _checkInPacketsSinceLastReply = 0; }
/**jsdoc /**jsdoc

View file

@ -199,7 +199,9 @@ void NLPacket::readVersion() {
} }
void NLPacket::readSourceID() { void NLPacket::readSourceID() {
if (!PacketTypeEnum::getNonSourcedPackets().contains(_type)) { if (PacketTypeEnum::getNonSourcedPackets().contains(_type)) {
_sourceID = NULL_LOCAL_ID;
} else {
_sourceID = sourceIDInHeader(*this); _sourceID = sourceIDInHeader(*this);
} }
} }

View file

@ -305,7 +305,8 @@ void NodeList::sendDomainServerCheckIn() {
} else if (_domainHandler.getIP().isNull() && _domainHandler.requiresICE()) { } else if (_domainHandler.getIP().isNull() && _domainHandler.requiresICE()) {
qCDebug(networking) << "Waiting for ICE discovered domain-server socket. Will not send domain-server check in."; qCDebug(networking) << "Waiting for ICE discovered domain-server socket. Will not send domain-server check in.";
handleICEConnectionToDomainServer(); handleICEConnectionToDomainServer();
} else if (!_domainHandler.getIP().isNull()) { // let the domain handler know we are due to send a checkin packet
} else if (!_domainHandler.getIP().isNull() && !_domainHandler.checkInPacketTimeout()) {
PacketType domainPacketType = !_domainHandler.isConnected() PacketType domainPacketType = !_domainHandler.isConnected()
? PacketType::DomainConnectRequest : PacketType::DomainListRequest; ? PacketType::DomainConnectRequest : PacketType::DomainListRequest;
@ -419,10 +420,15 @@ void NodeList::sendDomainServerCheckIn() {
flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::SendDSCheckIn); flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::SendDSCheckIn);
// Send duplicate check-ins in the exponentially increasing sequence 1, 1, 2, 4, ...
int outstandingCheckins = _domainHandler.getCheckInPacketsSinceLastReply();
int checkinCount = outstandingCheckins > 1 ? std::pow(2, outstandingCheckins - 2) : 1;
for (int i = 1; i < checkinCount; ++i) {
auto packetCopy = domainPacket->createCopy(*domainPacket);
sendPacket(std::move(packetCopy), _domainHandler.getSockAddr());
}
sendPacket(std::move(domainPacket), _domainHandler.getSockAddr()); sendPacket(std::move(domainPacket), _domainHandler.getSockAddr());
// let the domain handler know we sent another check in or connect packet
_domainHandler.sentCheckInPacket();
} }
} }

View file

@ -20,12 +20,6 @@
#include "OctreeLogging.h" #include "OctreeLogging.h"
OctreeProcessor::OctreeProcessor() :
_tree(NULL),
_managedTree(false)
{
}
void OctreeProcessor::init() { void OctreeProcessor::init() {
if (!_tree) { if (!_tree) {
_tree = createTree(); _tree = createTree();
@ -34,6 +28,9 @@ void OctreeProcessor::init() {
} }
OctreeProcessor::~OctreeProcessor() { OctreeProcessor::~OctreeProcessor() {
if (_tree) {
_tree->eraseAllOctreeElements(false);
}
} }
void OctreeProcessor::setTree(OctreePointer newTree) { void OctreeProcessor::setTree(OctreePointer newTree) {

View file

@ -28,7 +28,6 @@
class OctreeProcessor : public QObject, public QEnableSharedFromThis<OctreeProcessor> { class OctreeProcessor : public QObject, public QEnableSharedFromThis<OctreeProcessor> {
Q_OBJECT Q_OBJECT
public: public:
OctreeProcessor();
virtual ~OctreeProcessor(); virtual ~OctreeProcessor();
virtual char getMyNodeType() const = 0; virtual char getMyNodeType() const = 0;
@ -61,7 +60,7 @@ protected:
virtual OctreePointer createTree() = 0; virtual OctreePointer createTree() = 0;
OctreePointer _tree; OctreePointer _tree;
bool _managedTree; bool _managedTree { false };
SimpleMovingAverage _elementsPerPacket; SimpleMovingAverage _elementsPerPacket;
SimpleMovingAverage _entitiesPerPacket; SimpleMovingAverage _entitiesPerPacket;

View file

@ -269,7 +269,8 @@ void CharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar
} }
btQuaternion deltaRot = desiredRot * startRot.inverse(); btQuaternion deltaRot = desiredRot * startRot.inverse();
float angularSpeed = deltaRot.getAngle() / _followTimeRemaining; float angularSpeed = deltaRot.getAngle() / _followTimeRemaining;
btQuaternion angularDisplacement = btQuaternion(deltaRot.getAxis(), angularSpeed * dt); glm::vec3 rotationAxis = glm::normalize(glm::axis(bulletToGLM(deltaRot))); // deltaRot.getAxis() is inaccurate
btQuaternion angularDisplacement = btQuaternion(glmToBullet(rotationAxis), angularSpeed * dt);
btQuaternion endRot = angularDisplacement * startRot; btQuaternion endRot = angularDisplacement * startRot;
// in order to accumulate displacement of avatar position, we need to take _shapeLocalOffset into account. // in order to accumulate displacement of avatar position, we need to take _shapeLocalOffset into account.

View file

@ -834,3 +834,14 @@ void EntityMotionState::clearObjectVelocities() const {
} }
_entity->setAcceleration(glm::vec3(0.0f)); _entity->setAcceleration(glm::vec3(0.0f));
} }
void EntityMotionState::saveKinematicState(btScalar timeStep) {
_body->saveKinematicState(timeStep);
// This is a WORKAROUND for a quirk in Bullet: due to floating point error slow spinning kinematic objects will
// have a measured angular velocity of zero. This probably isn't a bug that the Bullet team is interested in
// fixing since there is one very simple workaround: use double-precision math for the physics simulation.
// We're not ready migrate to double-precision yet so we explicitly work around it by slamming the RigidBody's
// angular velocity with the value in the entity.
_body->setAngularVelocity(glmToBullet(_entity->getWorldAngularVelocity()));
}

View file

@ -97,6 +97,7 @@ public:
OwnershipState getOwnershipState() const { return _ownershipState; } OwnershipState getOwnershipState() const { return _ownershipState; }
void setRegion(uint8_t region); void setRegion(uint8_t region);
void saveKinematicState(btScalar timeStep) override;
protected: protected:
void updateSendVelocities(); void updateSendVelocities();

View file

@ -347,7 +347,7 @@ void ObjectMotionState::updateLastKinematicStep() {
} }
void ObjectMotionState::updateBodyMassProperties() { void ObjectMotionState::updateBodyMassProperties() {
float mass = getMass(); btScalar mass = getMass();
btVector3 inertia(1.0f, 1.0f, 1.0f); btVector3 inertia(1.0f, 1.0f, 1.0f);
if (mass > 0.0f) { if (mass > 0.0f) {
_body->getCollisionShape()->calculateLocalInertia(mass, inertia); _body->getCollisionShape()->calculateLocalInertia(mass, inertia);
@ -356,3 +356,7 @@ void ObjectMotionState::updateBodyMassProperties() {
_body->updateInertiaTensor(); _body->updateInertiaTensor();
} }
void ObjectMotionState::saveKinematicState(btScalar timeStep) {
_body->saveKinematicState(timeStep);
}

View file

@ -165,6 +165,7 @@ public:
virtual bool isLocallyOwned() const { return false; } virtual bool isLocallyOwned() const { return false; }
virtual bool isLocallyOwnedOrShouldBe() const { return false; } // aka shouldEmitCollisionEvents() virtual bool isLocallyOwnedOrShouldBe() const { return false; } // aka shouldEmitCollisionEvents()
virtual void saveKinematicState(btScalar timeStep);
friend class PhysicsEngine; friend class PhysicsEngine;

View file

@ -162,7 +162,13 @@ void ThreadSafeDynamicsWorld::saveKinematicState(btScalar timeStep) {
for (int i=0;i<m_nonStaticRigidBodies.size();i++) { for (int i=0;i<m_nonStaticRigidBodies.size();i++) {
btRigidBody* body = m_nonStaticRigidBodies[i]; btRigidBody* body = m_nonStaticRigidBodies[i];
if (body && body->isKinematicObject() && body->getActivationState() != ISLAND_SLEEPING) { if (body && body->isKinematicObject() && body->getActivationState() != ISLAND_SLEEPING) {
body->saveKinematicState(timeStep); if (body->getMotionState()) {
btMotionState* motionState = body->getMotionState();
ObjectMotionState* objectMotionState = static_cast<ObjectMotionState*>(motionState);
objectMotionState->saveKinematicState(timeStep);
} else {
body->saveKinematicState(timeStep);
}
} }
} }
} }

View file

@ -198,7 +198,7 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl
vec3 directionalSpecular; vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation); evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse; color += directionalDiffuse;
color += (ambientSpecular + directionalSpecular) / opacity; color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity);
return color; return color;
} }
@ -231,7 +231,7 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze(
vec3 directionalSpecular; vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation); evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse; color += directionalDiffuse;
color += (ambientSpecular + directionalSpecular) / opacity; color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity);
// Haze // Haze
if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {
@ -269,7 +269,7 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze(
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation); evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surface, metallic, fresnel, albedo, shadowAttenuation);
color += ambientDiffuse + directionalDiffuse; color += ambientDiffuse + directionalDiffuse;
color += (ambientSpecular + directionalSpecular) / opacity; color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity);
// Haze // Haze
if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) { if ((isHazeEnabled() > 0.0) && (hazeParams.hazeMode & HAZE_MODE_IS_ACTIVE) == HAZE_MODE_IS_ACTIVE) {

View file

@ -197,7 +197,7 @@ vec3 evalGlobalLightingAlphaBlended(mat4 invViewMat, float shadowAttenuation, fl
vec3 directionalSpecular; vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation); evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse; color += directionalDiffuse;
color += (ambientSpecular + directionalSpecular) / opacity; color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity);
return color; return color;
} }
@ -223,7 +223,7 @@ vec3 evalGlobalLightingAlphaBlendedWithHaze(
vec3 directionalSpecular; vec3 directionalSpecular;
evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation); evalLightingDirectional(directionalDiffuse, directionalSpecular, lightDirection, lightIrradiance, surfaceWS, metallic, fresnel, albedo, shadowAttenuation);
color += directionalDiffuse; color += directionalDiffuse;
color += (ambientSpecular + directionalSpecular) / opacity; color += evalSpecularWithOpacity(ambientSpecular + directionalSpecular, opacity);
// Haze // Haze
// FIXME - temporarily removed until we support it for forward... // FIXME - temporarily removed until we support it for forward...

View file

@ -143,6 +143,6 @@ vec4 evalLocalLighting(ivec3 cluster, int numLights, vec3 fragWorldPos, SurfaceD
fragSpecular *= isSpecularEnabled(); fragSpecular *= isSpecularEnabled();
fragColor.rgb += fragDiffuse; fragColor.rgb += fragDiffuse;
fragColor.rgb += fragSpecular / opacity; fragColor.rgb += evalSpecularWithOpacity(fragSpecular, opacity);
return fragColor; return fragColor;
} }

View file

@ -314,6 +314,9 @@ void evalFragShadingGloss(out vec3 diffuse, out vec3 specular,
specular = shading.xyz; specular = shading.xyz;
} }
vec3 evalSpecularWithOpacity(vec3 specular, float opacity) {
return specular / opacity;
}
<@if not GETFRESNEL0@> <@if not GETFRESNEL0@>
<@def GETFRESNEL0@> <@def GETFRESNEL0@>

View file

@ -267,7 +267,7 @@ vec3 fetchLightmapMap(vec2 uv) {
<@func discardTransparent(opacity)@> <@func discardTransparent(opacity)@>
{ {
if (<$opacity$> < 1.0) { if (<$opacity$> < 1e-6) {
discard; discard;
} }
} }

View file

@ -41,6 +41,7 @@ void main(void) {
float opacity = getMaterialOpacity(mat) * _alpha; float opacity = getMaterialOpacity(mat) * _alpha;
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
<$discardTransparent(opacity)$>;
vec3 albedo = getMaterialAlbedo(mat); vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;

View file

@ -44,6 +44,7 @@ void main(void) {
float opacity = getMaterialOpacity(mat) * _alpha; float opacity = getMaterialOpacity(mat) * _alpha;
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
<$discardTransparent(opacity)$>;
vec3 albedo = getMaterialAlbedo(mat); vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;

View file

@ -46,6 +46,7 @@ void main(void) {
float opacity = getMaterialOpacity(mat) * _alpha; float opacity = getMaterialOpacity(mat) * _alpha;
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
<$discardTransparent(opacity)$>;
vec3 albedo = getMaterialAlbedo(mat); vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;

View file

@ -45,6 +45,7 @@ void main(void) {
float opacity = getMaterialOpacity(mat) * _alpha; float opacity = getMaterialOpacity(mat) * _alpha;
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
<$discardTransparent(opacity)$>;
vec3 albedo = getMaterialAlbedo(mat); vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;

View file

@ -54,6 +54,7 @@ void main(void) {
float opacity = getMaterialOpacity(mat) * _alpha; float opacity = getMaterialOpacity(mat) * _alpha;
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
<$discardTransparent(opacity)$>;
vec3 albedo = getMaterialAlbedo(mat); vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;

View file

@ -31,6 +31,7 @@ void main(void) {
float opacity = getMaterialOpacity(mat) * _alpha; float opacity = getMaterialOpacity(mat) * _alpha;
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
<$discardTransparent(opacity)$>;
vec3 albedo = getMaterialAlbedo(mat); vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;

View file

@ -41,6 +41,7 @@ void main(void) {
float opacity = getMaterialOpacity(mat) * _alpha; float opacity = getMaterialOpacity(mat) * _alpha;
<$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>; <$evalMaterialOpacity(albedoTex.a, opacity, matKey, opacity)$>;
<$discardTransparent(opacity)$>;
vec3 albedo = getMaterialAlbedo(mat); vec3 albedo = getMaterialAlbedo(mat);
<$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>; <$evalMaterialAlbedo(albedoTex, albedo, matKey, albedo)$>;

View file

@ -64,3 +64,18 @@ const char* FACESHIFT_BLENDSHAPES[] = {
}; };
const int NUM_FACESHIFT_BLENDSHAPES = sizeof(FACESHIFT_BLENDSHAPES) / sizeof(char*); const int NUM_FACESHIFT_BLENDSHAPES = sizeof(FACESHIFT_BLENDSHAPES) / sizeof(char*);
const int EYE_BLINK_L_INDEX = 0;
const int EYE_BLINK_R_INDEX = 1;
const int EYE_SQUINT_L_INDEX = 2;
const int EYE_SQUINT_R_INDEX = 3;
const int EYE_OPEN_L_INDEX = 8;
const int EYE_OPEN_R_INDEX = 9;
const int BROWS_U_L_INDEX = 17;
const int BROWS_U_R_INDEX = 18;
const int EYE_BLINK_INDICES[] = { EYE_BLINK_L_INDEX, EYE_BLINK_R_INDEX };
const int EYE_SQUINT_INDICES[] = { EYE_SQUINT_L_INDEX, EYE_SQUINT_R_INDEX };
const int EYE_OPEN_INDICES[] = { EYE_OPEN_L_INDEX, EYE_OPEN_R_INDEX };
const int BROWS_U_INDICES[] = { BROWS_U_L_INDEX, BROWS_U_R_INDEX };

View file

@ -16,5 +16,10 @@
extern const char* FACESHIFT_BLENDSHAPES[]; extern const char* FACESHIFT_BLENDSHAPES[];
/// The size of FACESHIFT_BLENDSHAPES /// The size of FACESHIFT_BLENDSHAPES
extern const int NUM_FACESHIFT_BLENDSHAPES; extern const int NUM_FACESHIFT_BLENDSHAPES;
// Eyes and Brows indices
extern const int EYE_BLINK_INDICES[];
extern const int EYE_OPEN_INDICES[];
extern const int BROWS_U_INDICES[];
extern const int EYE_SQUINT_INDICES[];
#endif // hifi_FaceshiftConstants_h #endif // hifi_FaceshiftConstants_h

View file

@ -108,14 +108,13 @@ createControllerDisplay = function(config) {
for (var partName in controller.parts) { for (var partName in controller.parts) {
overlayID = this.overlays[i++]; overlayID = this.overlays[i++];
var part = controller.parts[partName]; var part = controller.parts[partName];
localPosition = Vec3.sum(controller.position, Vec3.multiplyQbyV(controller.rotation, part.naturalPosition)); localPosition = Vec3.subtract(part.naturalPosition, controller.naturalPosition);
var localRotation; var localRotation;
var value = this.partValues[partName]; var value = this.partValues[partName];
var offset, rotation; var offset, rotation;
if (value !== undefined) { if (value !== undefined) {
if (part.type === "linear") { if (part.type === "linear") {
var axis = Vec3.multiplyQbyV(controller.rotation, part.axis); offset = Vec3.multiply(part.maxTranslation * value, part.axis);
offset = Vec3.multiply(part.maxTranslation * value, axis);
localPosition = Vec3.sum(localPosition, offset); localPosition = Vec3.sum(localPosition, offset);
localRotation = undefined; localRotation = undefined;
} else if (part.type === "joystick") { } else if (part.type === "joystick") {
@ -126,8 +125,8 @@ createControllerDisplay = function(config) {
} else { } else {
offset = { x: 0, y: 0, z: 0 }; offset = { x: 0, y: 0, z: 0 };
} }
localPosition = Vec3.sum(controller.position, Vec3.multiplyQbyV(controller.rotation, Vec3.sum(offset, part.naturalPosition))); localPosition = Vec3.sum(offset, localPosition);
localRotation = Quat.multiply(controller.rotation, rotation); localRotation = rotation;
} else if (part.type === "rotational") { } else if (part.type === "rotational") {
value = clamp(value, part.minValue, part.maxValue); value = clamp(value, part.minValue, part.maxValue);
var pct = (value - part.minValue) / part.maxValue; var pct = (value - part.minValue) / part.maxValue;
@ -139,8 +138,8 @@ createControllerDisplay = function(config) {
} else { } else {
offset = { x: 0, y: 0, z: 0 }; offset = { x: 0, y: 0, z: 0 };
} }
localPosition = Vec3.sum(controller.position, Vec3.multiplyQbyV(controller.rotation, Vec3.sum(offset, part.naturalPosition))); localPosition = Vec3.sum(offset, localPosition);
localRotation = Quat.multiply(controller.rotation, rotation); localRotation = rotation;
} }
} }
if (localRotation !== undefined) { if (localRotation !== undefined) {
@ -169,9 +168,11 @@ createControllerDisplay = function(config) {
if (controller.naturalPosition) { if (controller.naturalPosition) {
position = Vec3.sum(Vec3.multiplyQbyV(controller.rotation, controller.naturalPosition), position); position = Vec3.sum(Vec3.multiplyQbyV(controller.rotation, controller.naturalPosition), position);
} else {
controller.naturalPosition = { x: 0, y: 0, z: 0 };
} }
var overlayID = Overlays.addOverlay("model", { var baseOverlayID = Overlays.addOverlay("model", {
url: controller.modelURL, url: controller.modelURL,
dimensions: Vec3.multiply(sensorScaleFactor, controller.dimensions), dimensions: Vec3.multiply(sensorScaleFactor, controller.dimensions),
localRotation: controller.rotation, localRotation: controller.rotation,
@ -181,23 +182,21 @@ createControllerDisplay = function(config) {
ignoreRayIntersection: true ignoreRayIntersection: true
}); });
controllerDisplay.overlays.push(overlayID); controllerDisplay.overlays.push(baseOverlayID);
overlayID = null;
if (controller.parts) { if (controller.parts) {
for (var partName in controller.parts) { for (var partName in controller.parts) {
var part = controller.parts[partName]; var part = controller.parts[partName];
var partPosition = Vec3.sum(controller.position, Vec3.multiplyQbyV(controller.rotation, part.naturalPosition)); var localPosition = Vec3.subtract(part.naturalPosition, controller.naturalPosition);
var innerRotation = controller.rotation; var localRotation = { x: 0, y: 0, z: 0, w: 1 }
controllerDisplay.parts[partName] = controller.parts[partName]; controllerDisplay.parts[partName] = controller.parts[partName];
var properties = { var properties = {
url: part.modelURL, url: part.modelURL,
localPosition: partPosition, localPosition: localPosition,
localRotation: innerRotation, localRotation: localRotation,
parentID: MyAvatar.SELF_ID, parentID: baseOverlayID,
parentJointIndex: controller.jointIndex,
ignoreRayIntersection: true ignoreRayIntersection: true
}; };
@ -207,11 +206,10 @@ createControllerDisplay = function(config) {
properties['textures'] = textures; properties['textures'] = textures;
} }
overlayID = Overlays.addOverlay("model", properties); var overlayID = Overlays.addOverlay("model", properties);
if (part.type === "rotational") { if (part.type === "rotational") {
var input = resolveHardware(part.input); var input = resolveHardware(part.input);
print("Mapping to: ", part.input, input);
mapping.from([input]).peek().to(function(partName) { mapping.from([input]).peek().to(function(partName) {
return function(value) { return function(value) {
// insert the most recent controller value into controllerDisplay.partValues. // insert the most recent controller value into controllerDisplay.partValues.

View file

@ -605,7 +605,6 @@
var finger = fingerKeys[i]; var finger = fingerKeys[i];
var LOOKUP_DISTANCE_MULTIPLIER = 1.5; var LOOKUP_DISTANCE_MULTIPLIER = 1.5;
var dist = LOOKUP_DISTANCE_MULTIPLIER*data.distance; var dist = LOOKUP_DISTANCE_MULTIPLIER*data.distance;
console.log("distance: " + dist);
var checkOffset = { var checkOffset = {
x: data.perpendicular.x * dist, x: data.perpendicular.x * dist,
y: data.perpendicular.y * dist, y: data.perpendicular.y * dist,

View file

@ -1835,7 +1835,7 @@ var keyReleaseEvent = function (event) {
deleteSelectedEntities(); deleteSelectedEntities();
} else if (event.text === "ESC") { } else if (event.text === "ESC") {
selectionManager.clearSelections(); selectionManager.clearSelections();
} else if (event.text === "TAB") { } else if (event.text === "t") {
selectionDisplay.toggleSpaceMode(); selectionDisplay.toggleSpaceMode();
} else if (event.text === "f") { } else if (event.text === "f") {
if (isActive) { if (isActive) {

View file

@ -668,6 +668,7 @@ window.onload = function () {
addImage(element, messageOptions.isLoggedIn, idx === 0 && messageOptions.canShare, idx === 1, false, false, false, true); addImage(element, messageOptions.isLoggedIn, idx === 0 && messageOptions.canShare, idx === 1, false, false, false, true);
}); });
document.getElementById("p1").classList.add("processingGif"); document.getElementById("p1").classList.add("processingGif");
document.getElementById("snap-button").disabled = true;
} else { } else {
var gifPath = message.image_data[0].localPath, var gifPath = message.image_data[0].localPath,
p1img = document.getElementById('p1img'); p1img = document.getElementById('p1img');
@ -677,14 +678,15 @@ window.onload = function () {
shareForUrl("p1"); shareForUrl("p1");
appendShareBar("p1", messageOptions.isLoggedIn, messageOptions.canShare, true, false, false, messageOptions.canBlast); appendShareBar("p1", messageOptions.isLoggedIn, messageOptions.canShare, true, false, false, messageOptions.canBlast);
document.getElementById("p1").classList.remove("processingGif"); document.getElementById("p1").classList.remove("processingGif");
document.getElementById("snap-button").disabled = false;
} }
} else { } else {
imageCount = message.image_data.length; imageCount = message.image_data.length;
message.image_data.forEach(function (element) { message.image_data.forEach(function (element) {
addImage(element, messageOptions.isLoggedIn, messageOptions.canShare, false, false, false, false, true); addImage(element, messageOptions.isLoggedIn, messageOptions.canShare, false, false, false, false, true);
}); });
document.getElementById("snap-button").disabled = false;
} }
document.getElementById("snap-button").disabled = false;
break; break;
case 'captureSettings': case 'captureSettings':
handleCaptureSetting(message.setting); handleCaptureSetting(message.setting);
@ -701,7 +703,7 @@ window.onload = function () {
case 'snapshotUploadComplete': case 'snapshotUploadComplete':
var isGif = fileExtensionMatches(message.image_url, "gif"); var isGif = fileExtensionMatches(message.image_url, "gif");
updateShareInfo(isGif ? "p1" : "p0", message.story_id); updateShareInfo(isGif ? "p1" : "p0", message.story_id);
if (isPrintProcessing()) { if (isPrintProcessing()) {
setPrintButtonEnabled(); setPrintButtonEnabled();
} }
break; break;
@ -724,11 +726,11 @@ function snapshotSettings() {
})); }));
} }
function takeSnapshot() { function takeSnapshot() {
document.getElementById("snap-button").disabled = true;
EventBridge.emitWebEvent(JSON.stringify({ EventBridge.emitWebEvent(JSON.stringify({
type: "snapshot", type: "snapshot",
action: "takeSnapshot" action: "takeSnapshot"
})); }));
document.getElementById("snap-button").disabled = true;
} }
function isPrintDisabled() { function isPrintDisabled() {
@ -739,14 +741,14 @@ function isPrintDisabled() {
document.getElementById('print-button').disabled; document.getElementById('print-button').disabled;
} }
function isPrintProcessing() { function isPrintProcessing() {
var printElement = document.getElementById('print-icon'); var printElement = document.getElementById('print-icon');
return printElement.classList.contains("print-icon") && return printElement.classList.contains("print-icon") &&
printElement.classList.contains("print-icon-loading") && printElement.classList.contains("print-icon-loading") &&
document.getElementById('print-button').disabled; document.getElementById('print-button').disabled;
} }
function isPrintEnabled() { function isPrintEnabled() {
var printElement = document.getElementById('print-icon'); var printElement = document.getElementById('print-icon');
return printElement.classList.contains("print-icon") && return printElement.classList.contains("print-icon") &&
printElement.classList.contains("print-icon-default") && printElement.classList.contains("print-icon-default") &&
@ -773,8 +775,8 @@ function requestPrintButtonUpdate() {
})); }));
} }
function printToPolaroid() { function printToPolaroid() {
if (isPrintEnabled()) { if (isPrintEnabled()) {
EventBridge.emitWebEvent(JSON.stringify({ EventBridge.emitWebEvent(JSON.stringify({
type: "snapshot", type: "snapshot",
action: "printToPolaroid" action: "printToPolaroid"

View file

@ -215,8 +215,10 @@ SelectionManager = (function() {
that.worldRotation = properties.boundingBox.rotation; that.worldRotation = properties.boundingBox.rotation;
that.entityType = properties.type; that.entityType = properties.type;
SelectionDisplay.setSpaceMode(SPACE_LOCAL); if (selectionUpdated) {
SelectionDisplay.setSpaceMode(SPACE_LOCAL);
}
} else { } else {
that.localRotation = null; that.localRotation = null;
that.localDimensions = null; that.localDimensions = null;
@ -1435,7 +1437,7 @@ SelectionDisplay = (function() {
that.setHandleRotateYawVisible(!activeTool || isActiveTool(handleRotateYawRing)); that.setHandleRotateYawVisible(!activeTool || isActiveTool(handleRotateYawRing));
that.setHandleRotateRollVisible(!activeTool || isActiveTool(handleRotateRollRing)); that.setHandleRotateRollVisible(!activeTool || isActiveTool(handleRotateRollRing));
var showScaleStretch = !activeTool && SelectionManager.selections.length === 1; var showScaleStretch = !activeTool && SelectionManager.selections.length === 1 && spaceMode === SPACE_LOCAL;
that.setHandleStretchXVisible(showScaleStretch || isActiveTool(handleStretchXSphere)); that.setHandleStretchXVisible(showScaleStretch || isActiveTool(handleStretchXSphere));
that.setHandleStretchYVisible(showScaleStretch || isActiveTool(handleStretchYSphere)); that.setHandleStretchYVisible(showScaleStretch || isActiveTool(handleStretchYSphere));
that.setHandleStretchZVisible(showScaleStretch || isActiveTool(handleStretchZSphere)); that.setHandleStretchZVisible(showScaleStretch || isActiveTool(handleStretchZSphere));
@ -2061,7 +2063,7 @@ SelectionDisplay = (function() {
}; };
var onMove = function(event) { var onMove = function(event) {
var proportional = (spaceMode === SPACE_WORLD) || directionEnum === STRETCH_DIRECTION.ALL; var proportional = directionEnum === STRETCH_DIRECTION.ALL;
var position, rotation; var position, rotation;
if (spaceMode === SPACE_LOCAL) { if (spaceMode === SPACE_LOCAL) {

View file

@ -310,7 +310,7 @@ function printToPolaroid(image_url) {
"gravity": { "x": 0, "y": -2.5, "z": 0 }, "gravity": { "x": 0, "y": -2.5, "z": 0 },
"velocity": { "x": 0, "y": 1.95, "z": 0 }, "velocity": { "x": 0, "y": 1.95, "z": 0 },
"angularVelocity": { "x": -1.0, "y": 0, "z": -1.3 }, "angularVelocity": Vec3.multiplyQbyV(MyAvatar.orientation, { "x": -1.0, "y": 0, "z": -1.3 }),
"dynamic": true, "dynamic": true,
"collisionsWillMove": true, "collisionsWillMove": true,