mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 12:37:51 +02:00
resolve conflicts on merge with upstream/core
This commit is contained in:
commit
653e0d29c7
40 changed files with 743 additions and 202 deletions
28
cmake/externals/zlib/CMakeLists.txt
vendored
Normal file
28
cmake/externals/zlib/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
set(EXTERNAL_NAME zlib)
|
||||||
|
string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
|
||||||
|
|
||||||
|
include(ExternalProject)
|
||||||
|
ExternalProject_Add(
|
||||||
|
${EXTERNAL_NAME}
|
||||||
|
URL http://zlib.net/zlib128.zip
|
||||||
|
URL_MD5 126f8676442ffbd97884eb4d6f32afb4
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
LOG_DOWNLOAD 1
|
||||||
|
)
|
||||||
|
|
||||||
|
# Hide this external target (for ide users)
|
||||||
|
set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals")
|
||||||
|
|
||||||
|
ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR)
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE PATH "List of zlib include directories")
|
||||||
|
|
||||||
|
ExternalProject_Get_Property(${EXTERNAL_NAME} BINARY_DIR)
|
||||||
|
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_DLL_PATH ${BINARY_DIR}/Release CACHE FILEPATH "Location of GLEW DLL")
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_LIBRARY_RELEASE ${BINARY_DIR}/Release/zlib.lib CACHE FILEPATH "Location of ZLib release library")
|
||||||
|
set(${EXTERNAL_NAME_UPPER}_LIBRARY_DEBUG "" CACHE FILEPATH "Location of ZLib debug library")
|
||||||
|
|
||||||
|
endif ()
|
|
@ -18,20 +18,18 @@ include("${MACRO_DIR}/HifiLibrarySearchHints.cmake")
|
||||||
hifi_library_search_hints("connexionclient")
|
hifi_library_search_hints("connexionclient")
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
find_library(3DConnexionClient 3DConnexionClient)
|
find_library(3DCONNEXIONCLIENT_LIBRARIES NAMES 3DConnexionClient HINTS 3DCONNEXIONCLIENT_SEARCH_DIRS)
|
||||||
if(EXISTS ${3DConnexionClient})
|
if(EXISTS ${3DConnexionClient})
|
||||||
set(3DCONNEXIONCLIENT_FOUND true)
|
set(3DCONNEXIONCLIENT_FOUND true)
|
||||||
set(3DCONNEXIONCLIENT_INCLUDE_DIRS ${3DConnexionClient})
|
set(3DCONNEXIONCLIENT_INCLUDE_DIRS ${3DConnexionClient})
|
||||||
set(3DCONNEXIONCLIENT_LIBRARY ${3DConnexionClient})
|
set(3DCONNEXIONCLIENT_LIBRARY ${3DConnexionClient})
|
||||||
message(STATUS "Found 3DConnexion at " ${3DConnexionClient})
|
message(STATUS "Found 3DConnexion at " ${3DConnexionClient})
|
||||||
mark_as_advanced(3DCONNEXIONCLIENT_INCLUDE_DIR CONNEXIONCLIENT_LIBRARY)
|
mark_as_advanced(3DCONNEXIONCLIENT_INCLUDE_DIR 3DCONNEXIONCLIENT_LIBRARY)
|
||||||
else ()
|
else ()
|
||||||
message(STATUS "Could NOT find 3DConnexionClient")
|
message(STATUS "Could NOT find 3DConnexionClient")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
elseif (WIN32)
|
||||||
|
find_path(3DCONNEXIONCLIENT_INCLUDE_DIRS I3dMouseParams.h PATH_SUFFIXES include HINTS ${3DCONNEXIONCLIENT_SEARCH_DIRS})
|
||||||
if (WIN32)
|
|
||||||
find_path(3DCONNEXIONCLIENT_INCLUDE_DIRS I3dMouseParams.h PATH_SUFFIXES Inc HINTS ${CONNEXIONCLIENT_SEARCH_DIRS})
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
include(FindPackageHandleStandardArgs)
|
||||||
find_package_handle_standard_args(3DConnexionClient DEFAULT_MSG 3DCONNEXIONCLIENT_INCLUDE_DIRS)
|
find_package_handle_standard_args(3DConnexionClient DEFAULT_MSG 3DCONNEXIONCLIENT_INCLUDE_DIRS)
|
||||||
|
|
|
@ -389,6 +389,10 @@
|
||||||
{
|
{
|
||||||
"value": "json",
|
"value": "json",
|
||||||
"label": "Entity server persists data as JSON"
|
"label": "Entity server persists data as JSON"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"value": "json.gz",
|
||||||
|
"label": "Entity server persists data as gzipped JSON"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"advanced": true
|
"advanced": true
|
||||||
|
|
78
examples/gridTest.js
Normal file
78
examples/gridTest.js
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
//
|
||||||
|
// Created by Philip Rosedale on July 28, 2015
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
// Creates a rectangular grid of objects, starting at the origin and proceeding along the X/Z plane.
|
||||||
|
// Useful for testing the rendering, LOD, and octree storage aspects of the system.
|
||||||
|
//
|
||||||
|
// Note that when creating things quickly, the entity server will ignore data if we send updates too quickly.
|
||||||
|
// like Internet MTU, these rates are set by th domain operator, so in this script there is a RATE_PER_SECOND
|
||||||
|
// variable letting you set this speed. If entities are missing from the grid after a relog, this number
|
||||||
|
// being too high may be the reason.
|
||||||
|
|
||||||
|
var SIZE = 10.0;
|
||||||
|
var SEPARATION = 20.0;
|
||||||
|
var ROWS_X = 30;
|
||||||
|
var ROWS_Z = 30;
|
||||||
|
var TYPE = "Sphere"; // Right now this can be "Box" or "Model" or "Sphere"
|
||||||
|
var MODEL_URL = "https://hifi-public.s3.amazonaws.com/models/props/LowPolyIsland/CypressTreeGroup.fbx";
|
||||||
|
var MODEL_DIMENSION = { x: 33, y: 16, z: 49 };
|
||||||
|
var RATE_PER_SECOND = 1000; // The entity server will drop data if we create things too fast.
|
||||||
|
var SCRIPT_INTERVAL = 100;
|
||||||
|
var LIFETIME = 600; // By default, these entities will live in the server for 10 minutes
|
||||||
|
|
||||||
|
var addRandom = false;
|
||||||
|
|
||||||
|
var x = 0;
|
||||||
|
var z = 0;
|
||||||
|
var totalCreated = 0;
|
||||||
|
|
||||||
|
Script.setInterval(function () {
|
||||||
|
if (!Entities.serversExist() || !Entities.canRez()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var numToCreate = RATE_PER_SECOND * (SCRIPT_INTERVAL / 1000.0);
|
||||||
|
for (var i = 0; i < numToCreate; i++) {
|
||||||
|
var position = { x: SIZE + (x * SEPARATION), y: SIZE, z: SIZE + (z * SEPARATION) };
|
||||||
|
if (TYPE == "Model") {
|
||||||
|
Entities.addEntity({
|
||||||
|
type: TYPE,
|
||||||
|
name: "gridTest",
|
||||||
|
modelURL: MODEL_URL,
|
||||||
|
position: position,
|
||||||
|
dimensions: MODEL_DIMENSION,
|
||||||
|
ignoreCollisions: true,
|
||||||
|
collisionsWillMove: false,
|
||||||
|
lifetime: LIFETIME
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
Entities.addEntity({
|
||||||
|
type: TYPE,
|
||||||
|
name: "gridTest",
|
||||||
|
position: position,
|
||||||
|
dimensions: { x: SIZE, y: SIZE, z: SIZE },
|
||||||
|
color: { red: x / ROWS_X * 255, green: 50, blue: z / ROWS_Z * 255 },
|
||||||
|
ignoreCollisions: true,
|
||||||
|
collisionsWillMove: false,
|
||||||
|
lifetime: LIFETIME
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
totalCreated++;
|
||||||
|
|
||||||
|
x++;
|
||||||
|
if (x == ROWS_X) {
|
||||||
|
x = 0;
|
||||||
|
z++;
|
||||||
|
print("Created: " + totalCreated);
|
||||||
|
}
|
||||||
|
if (z == ROWS_Z) {
|
||||||
|
Script.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, SCRIPT_INTERVAL);
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
The Mac version does not require any files. The 3D Connexion driver should be installed from http://www.3dconnexion.eu/service/drivers.html
|
The Mac version does not require any files. The 3D Connexion driver should be installed from http://www.3dconnexion.eu/service/drivers.html
|
||||||
|
|
||||||
For Windows the provided header file is required: Inc/I3dMouseParams.h
|
For Windows the provided header file is required: include/I3dMouseParams.h
|
64
interface/resources/meshes/defaultAvatar_full.fst
Normal file
64
interface/resources/meshes/defaultAvatar_full.fst
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
name = defaultAvatar_full
|
||||||
|
type = body+head
|
||||||
|
scale = 1
|
||||||
|
filename = defaultAvatar_full/defaultAvatar_full.fbx
|
||||||
|
texdir = defaultAvatar_full/textures
|
||||||
|
joint = jointNeck = Head
|
||||||
|
joint = jointLeftHand = LeftHand
|
||||||
|
joint = jointRoot = Hips
|
||||||
|
joint = jointHead = HeadTop_End
|
||||||
|
joint = jointRightHand = RightHand
|
||||||
|
joint = jointLean = Spine
|
||||||
|
freeJoint = LeftArm
|
||||||
|
freeJoint = LeftForeArm
|
||||||
|
freeJoint = RightArm
|
||||||
|
freeJoint = RightForeArm
|
||||||
|
jointIndex = LeftHand = 35
|
||||||
|
jointIndex = Reye = 3
|
||||||
|
jointIndex = Hips = 10
|
||||||
|
jointIndex = LeftHandIndex1 = 36
|
||||||
|
jointIndex = LeftHandIndex2 = 37
|
||||||
|
jointIndex = LeftHandIndex3 = 38
|
||||||
|
jointIndex = LeftHandIndex4 = 39
|
||||||
|
jointIndex = LeftShoulder = 32
|
||||||
|
jointIndex = RightLeg = 12
|
||||||
|
jointIndex = Grp_blendshapes = 0
|
||||||
|
jointIndex = Leye = 4
|
||||||
|
jointIndex = headphone = 8
|
||||||
|
jointIndex = RightForeArm = 26
|
||||||
|
jointIndex = Spine = 21
|
||||||
|
jointIndex = LeftFoot = 18
|
||||||
|
jointIndex = RightToeBase = 14
|
||||||
|
jointIndex = face = 1
|
||||||
|
jointIndex = LeftToe_End = 20
|
||||||
|
jointIndex = Spine1 = 22
|
||||||
|
jointIndex = body = 9
|
||||||
|
jointIndex = Spine2 = 23
|
||||||
|
jointIndex = RightUpLeg = 11
|
||||||
|
jointIndex = top1 = 7
|
||||||
|
jointIndex = Neck = 40
|
||||||
|
jointIndex = HeadTop_End = 42
|
||||||
|
jointIndex = RightShoulder = 24
|
||||||
|
jointIndex = RightArm = 25
|
||||||
|
jointIndex = Head = 41
|
||||||
|
jointIndex = LeftLeg = 17
|
||||||
|
jointIndex = LeftForeArm = 34
|
||||||
|
jointIndex = hair = 6
|
||||||
|
jointIndex = RightHand = 27
|
||||||
|
jointIndex = LeftToeBase = 19
|
||||||
|
jointIndex = LeftUpLeg = 16
|
||||||
|
jointIndex = mouth = 2
|
||||||
|
jointIndex = RightFoot = 13
|
||||||
|
jointIndex = LeftArm = 33
|
||||||
|
jointIndex = shield = 5
|
||||||
|
jointIndex = RightHandIndex1 = 28
|
||||||
|
jointIndex = RightHandIndex2 = 29
|
||||||
|
jointIndex = RightToe_End = 15
|
||||||
|
jointIndex = RightHandIndex3 = 30
|
||||||
|
jointIndex = RightHandIndex4 = 31
|
||||||
|
ry = 0
|
||||||
|
rz = 0
|
||||||
|
tx = 0
|
||||||
|
ty = 0
|
||||||
|
tz = 0
|
||||||
|
rx = 0
|
Binary file not shown.
BIN
interface/resources/meshes/defaultAvatar_full/textures/visor.png
Normal file
BIN
interface/resources/meshes/defaultAvatar_full/textures/visor.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.6 KiB |
|
@ -641,7 +641,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
|
||||||
applicationUpdater->checkForUpdate();
|
applicationUpdater->checkForUpdate();
|
||||||
|
|
||||||
// the 3Dconnexion device wants to be initiliazed after a window is displayed.
|
// the 3Dconnexion device wants to be initiliazed after a window is displayed.
|
||||||
ConnexionClient::init();
|
ConnexionClient::getInstance().init();
|
||||||
|
|
||||||
auto& packetReceiver = nodeList->getPacketReceiver();
|
auto& packetReceiver = nodeList->getPacketReceiver();
|
||||||
packetReceiver.registerListener(PacketType::DomainConnectionDenied, this, "handleDomainConnectionDeniedPacket");
|
packetReceiver.registerListener(PacketType::DomainConnectionDenied, this, "handleDomainConnectionDeniedPacket");
|
||||||
|
@ -754,7 +754,7 @@ Application::~Application() {
|
||||||
|
|
||||||
Leapmotion::destroy();
|
Leapmotion::destroy();
|
||||||
RealSense::destroy();
|
RealSense::destroy();
|
||||||
ConnexionClient::destroy();
|
ConnexionClient::getInstance().destroy();
|
||||||
|
|
||||||
qInstallMessageHandler(NULL); // NOTE: Do this as late as possible so we continue to get our log messages
|
qInstallMessageHandler(NULL); // NOTE: Do this as late as possible so we continue to get our log messages
|
||||||
}
|
}
|
||||||
|
@ -2020,6 +2020,7 @@ void Application::setActiveFaceTracker() {
|
||||||
#ifdef HAVE_DDE
|
#ifdef HAVE_DDE
|
||||||
bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::UseCamera);
|
bool isUsingDDE = Menu::getInstance()->isOptionChecked(MenuOption::UseCamera);
|
||||||
Menu::getInstance()->getActionForOption(MenuOption::BinaryEyelidControl)->setVisible(isUsingDDE);
|
Menu::getInstance()->getActionForOption(MenuOption::BinaryEyelidControl)->setVisible(isUsingDDE);
|
||||||
|
Menu::getInstance()->getActionForOption(MenuOption::CoupleEyelids)->setVisible(isUsingDDE);
|
||||||
Menu::getInstance()->getActionForOption(MenuOption::UseAudioForMouth)->setVisible(isUsingDDE);
|
Menu::getInstance()->getActionForOption(MenuOption::UseAudioForMouth)->setVisible(isUsingDDE);
|
||||||
Menu::getInstance()->getActionForOption(MenuOption::VelocityFilter)->setVisible(isUsingDDE);
|
Menu::getInstance()->getActionForOption(MenuOption::VelocityFilter)->setVisible(isUsingDDE);
|
||||||
Menu::getInstance()->getActionForOption(MenuOption::CalibrateCamera)->setVisible(isUsingDDE);
|
Menu::getInstance()->getActionForOption(MenuOption::CalibrateCamera)->setVisible(isUsingDDE);
|
||||||
|
|
|
@ -421,6 +421,8 @@ Menu::Menu() {
|
||||||
faceTrackingMenu->addSeparator();
|
faceTrackingMenu->addSeparator();
|
||||||
QAction* binaryEyelidControl = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::BinaryEyelidControl, 0, true);
|
QAction* binaryEyelidControl = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::BinaryEyelidControl, 0, true);
|
||||||
binaryEyelidControl->setVisible(true); // DDE face tracking is on by default
|
binaryEyelidControl->setVisible(true); // DDE face tracking is on by default
|
||||||
|
QAction* coupleEyelids = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::CoupleEyelids, 0, true);
|
||||||
|
coupleEyelids->setVisible(true); // DDE face tracking is on by default
|
||||||
QAction* useAudioForMouth = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseAudioForMouth, 0, true);
|
QAction* useAudioForMouth = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::UseAudioForMouth, 0, true);
|
||||||
useAudioForMouth->setVisible(true); // DDE face tracking is on by default
|
useAudioForMouth->setVisible(true); // DDE face tracking is on by default
|
||||||
QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true);
|
QAction* ddeFiltering = addCheckableActionToQMenuAndActionHash(faceTrackingMenu, MenuOption::VelocityFilter, 0, true);
|
||||||
|
|
|
@ -165,6 +165,7 @@ namespace MenuOption {
|
||||||
const QString ControlWithSpeech = "Control With Speech";
|
const QString ControlWithSpeech = "Control With Speech";
|
||||||
const QString CopyAddress = "Copy Address to Clipboard";
|
const QString CopyAddress = "Copy Address to Clipboard";
|
||||||
const QString CopyPath = "Copy Path to Clipboard";
|
const QString CopyPath = "Copy Path to Clipboard";
|
||||||
|
const QString CoupleEyelids = "Couple Eyelids";
|
||||||
const QString DebugAmbientOcclusion = "Debug Ambient Occlusion";
|
const QString DebugAmbientOcclusion = "Debug Ambient Occlusion";
|
||||||
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
||||||
const QString DeleteBookmark = "Delete Bookmark...";
|
const QString DeleteBookmark = "Delete Bookmark...";
|
||||||
|
|
|
@ -936,9 +936,15 @@ void Avatar::setFaceModelURL(const QUrl& faceModelURL) {
|
||||||
|
|
||||||
void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
||||||
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
AvatarData::setSkeletonModelURL(skeletonModelURL);
|
||||||
|
const QUrl DEFAULT_FULL_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_full.fst");
|
||||||
const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst");
|
const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst");
|
||||||
|
if (isMyAvatar()) {
|
||||||
|
_skeletonModel.setURL(_skeletonModelURL,
|
||||||
|
getUseFullAvatar() ? DEFAULT_FULL_MODEL_URL : DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar());
|
||||||
|
} else {
|
||||||
_skeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar());
|
_skeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
void Avatar::setAttachmentData(const QVector<AttachmentData>& attachmentData) {
|
||||||
AvatarData::setAttachmentData(attachmentData);
|
AvatarData::setAttachmentData(attachmentData);
|
||||||
|
|
|
@ -150,6 +150,7 @@ public:
|
||||||
Q_INVOKABLE glm::vec3 getAngularVelocity() const { return _angularVelocity; }
|
Q_INVOKABLE glm::vec3 getAngularVelocity() const { return _angularVelocity; }
|
||||||
Q_INVOKABLE glm::vec3 getAngularAcceleration() const { return _angularAcceleration; }
|
Q_INVOKABLE glm::vec3 getAngularAcceleration() const { return _angularAcceleration; }
|
||||||
|
|
||||||
|
virtual bool getUseFullAvatar() const { return false; }
|
||||||
|
|
||||||
/// Scales a world space position vector relative to the avatar position and scale
|
/// Scales a world space position vector relative to the avatar position and scale
|
||||||
/// \param vector position to be scaled. Will store the result
|
/// \param vector position to be scaled. Will store the result
|
||||||
|
|
|
@ -623,6 +623,12 @@ float loadSetting(QSettings& settings, const char* name, float defaultValue) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MyAvatar::setEnableRigAnimations(bool isEnabled) {
|
||||||
|
Settings settings;
|
||||||
|
settings.setValue("enableRig", isEnabled);
|
||||||
|
_rig->setEnableRig(isEnabled);
|
||||||
|
}
|
||||||
|
|
||||||
void MyAvatar::loadData() {
|
void MyAvatar::loadData() {
|
||||||
Settings settings;
|
Settings settings;
|
||||||
settings.beginGroup("Avatar");
|
settings.beginGroup("Avatar");
|
||||||
|
|
|
@ -72,6 +72,7 @@ public:
|
||||||
Q_INVOKABLE AnimationDetails getAnimationDetailsByRole(const QString& role);
|
Q_INVOKABLE AnimationDetails getAnimationDetailsByRole(const QString& role);
|
||||||
Q_INVOKABLE AnimationDetails getAnimationDetails(const QString& url);
|
Q_INVOKABLE AnimationDetails getAnimationDetails(const QString& url);
|
||||||
void clearJointAnimationPriorities();
|
void clearJointAnimationPriorities();
|
||||||
|
Q_INVOKABLE void setEnableRigAnimations(bool isEnabled);
|
||||||
|
|
||||||
// get/set avatar data
|
// get/set avatar data
|
||||||
void saveData();
|
void saveData();
|
||||||
|
@ -115,7 +116,7 @@ public:
|
||||||
Q_INVOKABLE void useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL,
|
Q_INVOKABLE void useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL,
|
||||||
const QString& headName = QString(), const QString& bodyName = QString());
|
const QString& headName = QString(), const QString& bodyName = QString());
|
||||||
|
|
||||||
Q_INVOKABLE bool getUseFullAvatar() const { return _useFullAvatar; }
|
Q_INVOKABLE virtual bool getUseFullAvatar() const { return _useFullAvatar; }
|
||||||
Q_INVOKABLE const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; }
|
Q_INVOKABLE const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; }
|
||||||
Q_INVOKABLE const QUrl& getHeadURLFromPreferences() const { return _headURLFromPreferences; }
|
Q_INVOKABLE const QUrl& getHeadURLFromPreferences() const { return _headURLFromPreferences; }
|
||||||
Q_INVOKABLE const QUrl& getBodyURLFromPreferences() const { return _skeletonURLFromPreferences; }
|
Q_INVOKABLE const QUrl& getBodyURLFromPreferences() const { return _skeletonURLFromPreferences; }
|
||||||
|
|
|
@ -42,7 +42,23 @@ SkeletonModel::~SkeletonModel() {
|
||||||
void SkeletonModel::initJointStates(QVector<JointState> states) {
|
void SkeletonModel::initJointStates(QVector<JointState> states) {
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
||||||
_boundingRadius = _rig->initJointStates(states, parentTransform);
|
|
||||||
|
int rootJointIndex = geometry.rootJointIndex;
|
||||||
|
int leftHandJointIndex = geometry.leftHandJointIndex;
|
||||||
|
int leftElbowJointIndex = leftHandJointIndex >= 0 ? geometry.joints.at(leftHandJointIndex).parentIndex : -1;
|
||||||
|
int leftShoulderJointIndex = leftElbowJointIndex >= 0 ? geometry.joints.at(leftElbowJointIndex).parentIndex : -1;
|
||||||
|
int rightHandJointIndex = geometry.rightHandJointIndex;
|
||||||
|
int rightElbowJointIndex = rightHandJointIndex >= 0 ? geometry.joints.at(rightHandJointIndex).parentIndex : -1;
|
||||||
|
int rightShoulderJointIndex = rightElbowJointIndex >= 0 ? geometry.joints.at(rightElbowJointIndex).parentIndex : -1;
|
||||||
|
|
||||||
|
_boundingRadius = _rig->initJointStates(states, parentTransform,
|
||||||
|
rootJointIndex,
|
||||||
|
leftHandJointIndex,
|
||||||
|
leftElbowJointIndex,
|
||||||
|
leftShoulderJointIndex,
|
||||||
|
rightHandJointIndex,
|
||||||
|
rightElbowJointIndex,
|
||||||
|
rightShoulderJointIndex);
|
||||||
|
|
||||||
// Determine the default eye position for avatar scale = 1.0
|
// Determine the default eye position for avatar scale = 1.0
|
||||||
int headJointIndex = _geometry->getFBXGeometry().headJointIndex;
|
int headJointIndex = _geometry->getFBXGeometry().headJointIndex;
|
||||||
|
@ -227,7 +243,7 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
|
||||||
palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), fingerDirection) * palmRotation;
|
palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), fingerDirection) * palmRotation;
|
||||||
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::AlternateIK)) {
|
||||||
setHandPosition(jointIndex, palmPosition, palmRotation);
|
_rig->setHandPosition(jointIndex, palmPosition, palmRotation, extractUniformScale(_scale), PALM_PRIORITY);
|
||||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) {
|
} else if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) {
|
||||||
float forearmLength = geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale);
|
float forearmLength = geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale);
|
||||||
glm::vec3 forearm = palmRotation * glm::vec3(sign * forearmLength, 0.0f, 0.0f);
|
glm::vec3 forearm = palmRotation * glm::vec3(sign * forearmLength, 0.0f, 0.0f);
|
||||||
|
@ -333,69 +349,6 @@ void SkeletonModel::renderOrientationDirections(gpu::Batch& batch, int jointInde
|
||||||
geometryCache->renderLine(batch, position, pFront, blue, jointLineIDs._front);
|
geometryCache->renderLine(batch, position, pFront, blue, jointLineIDs._front);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void SkeletonModel::setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation) {
|
|
||||||
// this algorithm is from sample code from sixense
|
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
|
||||||
int elbowJointIndex = geometry.joints.at(jointIndex).parentIndex;
|
|
||||||
if (elbowJointIndex == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int shoulderJointIndex = geometry.joints.at(elbowJointIndex).parentIndex;
|
|
||||||
glm::vec3 shoulderPosition;
|
|
||||||
if (!getJointPosition(shoulderJointIndex, shoulderPosition)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// precomputed lengths
|
|
||||||
float scale = extractUniformScale(_scale);
|
|
||||||
float upperArmLength = geometry.joints.at(elbowJointIndex).distanceToParent * scale;
|
|
||||||
float lowerArmLength = geometry.joints.at(jointIndex).distanceToParent * scale;
|
|
||||||
|
|
||||||
// first set wrist position
|
|
||||||
glm::vec3 wristPosition = position;
|
|
||||||
|
|
||||||
glm::vec3 shoulderToWrist = wristPosition - shoulderPosition;
|
|
||||||
float distanceToWrist = glm::length(shoulderToWrist);
|
|
||||||
|
|
||||||
// prevent gimbal lock
|
|
||||||
if (distanceToWrist > upperArmLength + lowerArmLength - EPSILON) {
|
|
||||||
distanceToWrist = upperArmLength + lowerArmLength - EPSILON;
|
|
||||||
shoulderToWrist = glm::normalize(shoulderToWrist) * distanceToWrist;
|
|
||||||
wristPosition = shoulderPosition + shoulderToWrist;
|
|
||||||
}
|
|
||||||
|
|
||||||
// cosine of angle from upper arm to hand vector
|
|
||||||
float cosA = (upperArmLength * upperArmLength + distanceToWrist * distanceToWrist - lowerArmLength * lowerArmLength) /
|
|
||||||
(2 * upperArmLength * distanceToWrist);
|
|
||||||
float mid = upperArmLength * cosA;
|
|
||||||
float height = sqrt(upperArmLength * upperArmLength + mid * mid - 2 * upperArmLength * mid * cosA);
|
|
||||||
|
|
||||||
// direction of the elbow
|
|
||||||
glm::vec3 handNormal = glm::cross(rotation * glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow rotating with wrist
|
|
||||||
glm::vec3 relaxedNormal = glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow pointing straight down
|
|
||||||
const float NORMAL_WEIGHT = 0.5f;
|
|
||||||
glm::vec3 finalNormal = glm::mix(relaxedNormal, handNormal, NORMAL_WEIGHT);
|
|
||||||
|
|
||||||
bool rightHand = (jointIndex == geometry.rightHandJointIndex);
|
|
||||||
if (rightHand ? (finalNormal.y > 0.0f) : (finalNormal.y < 0.0f)) {
|
|
||||||
finalNormal.y = 0.0f; // dont allow elbows to point inward (y is vertical axis)
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 tangent = glm::normalize(glm::cross(shoulderToWrist, finalNormal));
|
|
||||||
|
|
||||||
// ik solution
|
|
||||||
glm::vec3 elbowPosition = shoulderPosition + glm::normalize(shoulderToWrist) * mid - tangent * height;
|
|
||||||
glm::vec3 forwardVector(rightHand ? -1.0f : 1.0f, 0.0f, 0.0f);
|
|
||||||
glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition);
|
|
||||||
|
|
||||||
_rig->setJointRotationInBindFrame(shoulderJointIndex, shoulderRotation, PALM_PRIORITY);
|
|
||||||
_rig->setJointRotationInBindFrame(elbowJointIndex,
|
|
||||||
rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) *
|
|
||||||
shoulderRotation, PALM_PRIORITY);
|
|
||||||
_rig->setJointRotationInBindFrame(jointIndex, rotation, PALM_PRIORITY);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const {
|
bool SkeletonModel::getLeftHandPosition(glm::vec3& position) const {
|
||||||
return getJointPositionInWorldFrame(getLeftHandJointIndex(), position);
|
return getJointPositionInWorldFrame(getLeftHandJointIndex(), position);
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,11 +131,6 @@ private:
|
||||||
QHash<int, OrientationLineIDs> _jointOrientationLines;
|
QHash<int, OrientationLineIDs> _jointOrientationLines;
|
||||||
int _triangleFanID;
|
int _triangleFanID;
|
||||||
|
|
||||||
/// \param jointIndex index of joint in model
|
|
||||||
/// \param position position of joint in model-frame
|
|
||||||
/// \param rotation rotation of joint in model-frame
|
|
||||||
void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation);
|
|
||||||
|
|
||||||
bool getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
|
bool getEyeModelPositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
|
||||||
|
|
||||||
Avatar* _owningAvatar;
|
Avatar* _owningAvatar;
|
||||||
|
|
|
@ -158,19 +158,16 @@ ConnexionClient& ConnexionClient::getInstance() {
|
||||||
|
|
||||||
#ifdef HAVE_3DCONNEXIONCLIENT
|
#ifdef HAVE_3DCONNEXIONCLIENT
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef Q_OS_WIN
|
||||||
|
|
||||||
static ConnexionClient* gMouseInput = 0;
|
|
||||||
|
|
||||||
void ConnexionClient::toggleConnexion(bool shouldEnable) {
|
void ConnexionClient::toggleConnexion(bool shouldEnable) {
|
||||||
ConnexionData& connexiondata = ConnexionData::getInstance();
|
ConnexionData& connexiondata = ConnexionData::getInstance();
|
||||||
if (shouldEnable && connexiondata.getDeviceID() == 0) {
|
if (shouldEnable && connexiondata.getDeviceID() == 0) {
|
||||||
ConnexionClient::init();
|
init();
|
||||||
}
|
}
|
||||||
if (!shouldEnable && connexiondata.getDeviceID() != 0) {
|
if (!shouldEnable && connexiondata.getDeviceID() != 0) {
|
||||||
ConnexionClient::destroy();
|
destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnexionClient::init() {
|
void ConnexionClient::init() {
|
||||||
|
@ -179,14 +176,12 @@ void ConnexionClient::init() {
|
||||||
|
|
||||||
InitializeRawInput(GetActiveWindow());
|
InitializeRawInput(GetActiveWindow());
|
||||||
|
|
||||||
gMouseInput = &this;
|
QAbstractEventDispatcher::instance()->installNativeEventFilter(this);
|
||||||
|
|
||||||
QAbstractEventDispatcher::instance()->installNativeEventFilter(&cclient);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnexionClient::destroy() {
|
void ConnexionClient::destroy() {
|
||||||
QAbstractEventDispatcher::instance()->removeNativeEventFilter(&this);
|
QAbstractEventDispatcher::instance()->removeNativeEventFilter(this);
|
||||||
ConnexionData& connexiondata = ConnexionData::getInstance();
|
ConnexionData& connexiondata = ConnexionData::getInstance();
|
||||||
int deviceid = connexiondata.getDeviceID();
|
int deviceid = connexiondata.getDeviceID();
|
||||||
connexiondata.setDeviceID(0);
|
connexiondata.setDeviceID(0);
|
||||||
|
@ -294,17 +289,17 @@ unsigned short HidToVirtualKey(unsigned long pid, unsigned short hidKeyCode) {
|
||||||
|
|
||||||
bool ConnexionClient::RawInputEventFilter(void* msg, long* result) {
|
bool ConnexionClient::RawInputEventFilter(void* msg, long* result) {
|
||||||
ConnexionData& connexiondata = ConnexionData::getInstance();
|
ConnexionData& connexiondata = ConnexionData::getInstance();
|
||||||
if (ConnexionClient::Is3dmouseAttached() && connexiondata.getDeviceID() == 0) {
|
if (Is3dmouseAttached() && connexiondata.getDeviceID() == 0) {
|
||||||
connexiondata.registerToUserInputMapper(*Application::getUserInputMapper());
|
connexiondata.registerToUserInputMapper(*Application::getUserInputMapper());
|
||||||
connexiondata.assignDefaultInputMapping(*Application::getUserInputMapper());
|
connexiondata.assignDefaultInputMapping(*Application::getUserInputMapper());
|
||||||
UserActivityLogger::getInstance().connectedDevice("controller", "3Dconnexion");
|
UserActivityLogger::getInstance().connectedDevice("controller", "3Dconnexion");
|
||||||
} else if (!ConnexionClient::Is3dmouseAttached() && connexiondata.getDeviceID() != 0) {
|
} else if (!Is3dmouseAttached() && connexiondata.getDeviceID() != 0) {
|
||||||
int deviceid = connexiondata.getDeviceID();
|
int deviceid = connexiondata.getDeviceID();
|
||||||
connexiondata.setDeviceID(0);
|
connexiondata.setDeviceID(0);
|
||||||
Application::getUserInputMapper()->removeDevice(deviceid);
|
Application::getUserInputMapper()->removeDevice(deviceid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ConnexionClient::Is3dmouseAttached()) {
|
if (!Is3dmouseAttached()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -312,7 +307,7 @@ bool ConnexionClient::RawInputEventFilter(void* msg, long* result) {
|
||||||
|
|
||||||
if (message->message == WM_INPUT) {
|
if (message->message == WM_INPUT) {
|
||||||
HRAWINPUT hRawInput = reinterpret_cast<HRAWINPUT>(message->lParam);
|
HRAWINPUT hRawInput = reinterpret_cast<HRAWINPUT>(message->lParam);
|
||||||
gMouseInput->OnRawInput(RIM_INPUT, hRawInput);
|
OnRawInput(RIM_INPUT, hRawInput);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
result = 0;
|
result = 0;
|
||||||
}
|
}
|
||||||
|
@ -321,14 +316,6 @@ bool ConnexionClient::RawInputEventFilter(void* msg, long* result) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnexionClient::ConnexionClient() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnexionClient::~ConnexionClient() {
|
|
||||||
QAbstractEventDispatcher::instance()->removeNativeEventFilter(&this);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Access the mouse parameters structure
|
// Access the mouse parameters structure
|
||||||
I3dMouseParam& ConnexionClient::MouseParams() {
|
I3dMouseParam& ConnexionClient::MouseParams() {
|
||||||
return f3dMouseParams;
|
return f3dMouseParams;
|
||||||
|
@ -808,10 +795,6 @@ MouseParameters::MouseParameters() :
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MouseParameters::~MouseParameters()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MouseParameters::IsPanZoom() const {
|
bool MouseParameters::IsPanZoom() const {
|
||||||
return fIsPanZoom;
|
return fIsPanZoom;
|
||||||
}
|
}
|
||||||
|
@ -881,11 +864,11 @@ static void DeviceRemovedHandler(unsigned int connection);
|
||||||
static void MessageHandler(unsigned int connection, unsigned int messageType, void *messageArgument);
|
static void MessageHandler(unsigned int connection, unsigned int messageType, void *messageArgument);
|
||||||
|
|
||||||
void ConnexionClient::toggleConnexion(bool shouldEnable) {
|
void ConnexionClient::toggleConnexion(bool shouldEnable) {
|
||||||
if (shouldEnable && !ConnexionClient::Is3dmouseAttached()) {
|
if (shouldEnable && !Is3dmouseAttached()) {
|
||||||
ConnexionClient::init();
|
init();
|
||||||
}
|
}
|
||||||
if (!shouldEnable && ConnexionClient::Is3dmouseAttached()) {
|
if (!shouldEnable && Is3dmouseAttached()) {
|
||||||
ConnexionClient::destroy();
|
destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,7 +891,7 @@ void ConnexionClient::init() {
|
||||||
// use default switches
|
// use default switches
|
||||||
ConnexionClientControl(fConnexionClientID, kConnexionCtlSetSwitches, kConnexionSwitchesDisabled, NULL);
|
ConnexionClientControl(fConnexionClientID, kConnexionCtlSetSwitches, kConnexionSwitchesDisabled, NULL);
|
||||||
|
|
||||||
if (ConnexionClient::Is3dmouseAttached() && connexiondata.getDeviceID() == 0) {
|
if (Is3dmouseAttached() && connexiondata.getDeviceID() == 0) {
|
||||||
connexiondata.registerToUserInputMapper(*Application::getUserInputMapper());
|
connexiondata.registerToUserInputMapper(*Application::getUserInputMapper());
|
||||||
connexiondata.assignDefaultInputMapping(*Application::getUserInputMapper());
|
connexiondata.assignDefaultInputMapping(*Application::getUserInputMapper());
|
||||||
UserActivityLogger::getInstance().connectedDevice("controller", "3Dconnexion");
|
UserActivityLogger::getInstance().connectedDevice("controller", "3Dconnexion");
|
||||||
|
|
|
@ -23,9 +23,9 @@ class ConnexionClient : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
static ConnexionClient& getInstance();
|
static ConnexionClient& getInstance();
|
||||||
static void init() {};
|
void init() {};
|
||||||
static void destroy() {};
|
void destroy() {};
|
||||||
static bool Is3dmouseAttached() { return false; };
|
bool Is3dmouseAttached() { return false; };
|
||||||
public slots:
|
public slots:
|
||||||
void toggleConnexion(bool shouldEnable) {};
|
void toggleConnexion(bool shouldEnable) {};
|
||||||
};
|
};
|
||||||
|
@ -33,7 +33,7 @@ public slots:
|
||||||
|
|
||||||
#ifdef HAVE_3DCONNEXIONCLIENT
|
#ifdef HAVE_3DCONNEXIONCLIENT
|
||||||
// the windows connexion rawinput
|
// the windows connexion rawinput
|
||||||
#ifdef _WIN32
|
#ifdef Q_OS_WIN
|
||||||
|
|
||||||
#include "I3dMouseParams.h"
|
#include "I3dMouseParams.h"
|
||||||
#include <QAbstractNativeEventFilter>
|
#include <QAbstractNativeEventFilter>
|
||||||
|
@ -45,7 +45,6 @@ public slots:
|
||||||
class MouseParameters : public I3dMouseParam {
|
class MouseParameters : public I3dMouseParam {
|
||||||
public:
|
public:
|
||||||
MouseParameters();
|
MouseParameters();
|
||||||
~MouseParameters();
|
|
||||||
|
|
||||||
// I3dmouseSensor interface
|
// I3dmouseSensor interface
|
||||||
bool IsPanZoom() const;
|
bool IsPanZoom() const;
|
||||||
|
@ -86,13 +85,12 @@ private:
|
||||||
class ConnexionClient : public QObject, public QAbstractNativeEventFilter {
|
class ConnexionClient : public QObject, public QAbstractNativeEventFilter {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
ConnexionClient();
|
ConnexionClient() {};
|
||||||
~ConnexionClient();
|
|
||||||
|
|
||||||
static ConnexionClient& getInstance();
|
static ConnexionClient& getInstance();
|
||||||
static void init();
|
void init();
|
||||||
static void destroy();
|
void destroy();
|
||||||
static bool Is3dmouseAttached();
|
bool Is3dmouseAttached();
|
||||||
|
|
||||||
ConnexionClient* client;
|
ConnexionClient* client;
|
||||||
|
|
||||||
|
@ -106,7 +104,7 @@ public:
|
||||||
virtual bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) Q_DECL_OVERRIDE
|
virtual bool nativeEventFilter(const QByteArray& eventType, void* message, long* result) Q_DECL_OVERRIDE
|
||||||
{
|
{
|
||||||
MSG* msg = static_cast< MSG * >(message);
|
MSG* msg = static_cast< MSG * >(message);
|
||||||
return ConnexionClient::RawInputEventFilter(message, result);
|
return RawInputEventFilter(message, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
@ -120,7 +118,7 @@ signals:
|
||||||
private:
|
private:
|
||||||
bool InitializeRawInput(HWND hwndTarget);
|
bool InitializeRawInput(HWND hwndTarget);
|
||||||
|
|
||||||
static bool RawInputEventFilter(void* msg, long* result);
|
bool RawInputEventFilter(void* msg, long* result);
|
||||||
|
|
||||||
void OnRawInput(UINT nInputCode, HRAWINPUT hRawInput);
|
void OnRawInput(UINT nInputCode, HRAWINPUT hRawInput);
|
||||||
UINT GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader);
|
UINT GetRawInputBuffer(PRAWINPUT pData, PUINT pcbSize, UINT cbSizeHeader);
|
||||||
|
@ -165,9 +163,9 @@ class ConnexionClient : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
static ConnexionClient& getInstance();
|
static ConnexionClient& getInstance();
|
||||||
static void init();
|
void init();
|
||||||
static void destroy();
|
void destroy();
|
||||||
static bool Is3dmouseAttached();
|
bool Is3dmouseAttached();
|
||||||
public slots:
|
public slots:
|
||||||
void toggleConnexion(bool shouldEnable);
|
void toggleConnexion(bool shouldEnable);
|
||||||
};
|
};
|
||||||
|
|
|
@ -564,6 +564,13 @@ void DdeFaceTracker::decodePacket(const QByteArray& buffer) {
|
||||||
eyeCoefficients[1] = _filteredEyeBlinks[1];
|
eyeCoefficients[1] = _filteredEyeBlinks[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Couple eyelid values if configured - use the most "open" value for both
|
||||||
|
if (Menu::getInstance()->isOptionChecked(MenuOption::CoupleEyelids)) {
|
||||||
|
float eyeCoefficient = std::min(eyeCoefficients[0], eyeCoefficients[1]);
|
||||||
|
eyeCoefficients[0] = eyeCoefficient;
|
||||||
|
eyeCoefficients[1] = eyeCoefficient;
|
||||||
|
}
|
||||||
|
|
||||||
// Use EyeBlink values to control both EyeBlink and EyeOpen
|
// Use EyeBlink values to control both EyeBlink and EyeOpen
|
||||||
if (eyeCoefficients[0] > 0) {
|
if (eyeCoefficients[0] > 0) {
|
||||||
_coefficients[_leftBlinkIndex] = eyeCoefficients[0];
|
_coefficients[_leftBlinkIndex] = eyeCoefficients[0];
|
||||||
|
|
|
@ -49,7 +49,7 @@ void AnimationHandle::setMaskedJoints(const QStringList& maskedJoints) {
|
||||||
_jointMappings.clear();
|
_jointMappings.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationHandle::setRunning(bool running) {
|
void AnimationHandle::setRunning(bool running, bool doRestoreJoints) {
|
||||||
if (running && isRunning()) {
|
if (running && isRunning()) {
|
||||||
// if we're already running, this is the same as a restart
|
// if we're already running, this is the same as a restart
|
||||||
setFrameIndex(getFirstFrame());
|
setFrameIndex(getFirstFrame());
|
||||||
|
@ -62,7 +62,9 @@ void AnimationHandle::setRunning(bool running) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_rig->removeRunningAnimation(getAnimationHandlePointer());
|
_rig->removeRunningAnimation(getAnimationHandlePointer());
|
||||||
|
if (doRestoreJoints) {
|
||||||
restoreJoints();
|
restoreJoints();
|
||||||
|
}
|
||||||
replaceMatchingPriorities(0.0f);
|
replaceMatchingPriorities(0.0f);
|
||||||
}
|
}
|
||||||
emit runningChanged(isRunning());
|
emit runningChanged(isRunning());
|
||||||
|
@ -71,7 +73,9 @@ void AnimationHandle::setRunning(bool running) {
|
||||||
AnimationHandle::AnimationHandle(RigPointer rig) :
|
AnimationHandle::AnimationHandle(RigPointer rig) :
|
||||||
QObject(rig.get()),
|
QObject(rig.get()),
|
||||||
_rig(rig),
|
_rig(rig),
|
||||||
_priority(1.0f)
|
_priority(1.0f),
|
||||||
|
_fade(0.0f),
|
||||||
|
_fadePerSecond(0.0f)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,6 +64,10 @@ public:
|
||||||
void setPriority(float priority);
|
void setPriority(float priority);
|
||||||
float getPriority() const { return _priority; }
|
float getPriority() const { return _priority; }
|
||||||
void setMix(float mix) { _mix = mix; }
|
void setMix(float mix) { _mix = mix; }
|
||||||
|
void setFade(float fade) { _fade = fade; }
|
||||||
|
float getFade() const { return _fade; }
|
||||||
|
void setFadePerSecond(float fadePerSecond) { _fadePerSecond = fadePerSecond; }
|
||||||
|
float getFadePerSecond() const { return _fadePerSecond; }
|
||||||
|
|
||||||
void setMaskedJoints(const QStringList& maskedJoints);
|
void setMaskedJoints(const QStringList& maskedJoints);
|
||||||
const QStringList& getMaskedJoints() const { return _maskedJoints; }
|
const QStringList& getMaskedJoints() const { return _maskedJoints; }
|
||||||
|
@ -87,7 +91,7 @@ public:
|
||||||
void setLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); }
|
void setLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); }
|
||||||
float getLastFrame() const { return _animationLoop.getLastFrame(); }
|
float getLastFrame() const { return _animationLoop.getLastFrame(); }
|
||||||
|
|
||||||
void setRunning(bool running);
|
void setRunning(bool running, bool restoreJoints = true);
|
||||||
bool isRunning() const { return _animationLoop.isRunning(); }
|
bool isRunning() const { return _animationLoop.isRunning(); }
|
||||||
|
|
||||||
void setFrameIndex(float frameIndex) { _animationLoop.setFrameIndex(frameIndex); }
|
void setFrameIndex(float frameIndex) { _animationLoop.setFrameIndex(frameIndex); }
|
||||||
|
@ -111,7 +115,7 @@ signals:
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
void start() { setRunning(true); }
|
void start() { setRunning(true); }
|
||||||
void stop() { setRunning(false); }
|
void stop() { setRunning(false); _fadePerSecond = _fade = 0.0f; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -120,7 +124,9 @@ private:
|
||||||
QString _role;
|
QString _role;
|
||||||
QUrl _url;
|
QUrl _url;
|
||||||
float _priority;
|
float _priority;
|
||||||
float _mix;
|
float _mix; // How much of this animation to blend against what is already there. 1.0 sets to just this animation.
|
||||||
|
float _fade; // How far are we into full strength. 0.0 uses none of this animation, 1.0 (the max) is as much as possible.
|
||||||
|
float _fadePerSecond; // How fast should _fade change? +1.0 means _fade is increasing to 1.0 in 1 second. Negative is fading out.
|
||||||
|
|
||||||
QStringList _maskedJoints;
|
QStringList _maskedJoints;
|
||||||
QVector<int> _jointMappings;
|
QVector<int> _jointMappings;
|
||||||
|
|
|
@ -20,15 +20,81 @@ void AvatarRig::updateJointState(int index, glm::mat4 parentTransform) {
|
||||||
const FBXJoint& joint = state.getFBXJoint();
|
const FBXJoint& joint = state.getFBXJoint();
|
||||||
|
|
||||||
// compute model transforms
|
// compute model transforms
|
||||||
int parentIndex = joint.parentIndex;
|
if (index == _rootJointIndex) {
|
||||||
if (parentIndex == -1) {
|
// we always zero-out the translation part of an avatar's root join-transform.
|
||||||
state.computeTransform(parentTransform);
|
state.computeTransform(parentTransform);
|
||||||
clearJointTransformTranslation(index);
|
clearJointTransformTranslation(index);
|
||||||
} else {
|
} else {
|
||||||
// guard against out-of-bounds access to _jointStates
|
// guard against out-of-bounds access to _jointStates
|
||||||
if (joint.parentIndex >= 0 && joint.parentIndex < _jointStates.size()) {
|
int parentIndex = joint.parentIndex;
|
||||||
|
if (parentIndex >= 0 && parentIndex < _jointStates.size()) {
|
||||||
const JointState& parentState = _jointStates.at(parentIndex);
|
const JointState& parentState = _jointStates.at(parentIndex);
|
||||||
state.computeTransform(parentState.getTransform(), parentState.getTransformChanged());
|
state.computeTransform(parentState.getTransform(), parentState.getTransformChanged());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AvatarRig::setHandPosition(int jointIndex,
|
||||||
|
const glm::vec3& position, const glm::quat& rotation,
|
||||||
|
float scale, float priority) {
|
||||||
|
bool rightHand = (jointIndex == _rightHandJointIndex);
|
||||||
|
|
||||||
|
int elbowJointIndex = rightHand ? _rightElbowJointIndex : _leftElbowJointIndex;
|
||||||
|
int shoulderJointIndex = rightHand ? _rightShoulderJointIndex : _leftShoulderJointIndex;
|
||||||
|
|
||||||
|
// this algorithm is from sample code from sixense
|
||||||
|
if (elbowJointIndex == -1 || shoulderJointIndex == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 shoulderPosition;
|
||||||
|
if (!getJointPosition(shoulderJointIndex, shoulderPosition)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// precomputed lengths
|
||||||
|
float upperArmLength = _jointStates[elbowJointIndex].getFBXJoint().distanceToParent * scale;
|
||||||
|
float lowerArmLength = _jointStates[jointIndex].getFBXJoint().distanceToParent * scale;
|
||||||
|
|
||||||
|
// first set wrist position
|
||||||
|
glm::vec3 wristPosition = position;
|
||||||
|
|
||||||
|
glm::vec3 shoulderToWrist = wristPosition - shoulderPosition;
|
||||||
|
float distanceToWrist = glm::length(shoulderToWrist);
|
||||||
|
|
||||||
|
// prevent gimbal lock
|
||||||
|
if (distanceToWrist > upperArmLength + lowerArmLength - EPSILON) {
|
||||||
|
distanceToWrist = upperArmLength + lowerArmLength - EPSILON;
|
||||||
|
shoulderToWrist = glm::normalize(shoulderToWrist) * distanceToWrist;
|
||||||
|
wristPosition = shoulderPosition + shoulderToWrist;
|
||||||
|
}
|
||||||
|
|
||||||
|
// cosine of angle from upper arm to hand vector
|
||||||
|
float cosA = (upperArmLength * upperArmLength + distanceToWrist * distanceToWrist - lowerArmLength * lowerArmLength) /
|
||||||
|
(2 * upperArmLength * distanceToWrist);
|
||||||
|
float mid = upperArmLength * cosA;
|
||||||
|
float height = sqrt(upperArmLength * upperArmLength + mid * mid - 2 * upperArmLength * mid * cosA);
|
||||||
|
|
||||||
|
// direction of the elbow
|
||||||
|
glm::vec3 handNormal = glm::cross(rotation * glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow rotating with wrist
|
||||||
|
glm::vec3 relaxedNormal = glm::cross(glm::vec3(0.0f, 1.0f, 0.0f), shoulderToWrist); // elbow pointing straight down
|
||||||
|
const float NORMAL_WEIGHT = 0.5f;
|
||||||
|
glm::vec3 finalNormal = glm::mix(relaxedNormal, handNormal, NORMAL_WEIGHT);
|
||||||
|
|
||||||
|
if (rightHand ? (finalNormal.y > 0.0f) : (finalNormal.y < 0.0f)) {
|
||||||
|
finalNormal.y = 0.0f; // dont allow elbows to point inward (y is vertical axis)
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 tangent = glm::normalize(glm::cross(shoulderToWrist, finalNormal));
|
||||||
|
|
||||||
|
// ik solution
|
||||||
|
glm::vec3 elbowPosition = shoulderPosition + glm::normalize(shoulderToWrist) * mid - tangent * height;
|
||||||
|
glm::vec3 forwardVector(rightHand ? -1.0f : 1.0f, 0.0f, 0.0f);
|
||||||
|
glm::quat shoulderRotation = rotationBetween(forwardVector, elbowPosition - shoulderPosition);
|
||||||
|
|
||||||
|
setJointRotationInBindFrame(shoulderJointIndex, shoulderRotation, priority);
|
||||||
|
setJointRotationInBindFrame(elbowJointIndex,
|
||||||
|
rotationBetween(shoulderRotation * forwardVector, wristPosition - elbowPosition) *
|
||||||
|
shoulderRotation, priority);
|
||||||
|
setJointRotationInBindFrame(jointIndex, rotation, priority);
|
||||||
|
}
|
||||||
|
|
|
@ -22,6 +22,8 @@ class AvatarRig : public Rig {
|
||||||
public:
|
public:
|
||||||
~AvatarRig() {}
|
~AvatarRig() {}
|
||||||
virtual void updateJointState(int index, glm::mat4 parentTransform);
|
virtual void updateJointState(int index, glm::mat4 parentTransform);
|
||||||
|
virtual void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation,
|
||||||
|
float scale, float priority);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AvatarRig_h
|
#endif // hifi_AvatarRig_h
|
||||||
|
|
|
@ -22,6 +22,8 @@ class EntityRig : public Rig {
|
||||||
public:
|
public:
|
||||||
~EntityRig() {}
|
~EntityRig() {}
|
||||||
virtual void updateJointState(int index, glm::mat4 parentTransform);
|
virtual void updateJointState(int index, glm::mat4 parentTransform);
|
||||||
|
virtual void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation,
|
||||||
|
float scale, float priority) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_EntityRig_h
|
#endif // hifi_EntityRig_h
|
||||||
|
|
|
@ -80,7 +80,7 @@ void Rig::startAnimation(const QString& url, float fps, float priority,
|
||||||
handle->start();
|
handle->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::addAnimationByRole(const QString& role, const QString& url, float fps, float priority,
|
AnimationHandlePointer Rig::addAnimationByRole(const QString& role, const QString& url, float fps, float priority,
|
||||||
bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints, bool startAutomatically) {
|
bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints, bool startAutomatically) {
|
||||||
// check for a configured animation for the role
|
// check for a configured animation for the role
|
||||||
//qCDebug(animation) << "addAnimationByRole" << role << url << fps << priority << loop << hold << firstFrame << lastFrame << maskedJoints << startAutomatically;
|
//qCDebug(animation) << "addAnimationByRole" << role << url << fps << priority << loop << hold << firstFrame << lastFrame << maskedJoints << startAutomatically;
|
||||||
|
@ -89,7 +89,7 @@ void Rig::addAnimationByRole(const QString& role, const QString& url, float fps,
|
||||||
if (startAutomatically) {
|
if (startAutomatically) {
|
||||||
candidate->start();
|
candidate->start();
|
||||||
}
|
}
|
||||||
return;
|
return candidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AnimationHandlePointer handle = createAnimationHandle();
|
AnimationHandlePointer handle = createAnimationHandle();
|
||||||
|
@ -131,16 +131,18 @@ void Rig::addAnimationByRole(const QString& role, const QString& url, float fps,
|
||||||
if (startAutomatically) {
|
if (startAutomatically) {
|
||||||
handle->start();
|
handle->start();
|
||||||
}
|
}
|
||||||
|
return handle;
|
||||||
}
|
}
|
||||||
void Rig::startAnimationByRole(const QString& role, const QString& url, float fps, float priority,
|
void Rig::startAnimationByRole(const QString& role, const QString& url, float fps, float priority,
|
||||||
bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints) {
|
bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints) {
|
||||||
addAnimationByRole(role, url, fps, priority, loop, hold, firstFrame, lastFrame, maskedJoints, true);
|
AnimationHandlePointer handle = addAnimationByRole(role, url, fps, priority, loop, hold, firstFrame, lastFrame, maskedJoints, true);
|
||||||
|
handle->setFadePerSecond(1.0f); // For now. Could be individualized later.
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::stopAnimationByRole(const QString& role) {
|
void Rig::stopAnimationByRole(const QString& role) {
|
||||||
foreach (const AnimationHandlePointer& handle, getRunningAnimations()) {
|
foreach (const AnimationHandlePointer& handle, getRunningAnimations()) {
|
||||||
if (handle->getRole() == role) {
|
if (handle->getRole() == role) {
|
||||||
handle->stop();
|
handle->setFadePerSecond(-1.0f); // For now. Could be individualized later.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -166,7 +168,7 @@ bool Rig::isRunningAnimation(AnimationHandlePointer animationHandle) {
|
||||||
}
|
}
|
||||||
bool Rig::isRunningRole(const QString& role) { //obviously, there are more efficient ways to do this
|
bool Rig::isRunningRole(const QString& role) { //obviously, there are more efficient ways to do this
|
||||||
for (auto animation : _runningAnimations) {
|
for (auto animation : _runningAnimations) {
|
||||||
if (animation->getRole() == role) {
|
if ((animation->getRole() == role) && (animation->getFadePerSecond() >= 0.0f)) { // Don't count those being faded out
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,8 +182,24 @@ void Rig::deleteAnimations() {
|
||||||
_animationHandles.clear();
|
_animationHandles.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
float Rig::initJointStates(QVector<JointState> states, glm::mat4 parentTransform) {
|
float Rig::initJointStates(QVector<JointState> states, glm::mat4 parentTransform,
|
||||||
|
int rootJointIndex,
|
||||||
|
int leftHandJointIndex,
|
||||||
|
int leftElbowJointIndex,
|
||||||
|
int leftShoulderJointIndex,
|
||||||
|
int rightHandJointIndex,
|
||||||
|
int rightElbowJointIndex,
|
||||||
|
int rightShoulderJointIndex) {
|
||||||
_jointStates = states;
|
_jointStates = states;
|
||||||
|
|
||||||
|
_rootJointIndex = rootJointIndex;
|
||||||
|
_leftHandJointIndex = leftHandJointIndex;
|
||||||
|
_leftElbowJointIndex = leftElbowJointIndex;
|
||||||
|
_leftShoulderJointIndex = leftShoulderJointIndex;
|
||||||
|
_rightHandJointIndex = rightHandJointIndex;
|
||||||
|
_rightElbowJointIndex = rightElbowJointIndex;
|
||||||
|
_rightShoulderJointIndex = rightShoulderJointIndex;
|
||||||
|
|
||||||
initJointTransforms(parentTransform);
|
initJointTransforms(parentTransform);
|
||||||
|
|
||||||
int numStates = _jointStates.size();
|
int numStates = _jointStates.size();
|
||||||
|
@ -428,10 +446,45 @@ void Rig::computeMotionAnimationState(float deltaTime, const glm::vec3& worldPos
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rig::updateAnimations(float deltaTime, glm::mat4 parentTransform) {
|
void Rig::updateAnimations(float deltaTime, glm::mat4 parentTransform) {
|
||||||
int nAnimationsSoFar = 0;
|
|
||||||
|
// First normalize the fades so that they sum to 1.0.
|
||||||
|
// update the fade data in each animation (not normalized as they are an independent propert of animation)
|
||||||
foreach (const AnimationHandlePointer& handle, _runningAnimations) {
|
foreach (const AnimationHandlePointer& handle, _runningAnimations) {
|
||||||
handle->setMix(1.0f / ++nAnimationsSoFar);
|
float fadePerSecond = handle->getFadePerSecond();
|
||||||
handle->setPriority(1.0);
|
float fade = handle->getFade();
|
||||||
|
if (fadePerSecond != 0.0f) {
|
||||||
|
fade += fadePerSecond * deltaTime;
|
||||||
|
if ((0.0f >= fade) || (fade >= 1.0f)) {
|
||||||
|
fade = glm::clamp(fade, 0.0f, 1.0f);
|
||||||
|
handle->setFadePerSecond(0.0f);
|
||||||
|
}
|
||||||
|
handle->setFade(fade);
|
||||||
|
if (fade <= 0.0f) { // stop any finished animations now
|
||||||
|
handle->setRunning(false, false); // but do not restore joints as it causes a flicker
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sum the remaining fade data
|
||||||
|
float fadeTotal = 0.0f;
|
||||||
|
foreach (const AnimationHandlePointer& handle, _runningAnimations) {
|
||||||
|
fadeTotal += handle->getFade();
|
||||||
|
}
|
||||||
|
float fadeSumSoFar = 0.0f;
|
||||||
|
foreach (const AnimationHandlePointer& handle, _runningAnimations) {
|
||||||
|
handle->setPriority(1.0f);
|
||||||
|
float normalizedFade = handle->getFade() / fadeTotal;
|
||||||
|
// simulate() will blend each animation result into the result so far, based on the pairwise mix at at each step.
|
||||||
|
// i.e., slerp the 'mix' distance from the result so far towards this iteration's animation result.
|
||||||
|
// The formula here for mix is based on the idea that, at each step:
|
||||||
|
// fadeSum is to normalizedFade, as (1 - mix) is to mix
|
||||||
|
// i.e., fadeSumSoFar/normalizedFade = (1 - mix)/mix
|
||||||
|
// Then we solve for mix.
|
||||||
|
// Sanity check: For the first animation, fadeSum = 0, and the mix will always be 1.
|
||||||
|
// Sanity check: For equal blending, the formula is equivalent to mix = 1 / nAnimationsSoFar++
|
||||||
|
float mix = 1.0f / ((fadeSumSoFar / normalizedFade) + 1.0f);
|
||||||
|
assert((0.0f <= mix) && (mix <= 1.0f));
|
||||||
|
fadeSumSoFar += normalizedFade;
|
||||||
|
handle->setMix(mix);
|
||||||
handle->simulate(deltaTime);
|
handle->simulate(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,6 @@
|
||||||
|
|
||||||
class AnimationHandle;
|
class AnimationHandle;
|
||||||
typedef std::shared_ptr<AnimationHandle> AnimationHandlePointer;
|
typedef std::shared_ptr<AnimationHandle> AnimationHandlePointer;
|
||||||
// typedef QWeakPointer<AnimationHandle> WeakAnimationHandlePointer;
|
|
||||||
|
|
||||||
class Rig;
|
class Rig;
|
||||||
typedef std::shared_ptr<Rig> RigPointer;
|
typedef std::shared_ptr<Rig> RigPointer;
|
||||||
|
@ -87,11 +86,18 @@ public:
|
||||||
float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f,
|
float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f,
|
||||||
float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList());
|
float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList());
|
||||||
void stopAnimationByRole(const QString& role);
|
void stopAnimationByRole(const QString& role);
|
||||||
void addAnimationByRole(const QString& role, const QString& url = QString(), float fps = 30.0f,
|
AnimationHandlePointer addAnimationByRole(const QString& role, const QString& url = QString(), float fps = 30.0f,
|
||||||
float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f,
|
float priority = 1.0f, bool loop = false, bool hold = false, float firstFrame = 0.0f,
|
||||||
float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList(), bool startAutomatically = false);
|
float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList(), bool startAutomatically = false);
|
||||||
|
|
||||||
float initJointStates(QVector<JointState> states, glm::mat4 parentTransform);
|
float initJointStates(QVector<JointState> states, glm::mat4 parentTransform,
|
||||||
|
int rootJointIndex,
|
||||||
|
int leftHandJointIndex,
|
||||||
|
int leftElbowJointIndex,
|
||||||
|
int leftShoulderJointIndex,
|
||||||
|
int rightHandJointIndex,
|
||||||
|
int rightElbowJointIndex,
|
||||||
|
int rightShoulderJointIndex);
|
||||||
bool jointStatesEmpty() { return _jointStates.isEmpty(); };
|
bool jointStatesEmpty() { return _jointStates.isEmpty(); };
|
||||||
int getJointStateCount() const { return _jointStates.size(); }
|
int getJointStateCount() const { return _jointStates.size(); }
|
||||||
int indexOfJoint(const QString& jointName) ;
|
int indexOfJoint(const QString& jointName) ;
|
||||||
|
@ -150,6 +156,9 @@ public:
|
||||||
|
|
||||||
void updateFromHeadParameters(const HeadParameters& params);
|
void updateFromHeadParameters(const HeadParameters& params);
|
||||||
|
|
||||||
|
virtual void setHandPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation,
|
||||||
|
float scale, float priority) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist);
|
void updateLeanJoint(int index, float leanSideways, float leanForward, float torsoTwist);
|
||||||
|
@ -157,6 +166,15 @@ public:
|
||||||
void updateEyeJoint(int index, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade);
|
void updateEyeJoint(int index, const glm::quat& worldHeadOrientation, const glm::vec3& lookAt, const glm::vec3& saccade);
|
||||||
|
|
||||||
QVector<JointState> _jointStates;
|
QVector<JointState> _jointStates;
|
||||||
|
int _rootJointIndex = -1;
|
||||||
|
|
||||||
|
int _leftHandJointIndex = -1;
|
||||||
|
int _leftElbowJointIndex = -1;
|
||||||
|
int _leftShoulderJointIndex = -1;
|
||||||
|
|
||||||
|
int _rightHandJointIndex = -1;
|
||||||
|
int _rightElbowJointIndex = -1;
|
||||||
|
int _rightShoulderJointIndex = -1;
|
||||||
|
|
||||||
QList<AnimationHandlePointer> _animationHandles;
|
QList<AnimationHandlePointer> _animationHandles;
|
||||||
QList<AnimationHandlePointer> _runningAnimations;
|
QList<AnimationHandlePointer> _runningAnimations;
|
||||||
|
|
|
@ -71,7 +71,8 @@ CONSTRUCT_PROPERTY(exponent, 0.0f),
|
||||||
CONSTRUCT_PROPERTY(cutoff, ENTITY_ITEM_DEFAULT_CUTOFF),
|
CONSTRUCT_PROPERTY(cutoff, ENTITY_ITEM_DEFAULT_CUTOFF),
|
||||||
CONSTRUCT_PROPERTY(locked, ENTITY_ITEM_DEFAULT_LOCKED),
|
CONSTRUCT_PROPERTY(locked, ENTITY_ITEM_DEFAULT_LOCKED),
|
||||||
CONSTRUCT_PROPERTY(textures, ""),
|
CONSTRUCT_PROPERTY(textures, ""),
|
||||||
CONSTRUCT_PROPERTY(animationSettings, ""),
|
CONSTRUCT_PROPERTY(animationSettings, "{\"firstFrame\":0,\"fps\":30,\"frameIndex\":0,\"hold\":false,"
|
||||||
|
"\"lastFrame\":100000,\"loop\":false,\"running\":false,\"startAutomatically\":false}"),
|
||||||
CONSTRUCT_PROPERTY(userData, ENTITY_ITEM_DEFAULT_USER_DATA),
|
CONSTRUCT_PROPERTY(userData, ENTITY_ITEM_DEFAULT_USER_DATA),
|
||||||
CONSTRUCT_PROPERTY(simulationOwner, SimulationOwner()),
|
CONSTRUCT_PROPERTY(simulationOwner, SimulationOwner()),
|
||||||
CONSTRUCT_PROPERTY(text, TextEntityItem::DEFAULT_TEXT),
|
CONSTRUCT_PROPERTY(text, TextEntityItem::DEFAULT_TEXT),
|
||||||
|
|
|
@ -336,7 +336,7 @@ protected:
|
||||||
// Uniform Stage
|
// Uniform Stage
|
||||||
void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
|
void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
void releaseUniformBuffer(int slot);
|
void releaseUniformBuffer(uint32_t slot);
|
||||||
void resetUniformStage();
|
void resetUniformStage();
|
||||||
struct UniformStageState {
|
struct UniformStageState {
|
||||||
Buffers _buffers;
|
Buffers _buffers;
|
||||||
|
@ -349,7 +349,7 @@ protected:
|
||||||
// Resource Stage
|
// Resource Stage
|
||||||
void do_setResourceTexture(Batch& batch, uint32 paramOffset);
|
void do_setResourceTexture(Batch& batch, uint32 paramOffset);
|
||||||
|
|
||||||
void releaseResourceTexture(int slot);
|
void releaseResourceTexture(uint32_t slot);
|
||||||
void resetResourceStage();
|
void resetResourceStage();
|
||||||
struct ResourceStageState {
|
struct ResourceStageState {
|
||||||
Textures _textures;
|
Textures _textures;
|
||||||
|
|
|
@ -81,7 +81,7 @@ void GLBackend::killInput() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::syncInputStateCache() {
|
void GLBackend::syncInputStateCache() {
|
||||||
for (int i = 0; i < _input._attributeActivation.size(); i++) {
|
for (uint32_t i = 0; i < _input._attributeActivation.size(); i++) {
|
||||||
GLint active = 0;
|
GLint active = 0;
|
||||||
glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &active);
|
glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &active);
|
||||||
_input._attributeActivation[i] = active;
|
_input._attributeActivation[i] = active;
|
||||||
|
@ -244,7 +244,7 @@ void GLBackend::resetInputStage() {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < _input._attributeActivation.size(); i++) {
|
for (uint32_t i = 0; i < _input._attributeActivation.size(); i++) {
|
||||||
glDisableVertexAttribArray(i);
|
glDisableVertexAttribArray(i);
|
||||||
glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 0, 0);
|
glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 0, 0);
|
||||||
}
|
}
|
||||||
|
@ -254,7 +254,7 @@ void GLBackend::resetInputStage() {
|
||||||
_input._invalidFormat = false;
|
_input._invalidFormat = false;
|
||||||
_input._attributeActivation.reset();
|
_input._attributeActivation.reset();
|
||||||
|
|
||||||
for (int i = 0; i < _input._buffers.size(); i++) {
|
for (uint32_t i = 0; i < _input._buffers.size(); i++) {
|
||||||
_input._buffers[i].reset();
|
_input._buffers[i].reset();
|
||||||
_input._bufferOffsets[i] = 0;
|
_input._bufferOffsets[i] = 0;
|
||||||
_input._bufferStrides[i] = 0;
|
_input._bufferStrides[i] = 0;
|
||||||
|
|
|
@ -147,7 +147,7 @@ void GLBackend::resetPipelineStage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GLBackend::releaseUniformBuffer(int slot) {
|
void GLBackend::releaseUniformBuffer(uint32_t slot) {
|
||||||
#if (GPU_FEATURE_PROFILE == GPU_CORE)
|
#if (GPU_FEATURE_PROFILE == GPU_CORE)
|
||||||
auto& buf = _uniform._buffers[slot];
|
auto& buf = _uniform._buffers[slot];
|
||||||
if (buf) {
|
if (buf) {
|
||||||
|
@ -164,7 +164,7 @@ void GLBackend::releaseUniformBuffer(int slot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::resetUniformStage() {
|
void GLBackend::resetUniformStage() {
|
||||||
for (int i = 0; i < _uniform._buffers.size(); i++) {
|
for (uint32_t i = 0; i < _uniform._buffers.size(); i++) {
|
||||||
releaseUniformBuffer(i);
|
releaseUniformBuffer(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +217,7 @@ void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::releaseResourceTexture(int slot) {
|
void GLBackend::releaseResourceTexture(uint32_t slot) {
|
||||||
auto& tex = _resource._textures[slot];
|
auto& tex = _resource._textures[slot];
|
||||||
if (tex) {
|
if (tex) {
|
||||||
auto* object = Backend::getGPUObject<GLBackend::GLTexture>(*tex);
|
auto* object = Backend::getGPUObject<GLBackend::GLTexture>(*tex);
|
||||||
|
@ -234,7 +234,7 @@ void GLBackend::releaseResourceTexture(int slot) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::resetResourceStage() {
|
void GLBackend::resetResourceStage() {
|
||||||
for (int i = 0; i < _resource._textures.size(); i++) {
|
for (uint32_t i = 0; i < _resource._textures.size(); i++) {
|
||||||
releaseResourceTexture(i);
|
releaseResourceTexture(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,8 +147,8 @@ GLBackend::GLShader* compileShader(const Shader& shader) {
|
||||||
char* temp = new char[infoLength] ;
|
char* temp = new char[infoLength] ;
|
||||||
glGetShaderInfoLog(glshader, infoLength, NULL, temp);
|
glGetShaderInfoLog(glshader, infoLength, NULL, temp);
|
||||||
|
|
||||||
qWarning() << "GLShader::compileShader - failed to compile the gl shader object:";
|
qCWarning(gpulogging) << "GLShader::compileShader - failed to compile the gl shader object:";
|
||||||
qWarning() << temp;
|
qCWarning(gpulogging) << temp;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
filestream.open("debugshader.glsl.info.txt");
|
filestream.open("debugshader.glsl.info.txt");
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include <udt/PacketHeaders.h>
|
#include <udt/PacketHeaders.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <PathUtils.h>
|
#include <PathUtils.h>
|
||||||
|
#include <Gzip.h>
|
||||||
|
|
||||||
#include "CoverageMap.h"
|
#include "CoverageMap.h"
|
||||||
#include "OctreeConstants.h"
|
#include "OctreeConstants.h"
|
||||||
|
@ -48,7 +49,7 @@
|
||||||
#include "OctreeLogging.h"
|
#include "OctreeLogging.h"
|
||||||
|
|
||||||
|
|
||||||
QVector<QString> PERSIST_EXTENSIONS = {"svo", "json"};
|
QVector<QString> PERSIST_EXTENSIONS = {"svo", "json", "json.gz"};
|
||||||
|
|
||||||
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {
|
float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) {
|
||||||
return voxelSizeScale / powf(2, renderLevel);
|
return voxelSizeScale / powf(2, renderLevel);
|
||||||
|
@ -1801,13 +1802,19 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Octree::readFromFile(const char* fileName) {
|
bool Octree::readFromFile(const char* fileName) {
|
||||||
bool fileOk = false;
|
|
||||||
|
|
||||||
QString qFileName = findMostRecentFileExtension(fileName, PERSIST_EXTENSIONS);
|
QString qFileName = findMostRecentFileExtension(fileName, PERSIST_EXTENSIONS);
|
||||||
QFile file(qFileName);
|
|
||||||
fileOk = file.open(QIODevice::ReadOnly);
|
|
||||||
|
|
||||||
if(fileOk) {
|
if (qFileName.endsWith(".json.gz")) {
|
||||||
|
return readJSONFromGzippedFile(qFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile file(qFileName);
|
||||||
|
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
qCritical() << "unable to open for reading: " << fileName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
QDataStream fileInputStream(&file);
|
QDataStream fileInputStream(&file);
|
||||||
QFileInfo fileInfo(qFileName);
|
QFileInfo fileInfo(qFileName);
|
||||||
unsigned long fileLength = fileInfo.size();
|
unsigned long fileLength = fileInfo.size();
|
||||||
|
@ -1817,13 +1824,30 @@ bool Octree::readFromFile(const char* fileName) {
|
||||||
|
|
||||||
qCDebug(octree) << "Loading file" << qFileName << "...";
|
qCDebug(octree) << "Loading file" << qFileName << "...";
|
||||||
|
|
||||||
fileOk = readFromStream(fileLength, fileInputStream);
|
bool success = readFromStream(fileLength, fileInputStream);
|
||||||
|
|
||||||
emit importProgress(100);
|
emit importProgress(100);
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fileOk;
|
bool Octree::readJSONFromGzippedFile(QString qFileName) {
|
||||||
|
QFile file(qFileName);
|
||||||
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
|
qCritical() << "Cannot open gzipped json file for reading: " << qFileName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
QByteArray compressedJsonData = file.readAll();
|
||||||
|
QByteArray jsonData;
|
||||||
|
|
||||||
|
if (!gunzip(compressedJsonData, jsonData)) {
|
||||||
|
qCritical() << "json File not in gzip format: " << qFileName;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream jsonStream(jsonData);
|
||||||
|
return readJSONFromStream(-1, jsonStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Octree::readFromURL(const QString& urlString) {
|
bool Octree::readFromURL(const QString& urlString) {
|
||||||
|
@ -1859,18 +1883,17 @@ bool Octree::readFromURL(const QString& urlString) {
|
||||||
|
|
||||||
|
|
||||||
bool Octree::readFromStream(unsigned long streamLength, QDataStream& inputStream) {
|
bool Octree::readFromStream(unsigned long streamLength, QDataStream& inputStream) {
|
||||||
|
// decide if this is binary SVO or JSON-formatted SVO
|
||||||
// decide if this is SVO or JSON
|
|
||||||
QIODevice *device = inputStream.device();
|
QIODevice *device = inputStream.device();
|
||||||
char firstChar;
|
char firstChar;
|
||||||
device->getChar(&firstChar);
|
device->getChar(&firstChar);
|
||||||
device->ungetChar(firstChar);
|
device->ungetChar(firstChar);
|
||||||
|
|
||||||
if (firstChar == (char) PacketType::EntityData) {
|
if (firstChar == (char) PacketType::EntityData) {
|
||||||
qCDebug(octree) << "Reading from SVO Stream length:" << streamLength;
|
qCDebug(octree) << "Reading from binary SVO Stream length:" << streamLength;
|
||||||
return readSVOFromStream(streamLength, inputStream);
|
return readSVOFromStream(streamLength, inputStream);
|
||||||
} else {
|
} else {
|
||||||
qCDebug(octree) << "Reading from JSON Stream length:" << streamLength;
|
qCDebug(octree) << "Reading from JSON SVO Stream length:" << streamLength;
|
||||||
return readJSONFromStream(streamLength, inputStream);
|
return readJSONFromStream(streamLength, inputStream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2005,12 +2028,28 @@ bool Octree::readSVOFromStream(unsigned long streamLength, QDataStream& inputStr
|
||||||
return fileOk;
|
return fileOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Octree::readJSONFromStream(unsigned long streamLength, QDataStream& inputStream) {
|
const int READ_JSON_BUFFER_SIZE = 2048;
|
||||||
char* rawData = new char[streamLength + 1]; // allocate enough room to null terminate
|
|
||||||
inputStream.readRawData(rawData, streamLength);
|
|
||||||
rawData[streamLength] = 0; // make sure we null terminate this string
|
|
||||||
|
|
||||||
QJsonDocument asDocument = QJsonDocument::fromJson(rawData);
|
bool Octree::readJSONFromStream(unsigned long streamLength, QDataStream& inputStream) {
|
||||||
|
// if the data is gzipped we may not have a useful bytesAvailable() result, so just keep reading until
|
||||||
|
// we get an eof. Leave streamLength parameter for consistency.
|
||||||
|
|
||||||
|
QByteArray jsonBuffer;
|
||||||
|
char* rawData = new char[READ_JSON_BUFFER_SIZE];
|
||||||
|
while (true) {
|
||||||
|
int got = inputStream.readRawData(rawData, READ_JSON_BUFFER_SIZE - 1);
|
||||||
|
if (got < 0) {
|
||||||
|
qCritical() << "error while reading from json stream";
|
||||||
|
delete[] rawData;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (got == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
jsonBuffer += QByteArray(rawData, got);
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonDocument asDocument = QJsonDocument::fromJson(jsonBuffer);
|
||||||
QVariant asVariant = asDocument.toVariant();
|
QVariant asVariant = asDocument.toVariant();
|
||||||
QVariantMap asMap = asVariant.toMap();
|
QVariantMap asMap = asVariant.toMap();
|
||||||
readFromMap(asMap);
|
readFromMap(asMap);
|
||||||
|
@ -2028,13 +2067,14 @@ void Octree::writeToFile(const char* fileName, OctreeElement* element, QString p
|
||||||
writeToSVOFile(fileName, element);
|
writeToSVOFile(fileName, element);
|
||||||
} else if (persistAsFileType == "json") {
|
} else if (persistAsFileType == "json") {
|
||||||
writeToJSONFile(cFileName, element);
|
writeToJSONFile(cFileName, element);
|
||||||
|
} else if (persistAsFileType == "json.gz") {
|
||||||
|
writeToJSONFile(cFileName, element, true);
|
||||||
} else {
|
} else {
|
||||||
qCDebug(octree) << "unable to write octree to file of type" << persistAsFileType;
|
qCDebug(octree) << "unable to write octree to file of type" << persistAsFileType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Octree::writeToJSONFile(const char* fileName, OctreeElement* element) {
|
void Octree::writeToJSONFile(const char* fileName, OctreeElement* element, bool doGzip) {
|
||||||
QFile persistFile(fileName);
|
|
||||||
QVariantMap entityDescription;
|
QVariantMap entityDescription;
|
||||||
|
|
||||||
qCDebug(octree, "Saving JSON SVO to file %s...", fileName);
|
qCDebug(octree, "Saving JSON SVO to file %s...", fileName);
|
||||||
|
@ -2053,10 +2093,27 @@ void Octree::writeToJSONFile(const char* fileName, OctreeElement* element) {
|
||||||
|
|
||||||
// store the entity data
|
// store the entity data
|
||||||
bool entityDescriptionSuccess = writeToMap(entityDescription, top, true);
|
bool entityDescriptionSuccess = writeToMap(entityDescription, top, true);
|
||||||
|
if (!entityDescriptionSuccess) {
|
||||||
|
qCritical("Failed to convert Entities to QVariantMap while saving to json.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// convert the QVariantMap to JSON
|
// convert the QVariantMap to JSON
|
||||||
if (entityDescriptionSuccess && persistFile.open(QIODevice::WriteOnly)) {
|
QByteArray jsonData = QJsonDocument::fromVariant(entityDescription).toJson();
|
||||||
persistFile.write(QJsonDocument::fromVariant(entityDescription).toJson());
|
QByteArray jsonDataForFile;
|
||||||
|
|
||||||
|
if (doGzip) {
|
||||||
|
if (!gzip(jsonData, jsonDataForFile, -1)) {
|
||||||
|
qCritical("unable to gzip data while saving to json.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
jsonDataForFile = jsonData;
|
||||||
|
}
|
||||||
|
|
||||||
|
QFile persistFile(fileName);
|
||||||
|
if (persistFile.open(QIODevice::WriteOnly)) {
|
||||||
|
persistFile.write(jsonDataForFile);
|
||||||
} else {
|
} else {
|
||||||
qCritical("Could not write to JSON description of entities.");
|
qCritical("Could not write to JSON description of entities.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -330,7 +330,7 @@ public:
|
||||||
|
|
||||||
// Octree exporters
|
// Octree exporters
|
||||||
void writeToFile(const char* filename, OctreeElement* element = NULL, QString persistAsFileType = "svo");
|
void writeToFile(const char* filename, OctreeElement* element = NULL, QString persistAsFileType = "svo");
|
||||||
void writeToJSONFile(const char* filename, OctreeElement* element = NULL);
|
void writeToJSONFile(const char* filename, OctreeElement* element = NULL, bool doGzip = false);
|
||||||
void writeToSVOFile(const char* filename, OctreeElement* element = NULL);
|
void writeToSVOFile(const char* filename, OctreeElement* element = NULL);
|
||||||
virtual bool writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues) = 0;
|
virtual bool writeToMap(QVariantMap& entityDescription, OctreeElement* element, bool skipDefaultValues) = 0;
|
||||||
|
|
||||||
|
@ -340,6 +340,7 @@ public:
|
||||||
bool readFromStream(unsigned long streamLength, QDataStream& inputStream);
|
bool readFromStream(unsigned long streamLength, QDataStream& inputStream);
|
||||||
bool readSVOFromStream(unsigned long streamLength, QDataStream& inputStream);
|
bool readSVOFromStream(unsigned long streamLength, QDataStream& inputStream);
|
||||||
bool readJSONFromStream(unsigned long streamLength, QDataStream& inputStream);
|
bool readJSONFromStream(unsigned long streamLength, QDataStream& inputStream);
|
||||||
|
bool readJSONFromGzippedFile(QString qFileName);
|
||||||
virtual bool readFromMap(QVariantMap& entityDescription) = 0;
|
virtual bool readFromMap(QVariantMap& entityDescription) = 0;
|
||||||
|
|
||||||
unsigned long getOctreeElementsCount();
|
unsigned long getOctreeElementsCount();
|
||||||
|
|
|
@ -468,7 +468,23 @@ bool Model::updateGeometry() {
|
||||||
void Model::initJointStates(QVector<JointState> states) {
|
void Model::initJointStates(QVector<JointState> states) {
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
|
||||||
_boundingRadius = _rig->initJointStates(states, parentTransform);
|
|
||||||
|
int rootJointIndex = geometry.rootJointIndex;
|
||||||
|
int leftHandJointIndex = geometry.leftHandJointIndex;
|
||||||
|
int leftElbowJointIndex = leftHandJointIndex >= 0 ? geometry.joints.at(leftHandJointIndex).parentIndex : -1;
|
||||||
|
int leftShoulderJointIndex = leftElbowJointIndex >= 0 ? geometry.joints.at(leftElbowJointIndex).parentIndex : -1;
|
||||||
|
int rightHandJointIndex = geometry.rightHandJointIndex;
|
||||||
|
int rightElbowJointIndex = rightHandJointIndex >= 0 ? geometry.joints.at(rightHandJointIndex).parentIndex : -1;
|
||||||
|
int rightShoulderJointIndex = rightElbowJointIndex >= 0 ? geometry.joints.at(rightElbowJointIndex).parentIndex : -1;
|
||||||
|
|
||||||
|
_boundingRadius = _rig->initJointStates(states, parentTransform,
|
||||||
|
rootJointIndex,
|
||||||
|
leftHandJointIndex,
|
||||||
|
leftElbowJointIndex,
|
||||||
|
leftShoulderJointIndex,
|
||||||
|
rightHandJointIndex,
|
||||||
|
rightElbowJointIndex,
|
||||||
|
rightShoulderJointIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||||
|
|
|
@ -4,7 +4,17 @@ set(TARGET_NAME shared)
|
||||||
# TODO: there isn't really a good reason to have Script linked here - let's get what is requiring it out (RegisteredMetaTypes.cpp)
|
# TODO: there isn't really a good reason to have Script linked here - let's get what is requiring it out (RegisteredMetaTypes.cpp)
|
||||||
setup_hifi_library(Gui Network Script Widgets)
|
setup_hifi_library(Gui Network Script Widgets)
|
||||||
|
|
||||||
|
find_package(ZLIB REQUIRED)
|
||||||
|
target_link_libraries(${TARGET_NAME} ${ZLIB_LIBRARIES})
|
||||||
|
|
||||||
add_dependency_external_projects(glm)
|
add_dependency_external_projects(glm)
|
||||||
find_package(GLM REQUIRED)
|
find_package(GLM REQUIRED)
|
||||||
target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS})
|
target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS} ${ZLIB_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
# Birarda will fix this when he finds it.
|
||||||
|
get_filename_component(ZLIB_LIB_DIR "${ZLIB_LIBRARIES}" DIRECTORY)
|
||||||
|
get_filename_component(ZLIB_DIR "${ZLIB_LIB_DIR}" DIRECTORY)
|
||||||
|
set(ZLIB_BIN_DIR "${ZLIB_DIR}/bin")
|
||||||
|
add_paths_to_fixup_libs(${ZLIB_BIN_DIR})
|
||||||
|
endif ()
|
||||||
|
|
153
libraries/shared/src/Gzip.cpp
Normal file
153
libraries/shared/src/Gzip.cpp
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
//
|
||||||
|
// Gzip.cpp
|
||||||
|
// libraries/shared/src
|
||||||
|
//
|
||||||
|
// Created by Seth Alves on 2015-08-03.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <zlib.h>
|
||||||
|
#include "Gzip.h"
|
||||||
|
|
||||||
|
const int GZIP_WINDOWS_BIT = 31;
|
||||||
|
const int GZIP_CHUNK_SIZE = 4096;
|
||||||
|
const int DEFAULT_MEM_LEVEL = 8;
|
||||||
|
|
||||||
|
bool gunzip(QByteArray source, QByteArray &destination) {
|
||||||
|
destination.clear();
|
||||||
|
if (source.length() == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
z_stream strm;
|
||||||
|
strm.zalloc = Z_NULL;
|
||||||
|
strm.zfree = Z_NULL;
|
||||||
|
strm.opaque = Z_NULL;
|
||||||
|
strm.avail_in = 0;
|
||||||
|
strm.next_in = Z_NULL;
|
||||||
|
|
||||||
|
int status = inflateInit2(&strm, GZIP_WINDOWS_BIT);
|
||||||
|
|
||||||
|
if (status != Z_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *sourceData = source.data();
|
||||||
|
int sourceDataLength = source.length();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int chunkSize = qMin(GZIP_CHUNK_SIZE, sourceDataLength);
|
||||||
|
if (chunkSize <= 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
strm.next_in = (unsigned char*)sourceData;
|
||||||
|
strm.avail_in = chunkSize;
|
||||||
|
sourceData += chunkSize;
|
||||||
|
sourceDataLength -= chunkSize;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
char out[GZIP_CHUNK_SIZE];
|
||||||
|
|
||||||
|
strm.next_out = (unsigned char*)out;
|
||||||
|
strm.avail_out = GZIP_CHUNK_SIZE;
|
||||||
|
|
||||||
|
status = inflate(&strm, Z_NO_FLUSH);
|
||||||
|
|
||||||
|
switch (status) {
|
||||||
|
case Z_NEED_DICT:
|
||||||
|
status = Z_DATA_ERROR;
|
||||||
|
case Z_DATA_ERROR:
|
||||||
|
case Z_MEM_ERROR:
|
||||||
|
case Z_STREAM_ERROR:
|
||||||
|
inflateEnd(&strm);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int available = (GZIP_CHUNK_SIZE - strm.avail_out);
|
||||||
|
if (available > 0) {
|
||||||
|
destination.append((char*)out, available);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strm.avail_out != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == Z_STREAM_END) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inflateEnd(&strm);
|
||||||
|
return status == Z_STREAM_END;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gzip(QByteArray source, QByteArray &destination, int compressionLevel) {
|
||||||
|
destination.clear();
|
||||||
|
if (source.length() == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int flushOrFinish = 0;
|
||||||
|
z_stream strm;
|
||||||
|
strm.zalloc = Z_NULL;
|
||||||
|
strm.zfree = Z_NULL;
|
||||||
|
strm.opaque = Z_NULL;
|
||||||
|
strm.next_in = Z_NULL;
|
||||||
|
strm.avail_in = 0;
|
||||||
|
|
||||||
|
int status = deflateInit2(&strm,
|
||||||
|
qMax(Z_DEFAULT_COMPRESSION, qMin(9, compressionLevel)),
|
||||||
|
Z_DEFLATED,
|
||||||
|
GZIP_WINDOWS_BIT,
|
||||||
|
DEFAULT_MEM_LEVEL,
|
||||||
|
Z_DEFAULT_STRATEGY);
|
||||||
|
if (status != Z_OK) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
char *sourceData = source.data();
|
||||||
|
int sourceDataLength = source.length();
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
int chunkSize = qMin(GZIP_CHUNK_SIZE, sourceDataLength);
|
||||||
|
strm.next_in = (unsigned char*)sourceData;
|
||||||
|
strm.avail_in = chunkSize;
|
||||||
|
sourceData += chunkSize;
|
||||||
|
sourceDataLength -= chunkSize;
|
||||||
|
|
||||||
|
if (sourceDataLength <= 0) {
|
||||||
|
flushOrFinish = Z_FINISH;
|
||||||
|
} else {
|
||||||
|
flushOrFinish = Z_NO_FLUSH;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
char out[GZIP_CHUNK_SIZE];
|
||||||
|
strm.next_out = (unsigned char*)out;
|
||||||
|
strm.avail_out = GZIP_CHUNK_SIZE;
|
||||||
|
status = deflate(&strm, flushOrFinish);
|
||||||
|
if (status == Z_STREAM_ERROR) {
|
||||||
|
deflateEnd(&strm);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int available = (GZIP_CHUNK_SIZE - strm.avail_out);
|
||||||
|
if (available > 0) {
|
||||||
|
destination.append((char*)out, available);
|
||||||
|
}
|
||||||
|
if (strm.avail_out != 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flushOrFinish == Z_FINISH) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
deflateEnd(&strm);
|
||||||
|
return status == Z_STREAM_END;
|
||||||
|
}
|
27
libraries/shared/src/Gzip.h
Normal file
27
libraries/shared/src/Gzip.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// Gzip.h
|
||||||
|
// libraries/shared/src
|
||||||
|
//
|
||||||
|
// Created by Seth Alves on 2015-08-03.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef GZIP_H
|
||||||
|
#define GZIP_H
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
|
// The compression level must be Z_DEFAULT_COMPRESSION (-1), or between 0 and
|
||||||
|
// 9: 1 gives best speed, 9 gives best compression, 0 gives no
|
||||||
|
// compression at all (the input data is simply copied a block at a
|
||||||
|
// time). Z_DEFAULT_COMPRESSION requests a default compromise between
|
||||||
|
// speed and compression (currently equivalent to level 6).
|
||||||
|
|
||||||
|
bool gzip(QByteArray source, QByteArray &destination, int compressionLevel = -1); // -1 is Z_DEFAULT_COMPRESSION
|
||||||
|
|
||||||
|
bool gunzip(QByteArray source, QByteArray &destination);
|
||||||
|
|
||||||
|
#endif
|
|
@ -155,7 +155,6 @@ public:
|
||||||
|
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
|
|
||||||
// setFramePosition(QPoint(-1000, 0));
|
|
||||||
resize(QSize(800, 600));
|
resize(QSize(800, 600));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue