mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 08:56:25 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into merge-from-master-6-28-2pm
This commit is contained in:
commit
3293b4c898
52 changed files with 560 additions and 480 deletions
|
@ -150,28 +150,19 @@
|
||||||
"children": []
|
"children": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "hipsManipulatorOverlay",
|
"id": "defaultPoseOverlay",
|
||||||
"type": "overlay",
|
"type": "overlay",
|
||||||
"data": {
|
"data": {
|
||||||
"alpha": 0.0,
|
"alpha": 0.0,
|
||||||
"boneSet": "hipsOnly"
|
"alphaVar": "defaultPoseOverlayAlpha",
|
||||||
|
"boneSet": "fullBody",
|
||||||
|
"boneSetVar": "defaultPoseOverlayBoneSet"
|
||||||
},
|
},
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
"id": "hipsManipulator",
|
"id": "defaultPose",
|
||||||
"type": "manipulator",
|
"type": "defaultPose",
|
||||||
"data": {
|
"data": {
|
||||||
"alpha": 0.0,
|
|
||||||
"alphaVar": "hipsManipulatorAlpha",
|
|
||||||
"joints": [
|
|
||||||
{
|
|
||||||
"jointName": "Hips",
|
|
||||||
"rotationType": "absolute",
|
|
||||||
"translationType": "absolute",
|
|
||||||
"rotationVar": "hipsManipulatorRotation",
|
|
||||||
"translationVar": "hipsManipulatorPosition"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"children": []
|
"children": []
|
||||||
},
|
},
|
||||||
|
|
|
@ -4094,7 +4094,10 @@ void Application::init() {
|
||||||
EntityTreePointer tree = getEntities()->getTree();
|
EntityTreePointer tree = getEntities()->getTree();
|
||||||
if (auto entity = tree->findEntityByEntityItemID(id)) {
|
if (auto entity = tree->findEntityByEntityItemID(id)) {
|
||||||
auto sound = DependencyManager::get<SoundCache>()->getSound(newURL);
|
auto sound = DependencyManager::get<SoundCache>()->getSound(newURL);
|
||||||
entity->setCollisionSound(sound);
|
auto renderable = entity->getRenderableInterface();
|
||||||
|
if (renderable) {
|
||||||
|
renderable->setCollisionSound(sound);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, Qt::QueuedConnection);
|
}, Qt::QueuedConnection);
|
||||||
connect(getMyAvatar().get(), &MyAvatar::newCollisionSoundURL, this, [this](QUrl newURL) {
|
connect(getMyAvatar().get(), &MyAvatar::newCollisionSoundURL, this, [this](QUrl newURL) {
|
||||||
|
|
34
libraries/animation/src/AnimDefaultPose.cpp
Normal file
34
libraries/animation/src/AnimDefaultPose.cpp
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
//
|
||||||
|
// AnimDefaultPose.cpp
|
||||||
|
//
|
||||||
|
// Created by Anthony J. Thibault on 6/26/17.
|
||||||
|
// Copyright (c) 2017 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "AnimDefaultPose.h"
|
||||||
|
|
||||||
|
AnimDefaultPose::AnimDefaultPose(const QString& id) :
|
||||||
|
AnimNode(AnimNode::Type::DefaultPose, id)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimDefaultPose::~AnimDefaultPose() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const AnimPoseVec& AnimDefaultPose::evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) {
|
||||||
|
if (_skeleton) {
|
||||||
|
_poses = _skeleton->getRelativeDefaultPoses();
|
||||||
|
} else {
|
||||||
|
_poses.clear();
|
||||||
|
}
|
||||||
|
return _poses;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AnimPoseVec& AnimDefaultPose::getPosesInternal() const {
|
||||||
|
return _poses;
|
||||||
|
}
|
36
libraries/animation/src/AnimDefaultPose.h
Normal file
36
libraries/animation/src/AnimDefaultPose.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
//
|
||||||
|
// AnimDefaultPose.h
|
||||||
|
//
|
||||||
|
// Created by Anthony J. Thibault on 6/26/17.
|
||||||
|
// Copyright (c) 2017 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_AnimDefaultPose_h
|
||||||
|
#define hifi_AnimDefaultPose_h
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "AnimNode.h"
|
||||||
|
|
||||||
|
// Always returns the default pose of the current skeleton.
|
||||||
|
|
||||||
|
class AnimDefaultPose : public AnimNode {
|
||||||
|
public:
|
||||||
|
AnimDefaultPose(const QString& id);
|
||||||
|
virtual ~AnimDefaultPose() override;
|
||||||
|
|
||||||
|
virtual const AnimPoseVec& evaluate(const AnimVariantMap& animVars, const AnimContext& context, float dt, Triggers& triggersOut) override;
|
||||||
|
protected:
|
||||||
|
// for AnimDebugDraw rendering
|
||||||
|
virtual const AnimPoseVec& getPosesInternal() const override;
|
||||||
|
|
||||||
|
AnimPoseVec _poses;
|
||||||
|
|
||||||
|
// no copies
|
||||||
|
AnimDefaultPose(const AnimDefaultPose&) = delete;
|
||||||
|
AnimDefaultPose& operator=(const AnimDefaultPose&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_AnimDefaultPose_h
|
|
@ -870,9 +870,9 @@ const AnimPoseVec& AnimInverseKinematics::overlay(const AnimVariantMap& animVars
|
||||||
float scaleFactor = ((offsetLength - MIN_HIPS_OFFSET_LENGTH) / offsetLength);
|
float scaleFactor = ((offsetLength - MIN_HIPS_OFFSET_LENGTH) / offsetLength);
|
||||||
glm::vec3 hipsOffset = scaleFactor * _hipsOffset;
|
glm::vec3 hipsOffset = scaleFactor * _hipsOffset;
|
||||||
if (_hipsParentIndex == -1) {
|
if (_hipsParentIndex == -1) {
|
||||||
_relativePoses[_hipsIndex].trans() = underPoses[_hipsIndex].trans() + hipsOffset;
|
_relativePoses[_hipsIndex].trans() = _relativePoses[_hipsIndex].trans() + hipsOffset;
|
||||||
} else {
|
} else {
|
||||||
auto absHipsPose = _skeleton->getAbsolutePose(_hipsIndex, underPoses);
|
auto absHipsPose = _skeleton->getAbsolutePose(_hipsIndex, _relativePoses);
|
||||||
absHipsPose.trans() += hipsOffset;
|
absHipsPose.trans() += hipsOffset;
|
||||||
_relativePoses[_hipsIndex] = _skeleton->getAbsolutePose(_hipsParentIndex, _relativePoses).inverse() * absHipsPose;
|
_relativePoses[_hipsIndex] = _skeleton->getAbsolutePose(_hipsParentIndex, _relativePoses).inverse() * absHipsPose;
|
||||||
}
|
}
|
||||||
|
@ -1732,6 +1732,10 @@ void AnimInverseKinematics::initRelativePosesFromSolutionSource(SolutionSource s
|
||||||
break;
|
break;
|
||||||
case SolutionSource::RelaxToLimitCenterPoses:
|
case SolutionSource::RelaxToLimitCenterPoses:
|
||||||
blendToPoses(_limitCenterPoses, underPoses, RELAX_BLEND_FACTOR);
|
blendToPoses(_limitCenterPoses, underPoses, RELAX_BLEND_FACTOR);
|
||||||
|
// special case for hips: copy over hips pose whether or not IK is enabled.
|
||||||
|
if (_hipsIndex >= 0 && _hipsIndex < (int)_relativePoses.size()) {
|
||||||
|
_relativePoses[_hipsIndex] = _limitCenterPoses[_hipsIndex];
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case SolutionSource::PreviousSolution:
|
case SolutionSource::PreviousSolution:
|
||||||
// do nothing... _relativePoses is already the previous solution
|
// do nothing... _relativePoses is already the previous solution
|
||||||
|
|
|
@ -44,6 +44,7 @@ public:
|
||||||
StateMachine,
|
StateMachine,
|
||||||
Manipulator,
|
Manipulator,
|
||||||
InverseKinematics,
|
InverseKinematics,
|
||||||
|
DefaultPose,
|
||||||
NumTypes
|
NumTypes
|
||||||
};
|
};
|
||||||
using Pointer = std::shared_ptr<AnimNode>;
|
using Pointer = std::shared_ptr<AnimNode>;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "AnimStateMachine.h"
|
#include "AnimStateMachine.h"
|
||||||
#include "AnimManipulator.h"
|
#include "AnimManipulator.h"
|
||||||
#include "AnimInverseKinematics.h"
|
#include "AnimInverseKinematics.h"
|
||||||
|
#include "AnimDefaultPose.h"
|
||||||
|
|
||||||
using NodeLoaderFunc = AnimNode::Pointer (*)(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
using NodeLoaderFunc = AnimNode::Pointer (*)(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
||||||
using NodeProcessFunc = bool (*)(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
using NodeProcessFunc = bool (*)(AnimNode::Pointer node, const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
||||||
|
@ -35,6 +36,7 @@ static AnimNode::Pointer loadOverlayNode(const QJsonObject& jsonObj, const QStri
|
||||||
static AnimNode::Pointer loadStateMachineNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
static AnimNode::Pointer loadStateMachineNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
||||||
static AnimNode::Pointer loadManipulatorNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
static AnimNode::Pointer loadManipulatorNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
||||||
static AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
static AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
||||||
|
static AnimNode::Pointer loadDefaultPoseNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl);
|
||||||
|
|
||||||
// called after children have been loaded
|
// called after children have been loaded
|
||||||
// returns node on success, nullptr on failure.
|
// returns node on success, nullptr on failure.
|
||||||
|
@ -50,6 +52,7 @@ static const char* animNodeTypeToString(AnimNode::Type type) {
|
||||||
case AnimNode::Type::StateMachine: return "stateMachine";
|
case AnimNode::Type::StateMachine: return "stateMachine";
|
||||||
case AnimNode::Type::Manipulator: return "manipulator";
|
case AnimNode::Type::Manipulator: return "manipulator";
|
||||||
case AnimNode::Type::InverseKinematics: return "inverseKinematics";
|
case AnimNode::Type::InverseKinematics: return "inverseKinematics";
|
||||||
|
case AnimNode::Type::DefaultPose: return "defaultPose";
|
||||||
case AnimNode::Type::NumTypes: return nullptr;
|
case AnimNode::Type::NumTypes: return nullptr;
|
||||||
};
|
};
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -109,6 +112,7 @@ static NodeLoaderFunc animNodeTypeToLoaderFunc(AnimNode::Type type) {
|
||||||
case AnimNode::Type::StateMachine: return loadStateMachineNode;
|
case AnimNode::Type::StateMachine: return loadStateMachineNode;
|
||||||
case AnimNode::Type::Manipulator: return loadManipulatorNode;
|
case AnimNode::Type::Manipulator: return loadManipulatorNode;
|
||||||
case AnimNode::Type::InverseKinematics: return loadInverseKinematicsNode;
|
case AnimNode::Type::InverseKinematics: return loadInverseKinematicsNode;
|
||||||
|
case AnimNode::Type::DefaultPose: return loadDefaultPoseNode;
|
||||||
case AnimNode::Type::NumTypes: return nullptr;
|
case AnimNode::Type::NumTypes: return nullptr;
|
||||||
};
|
};
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -123,6 +127,7 @@ static NodeProcessFunc animNodeTypeToProcessFunc(AnimNode::Type type) {
|
||||||
case AnimNode::Type::StateMachine: return processStateMachineNode;
|
case AnimNode::Type::StateMachine: return processStateMachineNode;
|
||||||
case AnimNode::Type::Manipulator: return processDoNothing;
|
case AnimNode::Type::Manipulator: return processDoNothing;
|
||||||
case AnimNode::Type::InverseKinematics: return processDoNothing;
|
case AnimNode::Type::InverseKinematics: return processDoNothing;
|
||||||
|
case AnimNode::Type::DefaultPose: return processDoNothing;
|
||||||
case AnimNode::Type::NumTypes: return nullptr;
|
case AnimNode::Type::NumTypes: return nullptr;
|
||||||
};
|
};
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -347,7 +352,8 @@ static const char* boneSetStrings[AnimOverlay::NumBoneSets] = {
|
||||||
"empty",
|
"empty",
|
||||||
"leftHand",
|
"leftHand",
|
||||||
"rightHand",
|
"rightHand",
|
||||||
"hipsOnly"
|
"hipsOnly",
|
||||||
|
"bothFeet"
|
||||||
};
|
};
|
||||||
|
|
||||||
static AnimOverlay::BoneSet stringToBoneSetEnum(const QString& str) {
|
static AnimOverlay::BoneSet stringToBoneSetEnum(const QString& str) {
|
||||||
|
@ -517,6 +523,11 @@ AnimNode::Pointer loadInverseKinematicsNode(const QJsonObject& jsonObj, const QS
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static AnimNode::Pointer loadDefaultPoseNode(const QJsonObject& jsonObj, const QString& id, const QUrl& jsonUrl) {
|
||||||
|
auto node = std::make_shared<AnimDefaultPose>(id);
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
void buildChildMap(std::map<QString, int>& map, AnimNode::Pointer node) {
|
void buildChildMap(std::map<QString, int>& map, AnimNode::Pointer node) {
|
||||||
for (int i = 0; i < (int)node->getChildCount(); ++i) {
|
for (int i = 0; i < (int)node->getChildCount(); ++i) {
|
||||||
map.insert(std::pair<QString, int>(node->getChild(i)->getID(), i));
|
map.insert(std::pair<QString, int>(node->getChild(i)->getID(), i));
|
||||||
|
|
|
@ -35,6 +35,7 @@ void AnimOverlay::buildBoneSet(BoneSet boneSet) {
|
||||||
case LeftHandBoneSet: buildLeftHandBoneSet(); break;
|
case LeftHandBoneSet: buildLeftHandBoneSet(); break;
|
||||||
case RightHandBoneSet: buildRightHandBoneSet(); break;
|
case RightHandBoneSet: buildRightHandBoneSet(); break;
|
||||||
case HipsOnlyBoneSet: buildHipsOnlyBoneSet(); break;
|
case HipsOnlyBoneSet: buildHipsOnlyBoneSet(); break;
|
||||||
|
case BothFeetBoneSet: buildBothFeetBoneSet(); break;
|
||||||
default:
|
default:
|
||||||
case EmptyBoneSet: buildEmptyBoneSet(); break;
|
case EmptyBoneSet: buildEmptyBoneSet(); break;
|
||||||
}
|
}
|
||||||
|
@ -196,6 +197,20 @@ void AnimOverlay::buildHipsOnlyBoneSet() {
|
||||||
_boneSetVec[hipsJoint] = 1.0f;
|
_boneSetVec[hipsJoint] = 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AnimOverlay::buildBothFeetBoneSet() {
|
||||||
|
assert(_skeleton);
|
||||||
|
buildEmptyBoneSet();
|
||||||
|
int rightFoot = _skeleton->nameToJointIndex("RightFoot");
|
||||||
|
for_each_child_joint(_skeleton, rightFoot, [&](int i) {
|
||||||
|
_boneSetVec[i] = 1.0f;
|
||||||
|
});
|
||||||
|
int leftFoot = _skeleton->nameToJointIndex("LeftFoot");
|
||||||
|
for_each_child_joint(_skeleton, leftFoot, [&](int i) {
|
||||||
|
_boneSetVec[i] = 1.0f;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// for AnimDebugDraw rendering
|
// for AnimDebugDraw rendering
|
||||||
const AnimPoseVec& AnimOverlay::getPosesInternal() const {
|
const AnimPoseVec& AnimOverlay::getPosesInternal() const {
|
||||||
return _poses;
|
return _poses;
|
||||||
|
|
|
@ -38,6 +38,7 @@ public:
|
||||||
LeftHandBoneSet,
|
LeftHandBoneSet,
|
||||||
RightHandBoneSet,
|
RightHandBoneSet,
|
||||||
HipsOnlyBoneSet,
|
HipsOnlyBoneSet,
|
||||||
|
BothFeetBoneSet,
|
||||||
NumBoneSets
|
NumBoneSets
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,6 +78,7 @@ public:
|
||||||
void buildLeftHandBoneSet();
|
void buildLeftHandBoneSet();
|
||||||
void buildRightHandBoneSet();
|
void buildRightHandBoneSet();
|
||||||
void buildHipsOnlyBoneSet();
|
void buildHipsOnlyBoneSet();
|
||||||
|
void buildBothFeetBoneSet();
|
||||||
|
|
||||||
// no copies
|
// no copies
|
||||||
AnimOverlay(const AnimOverlay&) = delete;
|
AnimOverlay(const AnimOverlay&) = delete;
|
||||||
|
|
|
@ -144,38 +144,3 @@ void Animation::animationParseError(int error, QString str) {
|
||||||
finishedLoading(false);
|
finishedLoading(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimationDetails::AnimationDetails() :
|
|
||||||
role(), url(), fps(0.0f), priority(0.0f), loop(false), hold(false),
|
|
||||||
startAutomatically(false), firstFrame(0.0f), lastFrame(0.0f), running(false), currentFrame(0.0f)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimationDetails::AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop,
|
|
||||||
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame) :
|
|
||||||
role(role), url(url), fps(fps), priority(priority), loop(loop), hold(hold),
|
|
||||||
startAutomatically(startAutomatically), firstFrame(firstFrame), lastFrame(lastFrame),
|
|
||||||
running(running), currentFrame(currentFrame)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& details) {
|
|
||||||
QScriptValue obj = engine->newObject();
|
|
||||||
obj.setProperty("role", details.role);
|
|
||||||
obj.setProperty("url", details.url.toString());
|
|
||||||
obj.setProperty("fps", details.fps);
|
|
||||||
obj.setProperty("priority", details.priority);
|
|
||||||
obj.setProperty("loop", details.loop);
|
|
||||||
obj.setProperty("hold", details.hold);
|
|
||||||
obj.setProperty("startAutomatically", details.startAutomatically);
|
|
||||||
obj.setProperty("firstFrame", details.firstFrame);
|
|
||||||
obj.setProperty("lastFrame", details.lastFrame);
|
|
||||||
obj.setProperty("running", details.running);
|
|
||||||
obj.setProperty("currentFrame", details.currentFrame);
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& details) {
|
|
||||||
// nothing for now...
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -107,26 +107,5 @@ private:
|
||||||
QByteArray _data;
|
QByteArray _data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AnimationDetails {
|
|
||||||
public:
|
|
||||||
AnimationDetails();
|
|
||||||
AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop,
|
|
||||||
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame);
|
|
||||||
|
|
||||||
QString role;
|
|
||||||
QUrl url;
|
|
||||||
float fps;
|
|
||||||
float priority;
|
|
||||||
bool loop;
|
|
||||||
bool hold;
|
|
||||||
bool startAutomatically;
|
|
||||||
float firstFrame;
|
|
||||||
float lastFrame;
|
|
||||||
bool running;
|
|
||||||
float currentFrame;
|
|
||||||
};
|
|
||||||
Q_DECLARE_METATYPE(AnimationDetails);
|
|
||||||
QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& event);
|
|
||||||
void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& event);
|
|
||||||
|
|
||||||
#endif // hifi_AnimationCache_h
|
#endif // hifi_AnimationCache_h
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "AnimationLogging.h"
|
#include "AnimationLogging.h"
|
||||||
#include "AnimClip.h"
|
#include "AnimClip.h"
|
||||||
#include "AnimInverseKinematics.h"
|
#include "AnimInverseKinematics.h"
|
||||||
|
#include "AnimOverlay.h"
|
||||||
#include "AnimSkeleton.h"
|
#include "AnimSkeleton.h"
|
||||||
#include "AnimUtil.h"
|
#include "AnimUtil.h"
|
||||||
#include "IKTarget.h"
|
#include "IKTarget.h"
|
||||||
|
@ -1459,13 +1460,28 @@ void Rig::updateFromControllerParameters(const ControllerParameters& params, flo
|
||||||
updateFeet(leftFootEnabled, rightFootEnabled,
|
updateFeet(leftFootEnabled, rightFootEnabled,
|
||||||
params.controllerPoses[ControllerType_LeftFoot], params.controllerPoses[ControllerType_RightFoot]);
|
params.controllerPoses[ControllerType_LeftFoot], params.controllerPoses[ControllerType_RightFoot]);
|
||||||
|
|
||||||
if (hipsEnabled) {
|
// if the hips or the feet are being controlled.
|
||||||
|
if (hipsEnabled || rightFootEnabled || leftFootEnabled) {
|
||||||
|
// for more predictable IK solve from the center of the joint limits, not from the underpose
|
||||||
_animVars.set("solutionSource", (int)AnimInverseKinematics::SolutionSource::RelaxToLimitCenterPoses);
|
_animVars.set("solutionSource", (int)AnimInverseKinematics::SolutionSource::RelaxToLimitCenterPoses);
|
||||||
|
|
||||||
|
// replace the feet animation with the default pose, this is to prevent unexpected toe wiggling.
|
||||||
|
_animVars.set("defaultPoseOverlayAlpha", 1.0f);
|
||||||
|
_animVars.set("defaultPoseOverlayBoneSet", (int)AnimOverlay::BothFeetBoneSet);
|
||||||
|
} else {
|
||||||
|
// augment the IK with the underPose.
|
||||||
|
_animVars.set("solutionSource", (int)AnimInverseKinematics::SolutionSource::RelaxToUnderPoses);
|
||||||
|
|
||||||
|
// feet should follow source animation
|
||||||
|
_animVars.unset("defaultPoseOverlayAlpha");
|
||||||
|
_animVars.unset("defaultPoseOverlayBoneSet");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hipsEnabled) {
|
||||||
_animVars.set("hipsType", (int)IKTarget::Type::RotationAndPosition);
|
_animVars.set("hipsType", (int)IKTarget::Type::RotationAndPosition);
|
||||||
_animVars.set("hipsPosition", params.controllerPoses[ControllerType_Hips].trans());
|
_animVars.set("hipsPosition", params.controllerPoses[ControllerType_Hips].trans());
|
||||||
_animVars.set("hipsRotation", params.controllerPoses[ControllerType_Hips].rot());
|
_animVars.set("hipsRotation", params.controllerPoses[ControllerType_Hips].rot());
|
||||||
} else {
|
} else {
|
||||||
_animVars.set("solutionSource", (int)AnimInverseKinematics::SolutionSource::RelaxToUnderPoses);
|
|
||||||
_animVars.set("hipsType", (int)IKTarget::Type::Unknown);
|
_animVars.set("hipsType", (int)IKTarget::Type::Unknown);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,6 @@ void EntityTreeRenderer::reloadEntityScripts() {
|
||||||
void EntityTreeRenderer::init() {
|
void EntityTreeRenderer::init() {
|
||||||
OctreeProcessor::init();
|
OctreeProcessor::init();
|
||||||
EntityTreePointer entityTree = std::static_pointer_cast<EntityTree>(_tree);
|
EntityTreePointer entityTree = std::static_pointer_cast<EntityTree>(_tree);
|
||||||
entityTree->setFBXService(this);
|
|
||||||
|
|
||||||
if (_wantScripts) {
|
if (_wantScripts) {
|
||||||
resetEntitiesScriptEngine();
|
resetEntitiesScriptEngine();
|
||||||
|
@ -188,7 +187,6 @@ void EntityTreeRenderer::shutdown() {
|
||||||
|
|
||||||
void EntityTreeRenderer::setTree(OctreePointer newTree) {
|
void EntityTreeRenderer::setTree(OctreePointer newTree) {
|
||||||
OctreeProcessor::setTree(newTree);
|
OctreeProcessor::setTree(newTree);
|
||||||
std::static_pointer_cast<EntityTree>(_tree)->setFBXService(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTreeRenderer::update() {
|
void EntityTreeRenderer::update() {
|
||||||
|
@ -373,31 +371,6 @@ bool EntityTreeRenderer::applyLayeredZones() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FBXGeometry* EntityTreeRenderer::getGeometryForEntity(EntityItemPointer entityItem) {
|
|
||||||
const FBXGeometry* result = NULL;
|
|
||||||
|
|
||||||
if (entityItem->getType() == EntityTypes::Model) {
|
|
||||||
std::shared_ptr<RenderableModelEntityItem> modelEntityItem =
|
|
||||||
std::dynamic_pointer_cast<RenderableModelEntityItem>(entityItem);
|
|
||||||
assert(modelEntityItem); // we need this!!!
|
|
||||||
ModelPointer model = modelEntityItem->getModel(getSharedFromThis());
|
|
||||||
if (model && model->isLoaded()) {
|
|
||||||
result = &model->getFBXGeometry();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
ModelPointer EntityTreeRenderer::getModelForEntityItem(EntityItemPointer entityItem) {
|
|
||||||
ModelPointer result = nullptr;
|
|
||||||
if (entityItem->getType() == EntityTypes::Model) {
|
|
||||||
std::shared_ptr<RenderableModelEntityItem> modelEntityItem =
|
|
||||||
std::dynamic_pointer_cast<RenderableModelEntityItem>(entityItem);
|
|
||||||
result = modelEntityItem->getModel(getSharedFromThis());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EntityTreeRenderer::processEraseMessage(ReceivedMessage& message, const SharedNodePointer& sourceNode) {
|
void EntityTreeRenderer::processEraseMessage(ReceivedMessage& message, const SharedNodePointer& sourceNode) {
|
||||||
std::static_pointer_cast<EntityTree>(_tree)->processEraseMessage(message, sourceNode);
|
std::static_pointer_cast<EntityTree>(_tree)->processEraseMessage(message, sourceNode);
|
||||||
}
|
}
|
||||||
|
@ -889,7 +862,12 @@ void EntityTreeRenderer::checkAndCallPreload(const EntityItemID& entityID, bool
|
||||||
|
|
||||||
void EntityTreeRenderer::playEntityCollisionSound(EntityItemPointer entity, const Collision& collision) {
|
void EntityTreeRenderer::playEntityCollisionSound(EntityItemPointer entity, const Collision& collision) {
|
||||||
assert((bool)entity);
|
assert((bool)entity);
|
||||||
SharedSoundPointer collisionSound = entity->getCollisionSound();
|
auto renderable = entity->getRenderableInterface();
|
||||||
|
if (!renderable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedSoundPointer collisionSound = renderable->getCollisionSound();
|
||||||
if (!collisionSound) {
|
if (!collisionSound) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ using ModelWeakPointer = std::weak_ptr<Model>;
|
||||||
using CalculateEntityLoadingPriority = std::function<float(const EntityItem& item)>;
|
using CalculateEntityLoadingPriority = std::function<float(const EntityItem& item)>;
|
||||||
|
|
||||||
// Generic client side Octree renderer class.
|
// Generic client side Octree renderer class.
|
||||||
class EntityTreeRenderer : public OctreeProcessor, public EntityItemFBXService, public Dependency {
|
class EntityTreeRenderer : public OctreeProcessor, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
|
EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
|
||||||
|
@ -68,9 +68,6 @@ public:
|
||||||
|
|
||||||
virtual void init() override;
|
virtual void init() override;
|
||||||
|
|
||||||
virtual const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) override;
|
|
||||||
virtual ModelPointer getModelForEntityItem(EntityItemPointer entityItem) override;
|
|
||||||
|
|
||||||
/// clears the tree
|
/// clears the tree
|
||||||
virtual void clear() override;
|
virtual void clear() override;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <render/Scene.h>
|
#include <render/Scene.h>
|
||||||
#include <EntityItem.h>
|
#include <EntityItem.h>
|
||||||
|
#include <Sound.h>
|
||||||
#include "AbstractViewStateInterface.h"
|
#include "AbstractViewStateInterface.h"
|
||||||
#include "EntitiesRendererLogging.h"
|
#include "EntitiesRendererLogging.h"
|
||||||
|
|
||||||
|
@ -40,7 +41,11 @@ public:
|
||||||
virtual void render(RenderArgs* args) {};
|
virtual void render(RenderArgs* args) {};
|
||||||
virtual bool addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) = 0;
|
virtual bool addToScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) = 0;
|
||||||
virtual void removeFromScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) = 0;
|
virtual void removeFromScene(const EntityItemPointer& self, const render::ScenePointer& scene, render::Transaction& transaction) = 0;
|
||||||
|
const SharedSoundPointer& getCollisionSound() { return _collisionSound; }
|
||||||
|
void setCollisionSound(const SharedSoundPointer& sound) { _collisionSound = sound; }
|
||||||
virtual RenderableEntityInterface* getRenderableInterface() { return nullptr; }
|
virtual RenderableEntityInterface* getRenderableInterface() { return nullptr; }
|
||||||
|
private:
|
||||||
|
SharedSoundPointer _collisionSound;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RenderableEntityItemProxy {
|
class RenderableEntityItemProxy {
|
||||||
|
|
|
@ -69,11 +69,9 @@ void RenderableModelEntityItem::setModelURL(const QString& url) {
|
||||||
|
|
||||||
void RenderableModelEntityItem::loader() {
|
void RenderableModelEntityItem::loader() {
|
||||||
_needsModelReload = true;
|
_needsModelReload = true;
|
||||||
auto renderer = DependencyManager::get<EntityTreeRenderer>();
|
|
||||||
assert(renderer);
|
|
||||||
{
|
{
|
||||||
PerformanceTimer perfTimer("getModel");
|
PerformanceTimer perfTimer("getModel");
|
||||||
getModel(renderer);
|
getModel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -390,8 +388,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
if (!_model || _needsModelReload) {
|
if (!_model || _needsModelReload) {
|
||||||
// TODO: this getModel() appears to be about 3% of model render time. We should optimize
|
// TODO: this getModel() appears to be about 3% of model render time. We should optimize
|
||||||
PerformanceTimer perfTimer("getModel");
|
PerformanceTimer perfTimer("getModel");
|
||||||
auto renderer = qSharedPointerCast<EntityTreeRenderer>(args->_renderData);
|
getModel();
|
||||||
getModel(renderer);
|
|
||||||
|
|
||||||
// Remap textures immediately after loading to avoid flicker
|
// Remap textures immediately after loading to avoid flicker
|
||||||
remapTextures();
|
remapTextures();
|
||||||
|
@ -483,7 +480,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
auto& currentURL = getParsedModelURL();
|
auto& currentURL = getParsedModelURL();
|
||||||
if (currentURL != _model->getURL()) {
|
if (currentURL != _model->getURL()) {
|
||||||
// Defer setting the url to the render thread
|
// Defer setting the url to the render thread
|
||||||
getModel(_myRenderer);
|
getModel();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -492,16 +489,11 @@ ModelPointer RenderableModelEntityItem::getModelNotSafe() {
|
||||||
return _model;
|
return _model;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelPointer RenderableModelEntityItem::getModel(QSharedPointer<EntityTreeRenderer> renderer) {
|
ModelPointer RenderableModelEntityItem::getModel() {
|
||||||
if (!renderer) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure our renderer is setup
|
// make sure our renderer is setup
|
||||||
if (!_myRenderer) {
|
if (!_myRenderer) {
|
||||||
_myRenderer = renderer;
|
_myRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||||
}
|
}
|
||||||
assert(_myRenderer == renderer); // you should only ever render on one renderer
|
|
||||||
|
|
||||||
if (!_myRenderer || QThread::currentThread() != _myRenderer->thread()) {
|
if (!_myRenderer || QThread::currentThread() != _myRenderer->thread()) {
|
||||||
return _model;
|
return _model;
|
||||||
|
@ -513,7 +505,7 @@ ModelPointer RenderableModelEntityItem::getModel(QSharedPointer<EntityTreeRender
|
||||||
if (!getModelURL().isEmpty()) {
|
if (!getModelURL().isEmpty()) {
|
||||||
// If we don't have a model, allocate one *immediately*
|
// If we don't have a model, allocate one *immediately*
|
||||||
if (!_model) {
|
if (!_model) {
|
||||||
_model = _myRenderer->allocateModel(getModelURL(), renderer->getEntityLoadingPriority(*this), this);
|
_model = _myRenderer->allocateModel(getModelURL(), _myRenderer->getEntityLoadingPriority(*this), this);
|
||||||
_needsInitialSimulation = true;
|
_needsInitialSimulation = true;
|
||||||
// If we need to change URLs, update it *after rendering* (to avoid access violations)
|
// If we need to change URLs, update it *after rendering* (to avoid access violations)
|
||||||
} else if (QUrl(getModelURL()) != _model->getURL()) {
|
} else if (QUrl(getModelURL()) != _model->getURL()) {
|
||||||
|
@ -587,6 +579,17 @@ EntityItemProperties RenderableModelEntityItem::getProperties(EntityPropertyFlag
|
||||||
properties.setRenderInfoHasTransparent(_model->getRenderInfoHasTransparent());
|
properties.setRenderInfoHasTransparent(_model->getRenderInfoHasTransparent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (_model && _model->isLoaded()) {
|
||||||
|
// TODO: improve naturalDimensions in the future,
|
||||||
|
// for now we've added this hack for setting natural dimensions of models
|
||||||
|
Extents meshExtents = _model->getFBXGeometry().getUnscaledMeshExtents();
|
||||||
|
properties.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum);
|
||||||
|
properties.calculateNaturalPosition(meshExtents.minimum, meshExtents.maximum);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1255,3 +1258,27 @@ QStringList RenderableModelEntityItem::getJointNames() const {
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RenderableModelEntityItem::mapJoints(const QStringList& modelJointNames) {
|
||||||
|
// if we don't have animation, or we're already joint mapped then bail early
|
||||||
|
if (!hasAnimation() || jointsMapped()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_animation || _animation->getURL().toString() != getAnimationURL()) {
|
||||||
|
_animation = DependencyManager::get<AnimationCache>()->getAnimation(getAnimationURL());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_animation && _animation->isLoaded()) {
|
||||||
|
QStringList animationJointNames = _animation->getJointNames();
|
||||||
|
|
||||||
|
if (modelJointNames.size() > 0 && animationJointNames.size() > 0) {
|
||||||
|
_jointMapping.resize(modelJointNames.size());
|
||||||
|
for (int i = 0; i < modelJointNames.size(); i++) {
|
||||||
|
_jointMapping[i] = animationJointNames.indexOf(modelJointNames[i]);
|
||||||
|
}
|
||||||
|
_jointMappingCompleted = true;
|
||||||
|
_jointMappingURL = _animationProperties.getURL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
#include <ModelEntityItem.h>
|
#include <ModelEntityItem.h>
|
||||||
|
#include <AnimationCache.h>
|
||||||
|
|
||||||
class Model;
|
class Model;
|
||||||
class EntityTreeRenderer;
|
class EntityTreeRenderer;
|
||||||
|
@ -53,7 +54,7 @@ public:
|
||||||
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||||
BoxFace& face, glm::vec3& surfaceNormal,
|
BoxFace& face, glm::vec3& surfaceNormal,
|
||||||
void** intersectedObject, bool precisionPicking) const override;
|
void** intersectedObject, bool precisionPicking) const override;
|
||||||
ModelPointer getModel(QSharedPointer<EntityTreeRenderer> renderer);
|
ModelPointer getModel();
|
||||||
ModelPointer getModelNotSafe();
|
ModelPointer getModelNotSafe();
|
||||||
|
|
||||||
virtual bool needsToCallUpdate() const override;
|
virtual bool needsToCallUpdate() const override;
|
||||||
|
@ -106,6 +107,15 @@ public:
|
||||||
// Transparency is handled in ModelMeshPartPayload
|
// Transparency is handled in ModelMeshPartPayload
|
||||||
bool isTransparent() override { return false; }
|
bool isTransparent() override { return false; }
|
||||||
|
|
||||||
|
void mapJoints(const QStringList& modelJointNames);
|
||||||
|
bool jointsMapped() const {
|
||||||
|
return _jointMappingURL == getAnimationURL() && _jointMappingCompleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimationPointer getAnimation() const {
|
||||||
|
return _animation;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVariantMap parseTexturesToMap(QString textures);
|
QVariantMap parseTexturesToMap(QString textures);
|
||||||
void remapTextures();
|
void remapTextures();
|
||||||
|
@ -131,6 +141,12 @@ private:
|
||||||
bool _needsJointSimulation { false };
|
bool _needsJointSimulation { false };
|
||||||
bool _showCollisionGeometry { false };
|
bool _showCollisionGeometry { false };
|
||||||
const void* _collisionMeshKey { nullptr };
|
const void* _collisionMeshKey { nullptr };
|
||||||
|
|
||||||
|
// used on client side
|
||||||
|
bool _jointMappingCompleted { false };
|
||||||
|
QVector<int> _jointMapping; // domain is index into model-joints, range is index into animation-joints
|
||||||
|
QString _jointMappingURL;
|
||||||
|
AnimationPointer _animation;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_RenderableModelEntityItem_h
|
#endif // hifi_RenderableModelEntityItem_h
|
||||||
|
|
|
@ -9,11 +9,15 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include "RenderablePolyVoxEntityItem.h"
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QtConcurrent/QtConcurrentRun>
|
#include <QtConcurrent/QtConcurrentRun>
|
||||||
#include <glm/gtx/transform.hpp>
|
#include <glm/gtx/transform.hpp>
|
||||||
|
#include <model-networking/SimpleMeshProxy.h>
|
||||||
#include "ModelScriptingInterface.h"
|
#include "ModelScriptingInterface.h"
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
#if defined(__GNUC__) && !defined(__clang__)
|
||||||
|
@ -52,7 +56,6 @@
|
||||||
#include "EntityTreeRenderer.h"
|
#include "EntityTreeRenderer.h"
|
||||||
#include "polyvox_vert.h"
|
#include "polyvox_vert.h"
|
||||||
#include "polyvox_frag.h"
|
#include "polyvox_frag.h"
|
||||||
#include "RenderablePolyVoxEntityItem.h"
|
|
||||||
#include "EntityEditPacketSender.h"
|
#include "EntityEditPacketSender.h"
|
||||||
#include "PhysicalEntitySimulation.h"
|
#include "PhysicalEntitySimulation.h"
|
||||||
|
|
||||||
|
@ -1626,6 +1629,7 @@ void RenderablePolyVoxEntityItem::locationChanged(bool tellPhysics) {
|
||||||
scene->enqueueTransaction(transaction);
|
scene->enqueueTransaction(transaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) {
|
bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) {
|
||||||
if (!updateDependents()) {
|
if (!updateDependents()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -1645,7 +1649,7 @@ bool RenderablePolyVoxEntityItem::getMeshes(MeshProxyList& result) {
|
||||||
} else {
|
} else {
|
||||||
success = true;
|
success = true;
|
||||||
// the mesh will be in voxel-space. transform it into object-space
|
// the mesh will be in voxel-space. transform it into object-space
|
||||||
meshProxy = new MeshProxy(
|
meshProxy = new SimpleMeshProxy(
|
||||||
_mesh->map([=](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); },
|
_mesh->map([=](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); },
|
||||||
[=](glm::vec3 normal){ return glm::normalize(glm::vec3(transform * glm::vec4(normal, 0.0f))); },
|
[=](glm::vec3 normal){ return glm::normalize(glm::vec3(transform * glm::vec4(normal, 0.0f))); },
|
||||||
[&](uint32_t index){ return index; }));
|
[&](uint32_t index){ return index; }));
|
||||||
|
|
|
@ -12,17 +12,19 @@
|
||||||
#ifndef hifi_RenderablePolyVoxEntityItem_h
|
#ifndef hifi_RenderablePolyVoxEntityItem_h
|
||||||
#define hifi_RenderablePolyVoxEntityItem_h
|
#define hifi_RenderablePolyVoxEntityItem_h
|
||||||
|
|
||||||
#include <QSemaphore>
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
#include <QSemaphore>
|
||||||
|
|
||||||
#include <PolyVoxCore/SimpleVolume.h>
|
#include <PolyVoxCore/SimpleVolume.h>
|
||||||
#include <PolyVoxCore/Raycast.h>
|
#include <PolyVoxCore/Raycast.h>
|
||||||
|
|
||||||
|
#include <gpu/Context.h>
|
||||||
|
#include <model/Forward.h>
|
||||||
#include <TextureCache.h>
|
#include <TextureCache.h>
|
||||||
|
#include <PolyVoxEntityItem.h>
|
||||||
|
|
||||||
#include "PolyVoxEntityItem.h"
|
|
||||||
#include "RenderableEntityItem.h"
|
#include "RenderableEntityItem.h"
|
||||||
#include "gpu/Context.h"
|
|
||||||
|
|
||||||
class PolyVoxPayload {
|
class PolyVoxPayload {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -1,9 +1,3 @@
|
||||||
set(TARGET_NAME entities)
|
set(TARGET_NAME entities)
|
||||||
setup_hifi_library(Network Script)
|
setup_hifi_library(Network Script)
|
||||||
link_hifi_libraries(avatars shared audio octree model model-networking fbx networking animation)
|
link_hifi_libraries(shared networking octree avatars)
|
||||||
include_hifi_library_headers(networking)
|
|
||||||
include_hifi_library_headers(gpu)
|
|
||||||
|
|
||||||
target_bullet()
|
|
||||||
|
|
||||||
include_hifi_library_headers(render)
|
|
||||||
|
|
|
@ -9,12 +9,12 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "AnimationPropertyGroup.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <OctreePacketData.h>
|
#include <OctreePacketData.h>
|
||||||
|
|
||||||
#include <AnimationLoop.h>
|
|
||||||
|
|
||||||
#include "AnimationPropertyGroup.h"
|
|
||||||
#include "EntityItemProperties.h"
|
#include "EntityItemProperties.h"
|
||||||
#include "EntityItemPropertiesMacros.h"
|
#include "EntityItemPropertiesMacros.h"
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
#include <QtScript/QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
|
|
||||||
#include "AnimationLoop.h"
|
#include <shared/types/AnimationLoop.h> // for Animation, AnimationCache, and AnimationPointer classes
|
||||||
#include "EntityItemPropertiesMacros.h"
|
#include "EntityItemPropertiesMacros.h"
|
||||||
#include "PropertyGroup.h"
|
#include "PropertyGroup.h"
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,8 @@
|
||||||
#include <PhysicsHelpers.h>
|
#include <PhysicsHelpers.h>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
#include <SharedUtil.h> // usecTimestampNow()
|
#include <SharedUtil.h> // usecTimestampNow()
|
||||||
#include <SoundCache.h>
|
|
||||||
#include <LogHandler.h>
|
#include <LogHandler.h>
|
||||||
|
#include <Extents.h>
|
||||||
|
|
||||||
#include "EntityScriptingInterface.h"
|
#include "EntityScriptingInterface.h"
|
||||||
#include "EntitiesLogging.h"
|
#include "EntitiesLogging.h"
|
||||||
|
@ -988,21 +988,6 @@ void EntityItem::setCollisionSoundURL(const QString& value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedSoundPointer EntityItem::getCollisionSound() {
|
|
||||||
SharedSoundPointer result;
|
|
||||||
withReadLock([&] {
|
|
||||||
result = _collisionSound;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!result) {
|
|
||||||
result = DependencyManager::get<SoundCache>()->getSound(_collisionSoundURL);
|
|
||||||
withWriteLock([&] {
|
|
||||||
_collisionSound = result;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EntityItem::simulate(const quint64& now) {
|
void EntityItem::simulate(const quint64& now) {
|
||||||
if (getLastSimulated() == 0) {
|
if (getLastSimulated() == 0) {
|
||||||
setLastSimulated(now);
|
setLastSimulated(now);
|
||||||
|
@ -2650,12 +2635,6 @@ QString EntityItem::getCollisionSoundURL() const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::setCollisionSound(SharedSoundPointer sound) {
|
|
||||||
withWriteLock([&] {
|
|
||||||
_collisionSound = sound;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 EntityItem::getRegistrationPoint() const {
|
glm::vec3 EntityItem::getRegistrationPoint() const {
|
||||||
glm::vec3 result;
|
glm::vec3 result;
|
||||||
withReadLock([&] {
|
withReadLock([&] {
|
||||||
|
|
|
@ -19,14 +19,13 @@
|
||||||
|
|
||||||
#include <QtGui/QWindow>
|
#include <QtGui/QWindow>
|
||||||
|
|
||||||
#include <AnimationCache.h> // for Animation, AnimationCache, and AnimationPointer classes
|
#include <shared/types/AnimationLoop.h> // for Animation, AnimationCache, and AnimationPointer classes
|
||||||
#include <Octree.h> // for EncodeBitstreamParams class
|
#include <Octree.h> // for EncodeBitstreamParams class
|
||||||
#include <OctreeElement.h> // for OctreeElement::AppendState
|
#include <OctreeElement.h> // for OctreeElement::AppendState
|
||||||
#include <OctreePacketData.h>
|
#include <OctreePacketData.h>
|
||||||
#include <PhysicsCollisionGroups.h>
|
#include <PhysicsCollisionGroups.h>
|
||||||
#include <ShapeInfo.h>
|
#include <ShapeInfo.h>
|
||||||
#include <Transform.h>
|
#include <Transform.h>
|
||||||
#include <Sound.h>
|
|
||||||
#include <SpatiallyNestable.h>
|
#include <SpatiallyNestable.h>
|
||||||
#include <Interpolate.h>
|
#include <Interpolate.h>
|
||||||
|
|
||||||
|
@ -260,9 +259,6 @@ public:
|
||||||
QString getCollisionSoundURL() const;
|
QString getCollisionSoundURL() const;
|
||||||
void setCollisionSoundURL(const QString& value);
|
void setCollisionSoundURL(const QString& value);
|
||||||
|
|
||||||
SharedSoundPointer getCollisionSound();
|
|
||||||
void setCollisionSound(SharedSoundPointer sound);
|
|
||||||
|
|
||||||
glm::vec3 getRegistrationPoint() const; /// registration point as ratio of entity
|
glm::vec3 getRegistrationPoint() const; /// registration point as ratio of entity
|
||||||
|
|
||||||
/// registration point as ratio of entity
|
/// registration point as ratio of entity
|
||||||
|
@ -526,7 +522,6 @@ protected:
|
||||||
quint64 _loadedScriptTimestamp { ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP + 1 };
|
quint64 _loadedScriptTimestamp { ENTITY_ITEM_DEFAULT_SCRIPT_TIMESTAMP + 1 };
|
||||||
|
|
||||||
QString _collisionSoundURL;
|
QString _collisionSoundURL;
|
||||||
SharedSoundPointer _collisionSound;
|
|
||||||
glm::vec3 _registrationPoint;
|
glm::vec3 _registrationPoint;
|
||||||
float _angularDamping;
|
float _angularDamping;
|
||||||
bool _visible;
|
bool _visible;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "EntityItemID.h"
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
|
@ -17,7 +18,6 @@
|
||||||
#include <UUID.h>
|
#include <UUID.h>
|
||||||
|
|
||||||
#include "RegisteredMetaTypes.h"
|
#include "RegisteredMetaTypes.h"
|
||||||
#include "EntityItemID.h"
|
|
||||||
|
|
||||||
int entityItemIDTypeID = qRegisterMetaType<EntityItemID>();
|
int entityItemIDTypeID = qRegisterMetaType<EntityItemID>();
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <ByteCountCoding.h>
|
#include <ByteCountCoding.h>
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
#include <RegisteredMetaTypes.h>
|
#include <RegisteredMetaTypes.h>
|
||||||
|
#include <Extents.h>
|
||||||
|
|
||||||
#include "EntitiesLogging.h"
|
#include "EntitiesLogging.h"
|
||||||
#include "EntityItem.h"
|
#include "EntityItem.h"
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtx/component_wise.hpp>
|
||||||
|
|
||||||
#include <QtScript/QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include <VariantMapToScriptValue.h>
|
#include <VariantMapToScriptValue.h>
|
||||||
#include <SharedUtil.h>
|
#include <SharedUtil.h>
|
||||||
#include <SpatialParentFinder.h>
|
#include <SpatialParentFinder.h>
|
||||||
#include <model-networking/MeshProxy.h>
|
|
||||||
|
|
||||||
#include "EntitiesLogging.h"
|
#include "EntitiesLogging.h"
|
||||||
#include "EntityDynamicFactoryInterface.h"
|
#include "EntityDynamicFactoryInterface.h"
|
||||||
|
@ -298,18 +297,6 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit
|
||||||
}
|
}
|
||||||
|
|
||||||
results = entity->getProperties(desiredProperties);
|
results = entity->getProperties(desiredProperties);
|
||||||
|
|
||||||
// TODO: improve naturalDimensions in the future,
|
|
||||||
// for now we've added this hack for setting natural dimensions of models
|
|
||||||
if (entity->getType() == EntityTypes::Model) {
|
|
||||||
const FBXGeometry* geometry = _entityTree->getGeometryForEntity(entity);
|
|
||||||
if (geometry) {
|
|
||||||
Extents meshExtents = geometry->getUnscaledMeshExtents();
|
|
||||||
results.setNaturalDimensions(meshExtents.maximum - meshExtents.minimum);
|
|
||||||
results.calculateNaturalPosition(meshExtents.minimum, meshExtents.maximum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,11 +9,15 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <PerfStat.h>
|
#include "EntityTree.h"
|
||||||
#include <QDateTime>
|
#include <QtCore/QDateTime>
|
||||||
|
#include <QtCore/QQueue>
|
||||||
|
|
||||||
#include <QtScript/QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
|
|
||||||
#include "EntityTree.h"
|
#include <PerfStat.h>
|
||||||
|
#include <Extents.h>
|
||||||
|
|
||||||
#include "EntitySimulation.h"
|
#include "EntitySimulation.h"
|
||||||
#include "VariantMapToScriptValue.h"
|
#include "VariantMapToScriptValue.h"
|
||||||
|
|
||||||
|
@ -55,9 +59,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
EntityTree::EntityTree(bool shouldReaverage) :
|
EntityTree::EntityTree(bool shouldReaverage) :
|
||||||
Octree(shouldReaverage),
|
Octree(shouldReaverage)
|
||||||
_fbxService(NULL),
|
|
||||||
_simulation(NULL)
|
|
||||||
{
|
{
|
||||||
resetClientEditStats();
|
resetClientEditStats();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,13 +41,6 @@ public:
|
||||||
virtual void entityCreated(const EntityItem& newEntity, const SharedNodePointer& senderNode) = 0;
|
virtual void entityCreated(const EntityItem& newEntity, const SharedNodePointer& senderNode) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EntityItemFBXService {
|
|
||||||
public:
|
|
||||||
virtual const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) = 0;
|
|
||||||
virtual ModelPointer getModelForEntityItem(EntityItemPointer entityItem) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
class SendEntitiesOperationArgs {
|
class SendEntitiesOperationArgs {
|
||||||
public:
|
public:
|
||||||
glm::vec3 root;
|
glm::vec3 root;
|
||||||
|
@ -189,15 +182,6 @@ public:
|
||||||
int processEraseMessage(ReceivedMessage& message, const SharedNodePointer& sourceNode);
|
int processEraseMessage(ReceivedMessage& message, const SharedNodePointer& sourceNode);
|
||||||
int processEraseMessageDetails(const QByteArray& buffer, const SharedNodePointer& sourceNode);
|
int processEraseMessageDetails(const QByteArray& buffer, const SharedNodePointer& sourceNode);
|
||||||
|
|
||||||
EntityItemFBXService* getFBXService() const { return _fbxService; }
|
|
||||||
void setFBXService(EntityItemFBXService* service) { _fbxService = service; }
|
|
||||||
const FBXGeometry* getGeometryForEntity(EntityItemPointer entityItem) {
|
|
||||||
return _fbxService ? _fbxService->getGeometryForEntity(entityItem) : NULL;
|
|
||||||
}
|
|
||||||
ModelPointer getModelForEntityItem(EntityItemPointer entityItem) {
|
|
||||||
return _fbxService ? _fbxService->getModelForEntityItem(entityItem) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
EntityTreeElementPointer getContainingElement(const EntityItemID& entityItemID) /*const*/;
|
EntityTreeElementPointer getContainingElement(const EntityItemID& entityItemID) /*const*/;
|
||||||
void setContainingElement(const EntityItemID& entityItemID, EntityTreeElementPointer element);
|
void setContainingElement(const EntityItemID& entityItemID, EntityTreeElementPointer element);
|
||||||
void debugDumpMap();
|
void debugDumpMap();
|
||||||
|
@ -325,8 +309,6 @@ protected:
|
||||||
_deletedEntityItemIDs << id;
|
_deletedEntityItemIDs << id;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityItemFBXService* _fbxService;
|
|
||||||
|
|
||||||
mutable QReadWriteLock _entityToElementLock;
|
mutable QReadWriteLock _entityToElementLock;
|
||||||
QHash<EntityItemID, EntityTreeElementPointer> _entityToElementMap;
|
QHash<EntityItemID, EntityTreeElementPointer> _entityToElementMap;
|
||||||
|
|
||||||
|
|
|
@ -9,17 +9,18 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "EntityTreeElement.h"
|
||||||
|
|
||||||
#include <glm/gtx/transform.hpp>
|
#include <glm/gtx/transform.hpp>
|
||||||
|
|
||||||
#include <FBXReader.h>
|
|
||||||
#include <GeometryUtil.h>
|
#include <GeometryUtil.h>
|
||||||
#include <OctreeUtils.h>
|
#include <OctreeUtils.h>
|
||||||
|
#include <Extents.h>
|
||||||
|
|
||||||
#include "EntitiesLogging.h"
|
#include "EntitiesLogging.h"
|
||||||
#include "EntityNodeData.h"
|
#include "EntityNodeData.h"
|
||||||
#include "EntityItemProperties.h"
|
#include "EntityItemProperties.h"
|
||||||
#include "EntityTree.h"
|
#include "EntityTree.h"
|
||||||
#include "EntityTreeElement.h"
|
|
||||||
#include "EntityTypes.h"
|
#include "EntityTypes.h"
|
||||||
|
|
||||||
EntityTreeElement::EntityTreeElement(unsigned char* octalCode) : OctreeElement() {
|
EntityTreeElement::EntityTreeElement(unsigned char* octalCode) : OctreeElement() {
|
||||||
|
|
|
@ -9,12 +9,11 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "KeyLightPropertyGroup.h"
|
||||||
|
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
#include <OctreePacketData.h>
|
#include <OctreePacketData.h>
|
||||||
|
|
||||||
#include <AnimationLoop.h>
|
|
||||||
|
|
||||||
#include "KeyLightPropertyGroup.h"
|
|
||||||
#include "EntityItemProperties.h"
|
#include "EntityItemProperties.h"
|
||||||
#include "EntityItemPropertiesMacros.h"
|
#include "EntityItemPropertiesMacros.h"
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,6 @@ ModelEntityItem::ModelEntityItem(const EntityItemID& entityItemID) : EntityItem(
|
||||||
_animationLoop.setResetOnRunning(false);
|
_animationLoop.setResetOnRunning(false);
|
||||||
|
|
||||||
_type = EntityTypes::Model;
|
_type = EntityTypes::Model;
|
||||||
_jointMappingCompleted = false;
|
|
||||||
_lastKnownCurrentFrame = -1;
|
_lastKnownCurrentFrame = -1;
|
||||||
_color[0] = _color[1] = _color[2] = 0;
|
_color[0] = _color[1] = _color[2] = 0;
|
||||||
}
|
}
|
||||||
|
@ -204,30 +203,6 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void ModelEntityItem::mapJoints(const QStringList& modelJointNames) {
|
|
||||||
// if we don't have animation, or we're already joint mapped then bail early
|
|
||||||
if (!hasAnimation() || jointsMapped()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_animation || _animation->getURL().toString() != getAnimationURL()) {
|
|
||||||
_animation = DependencyManager::get<AnimationCache>()->getAnimation(getAnimationURL());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_animation && _animation->isLoaded()) {
|
|
||||||
QStringList animationJointNames = _animation->getJointNames();
|
|
||||||
|
|
||||||
if (modelJointNames.size() > 0 && animationJointNames.size() > 0) {
|
|
||||||
_jointMapping.resize(modelJointNames.size());
|
|
||||||
for (int i = 0; i < modelJointNames.size(); i++) {
|
|
||||||
_jointMapping[i] = animationJointNames.indexOf(modelJointNames[i]);
|
|
||||||
}
|
|
||||||
_jointMappingCompleted = true;
|
|
||||||
_jointMappingURL = _animationProperties.getURL();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ModelEntityItem::isAnimatingSomething() const {
|
bool ModelEntityItem::isAnimatingSomething() const {
|
||||||
return getAnimationIsPlaying() &&
|
return getAnimationIsPlaying() &&
|
||||||
getAnimationFPS() != 0.0f &&
|
getAnimationFPS() != 0.0f &&
|
||||||
|
|
|
@ -12,8 +12,6 @@
|
||||||
#ifndef hifi_ModelEntityItem_h
|
#ifndef hifi_ModelEntityItem_h
|
||||||
#define hifi_ModelEntityItem_h
|
#define hifi_ModelEntityItem_h
|
||||||
|
|
||||||
#include <AnimationLoop.h>
|
|
||||||
|
|
||||||
#include "EntityItem.h"
|
#include "EntityItem.h"
|
||||||
#include "AnimationPropertyGroup.h"
|
#include "AnimationPropertyGroup.h"
|
||||||
|
|
||||||
|
@ -103,10 +101,7 @@ public:
|
||||||
void setAnimationLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); }
|
void setAnimationLastFrame(float lastFrame) { _animationLoop.setLastFrame(lastFrame); }
|
||||||
float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); }
|
float getAnimationLastFrame() const { return _animationLoop.getLastFrame(); }
|
||||||
|
|
||||||
void mapJoints(const QStringList& modelJointNames);
|
|
||||||
bool jointsMapped() const { return _jointMappingURL == getAnimationURL() && _jointMappingCompleted; }
|
|
||||||
|
|
||||||
AnimationPointer getAnimation() const { return _animation; }
|
|
||||||
bool getAnimationIsPlaying() const { return _animationLoop.getRunning(); }
|
bool getAnimationIsPlaying() const { return _animationLoop.getRunning(); }
|
||||||
float getAnimationCurrentFrame() const { return _animationLoop.getCurrentFrame(); }
|
float getAnimationCurrentFrame() const { return _animationLoop.getCurrentFrame(); }
|
||||||
float getAnimationFPS() const { return _animationLoop.getFPS(); }
|
float getAnimationFPS() const { return _animationLoop.getFPS(); }
|
||||||
|
@ -158,7 +153,6 @@ protected:
|
||||||
QUrl _parsedModelURL;
|
QUrl _parsedModelURL;
|
||||||
QString _compoundShapeURL;
|
QString _compoundShapeURL;
|
||||||
|
|
||||||
AnimationPointer _animation;
|
|
||||||
AnimationPropertyGroup _animationProperties;
|
AnimationPropertyGroup _animationProperties;
|
||||||
AnimationLoop _animationLoop;
|
AnimationLoop _animationLoop;
|
||||||
|
|
||||||
|
@ -166,11 +160,6 @@ protected:
|
||||||
QString _textures;
|
QString _textures;
|
||||||
|
|
||||||
ShapeType _shapeType = SHAPE_TYPE_NONE;
|
ShapeType _shapeType = SHAPE_TYPE_NONE;
|
||||||
|
|
||||||
// used on client side
|
|
||||||
bool _jointMappingCompleted;
|
|
||||||
QVector<int> _jointMapping; // domain is index into model-joints, range is index into animation-joints
|
|
||||||
QString _jointMappingURL;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ModelEntityItem_h
|
#endif // hifi_ModelEntityItem_h
|
||||||
|
|
|
@ -1,44 +0,0 @@
|
||||||
//
|
|
||||||
// MeshFace.cpp
|
|
||||||
// libraries/model/src/model/
|
|
||||||
//
|
|
||||||
// Created by Seth Alves on 2017-3-23
|
|
||||||
// Copyright 2017 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 <RegisteredMetaTypes.h>
|
|
||||||
|
|
||||||
#include "MeshFace.h"
|
|
||||||
|
|
||||||
|
|
||||||
QScriptValue meshFaceToScriptValue(QScriptEngine* engine, const MeshFace &meshFace) {
|
|
||||||
QScriptValue obj = engine->newObject();
|
|
||||||
obj.setProperty("vertices", qVectorIntToScriptValue(engine, meshFace.vertexIndices));
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
void meshFaceFromScriptValue(const QScriptValue &object, MeshFace& meshFaceResult) {
|
|
||||||
qVectorIntFromScriptValue(object.property("vertices"), meshFaceResult.vertexIndices);
|
|
||||||
}
|
|
||||||
|
|
||||||
QScriptValue qVectorMeshFaceToScriptValue(QScriptEngine* engine, const QVector<MeshFace>& vector) {
|
|
||||||
QScriptValue array = engine->newArray();
|
|
||||||
for (int i = 0; i < vector.size(); i++) {
|
|
||||||
array.setProperty(i, meshFaceToScriptValue(engine, vector.at(i)));
|
|
||||||
}
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector<MeshFace>& result) {
|
|
||||||
int length = array.property("length").toInteger();
|
|
||||||
result.clear();
|
|
||||||
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
MeshFace meshFace = MeshFace();
|
|
||||||
meshFaceFromScriptValue(array.property(i), meshFace);
|
|
||||||
result << meshFace;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
//
|
|
||||||
// MeshFace.h
|
|
||||||
// libraries/model/src/model/
|
|
||||||
//
|
|
||||||
// Created by Seth Alves on 2017-3-23
|
|
||||||
// Copyright 2017 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_MeshFace_h
|
|
||||||
#define hifi_MeshFace_h
|
|
||||||
|
|
||||||
#include <QScriptEngine>
|
|
||||||
#include <QScriptValueIterator>
|
|
||||||
#include <QtScript/QScriptValue>
|
|
||||||
|
|
||||||
#include <model/Geometry.h>
|
|
||||||
|
|
||||||
using MeshPointer = std::shared_ptr<model::Mesh>;
|
|
||||||
|
|
||||||
class MeshFace {
|
|
||||||
|
|
||||||
public:
|
|
||||||
MeshFace() {}
|
|
||||||
~MeshFace() {}
|
|
||||||
|
|
||||||
QVector<uint32_t> vertexIndices;
|
|
||||||
// TODO -- material...
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(MeshFace)
|
|
||||||
Q_DECLARE_METATYPE(QVector<MeshFace>)
|
|
||||||
|
|
||||||
QScriptValue meshFaceToScriptValue(QScriptEngine* engine, const MeshFace &meshFace);
|
|
||||||
void meshFaceFromScriptValue(const QScriptValue &object, MeshFace& meshFaceResult);
|
|
||||||
QScriptValue qVectorMeshFaceToScriptValue(QScriptEngine* engine, const QVector<MeshFace>& vector);
|
|
||||||
void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector<MeshFace>& result);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // hifi_MeshFace_h
|
|
|
@ -1,48 +0,0 @@
|
||||||
//
|
|
||||||
// MeshProxy.cpp
|
|
||||||
// libraries/model/src/model/
|
|
||||||
//
|
|
||||||
// Created by Seth Alves on 2017-3-22.
|
|
||||||
// Copyright 2017 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 "MeshProxy.h"
|
|
||||||
|
|
||||||
|
|
||||||
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) {
|
|
||||||
return engine->newQObject(in, QScriptEngine::QtOwnership,
|
|
||||||
QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects);
|
|
||||||
}
|
|
||||||
|
|
||||||
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) {
|
|
||||||
out = qobject_cast<MeshProxy*>(value.toQObject());
|
|
||||||
}
|
|
||||||
|
|
||||||
QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in) {
|
|
||||||
// QScriptValueList result;
|
|
||||||
QScriptValue result = engine->newArray();
|
|
||||||
int i = 0;
|
|
||||||
foreach (MeshProxy* const meshProxy, in) {
|
|
||||||
result.setProperty(i++, meshToScriptValue(engine, meshProxy));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out) {
|
|
||||||
QScriptValueIterator itr(value);
|
|
||||||
|
|
||||||
qDebug() << "in meshesFromScriptValue, value.length =" << value.property("length").toInt32();
|
|
||||||
|
|
||||||
while(itr.hasNext()) {
|
|
||||||
itr.next();
|
|
||||||
MeshProxy* meshProxy = qscriptvalue_cast<MeshProxyList::value_type>(itr.value());
|
|
||||||
if (meshProxy) {
|
|
||||||
out.append(meshProxy);
|
|
||||||
} else {
|
|
||||||
qDebug() << "null meshProxy";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,52 +0,0 @@
|
||||||
//
|
|
||||||
// MeshProxy.h
|
|
||||||
// libraries/model/src/model/
|
|
||||||
//
|
|
||||||
// Created by Seth Alves on 2017-1-27.
|
|
||||||
// Copyright 2017 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_MeshProxy_h
|
|
||||||
#define hifi_MeshProxy_h
|
|
||||||
|
|
||||||
#include <QScriptEngine>
|
|
||||||
#include <QScriptValueIterator>
|
|
||||||
#include <QtScript/QScriptValue>
|
|
||||||
|
|
||||||
#include <model/Geometry.h>
|
|
||||||
|
|
||||||
using MeshPointer = std::shared_ptr<model::Mesh>;
|
|
||||||
|
|
||||||
class MeshProxy : public QObject {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
MeshProxy(MeshPointer mesh) : _mesh(mesh) {}
|
|
||||||
~MeshProxy() {}
|
|
||||||
|
|
||||||
MeshPointer getMeshPointer() const { return _mesh; }
|
|
||||||
|
|
||||||
Q_INVOKABLE int getNumVertices() const { return (int)_mesh->getNumVertices(); }
|
|
||||||
Q_INVOKABLE glm::vec3 getPos3(int index) const { return _mesh->getPos3(index); }
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
MeshPointer _mesh;
|
|
||||||
};
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(MeshProxy*);
|
|
||||||
|
|
||||||
class MeshProxyList : public QList<MeshProxy*> {}; // typedef and using fight with the Qt macros/templates, do this instead
|
|
||||||
Q_DECLARE_METATYPE(MeshProxyList);
|
|
||||||
|
|
||||||
|
|
||||||
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in);
|
|
||||||
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out);
|
|
||||||
|
|
||||||
QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in);
|
|
||||||
void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out);
|
|
||||||
|
|
||||||
#endif // hifi_MeshProxy_h
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// SimpleMeshProxy.cpp
|
||||||
|
// libraries/model-networking/src/model-networking/
|
||||||
|
//
|
||||||
|
// Created by Seth Alves on 2017-3-22.
|
||||||
|
// Copyright 2017 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 "SimpleMeshProxy.h"
|
||||||
|
|
||||||
|
#include <model/Geometry.h>
|
||||||
|
|
||||||
|
MeshPointer SimpleMeshProxy::getMeshPointer() const {
|
||||||
|
return _mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SimpleMeshProxy::getNumVertices() const {
|
||||||
|
return (int)_mesh->getNumVertices();
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::vec3 SimpleMeshProxy::getPos3(int index) const {
|
||||||
|
return _mesh->getPos3(index);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
//
|
||||||
|
// SimpleMeshProxy.h
|
||||||
|
// libraries/model-networking/src/model-networking/
|
||||||
|
//
|
||||||
|
// Created by Seth Alves on 2017-1-27.
|
||||||
|
// Copyright 2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_SimpleMeshProxy_h
|
||||||
|
#define hifi_SimpleMeshProxy_h
|
||||||
|
|
||||||
|
#include <QScriptEngine>
|
||||||
|
#include <QScriptValueIterator>
|
||||||
|
#include <QtScript/QScriptValue>
|
||||||
|
|
||||||
|
#include <RegisteredMetaTypes.h>
|
||||||
|
|
||||||
|
class SimpleMeshProxy : public MeshProxy {
|
||||||
|
public:
|
||||||
|
SimpleMeshProxy(const MeshPointer& mesh) : _mesh(mesh) { }
|
||||||
|
|
||||||
|
MeshPointer getMeshPointer() const override;
|
||||||
|
|
||||||
|
int getNumVertices() const override;
|
||||||
|
|
||||||
|
glm::vec3 getPos3(int index) const override;
|
||||||
|
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const MeshPointer _mesh;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // hifi_SimpleMeshProxy_h
|
19
libraries/model/src/model/Forward.h
Normal file
19
libraries/model/src/model/Forward.h
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
//
|
||||||
|
// Forward.h
|
||||||
|
// libraries/model/src/model
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2017/06/21
|
||||||
|
// Copyright 2013-2017 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#ifndef hifi_model_Forward_h
|
||||||
|
#define hifi_model_Forward_h
|
||||||
|
|
||||||
|
namespace model {
|
||||||
|
class Mesh;
|
||||||
|
using MeshPointer = std::shared_ptr<Mesh>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -9,17 +9,17 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "ModelScriptingInterface.h"
|
||||||
#include <QScriptEngine>
|
#include <QScriptEngine>
|
||||||
#include <QScriptValueIterator>
|
#include <QScriptValueIterator>
|
||||||
#include <QtScript/QScriptValue>
|
#include <QtScript/QScriptValue>
|
||||||
#include <model-networking/MeshFace.h>
|
#include <model-networking/SimpleMeshProxy.h>
|
||||||
#include "ScriptEngine.h"
|
#include "ScriptEngine.h"
|
||||||
#include "ScriptEngineLogging.h"
|
#include "ScriptEngineLogging.h"
|
||||||
#include "ModelScriptingInterface.h"
|
|
||||||
#include "OBJWriter.h"
|
#include "OBJWriter.h"
|
||||||
|
|
||||||
ModelScriptingInterface::ModelScriptingInterface(QObject* parent) : QObject(parent) {
|
ModelScriptingInterface::ModelScriptingInterface(QObject* parent) : QObject(parent) {
|
||||||
_modelScriptEngine = qobject_cast<ScriptEngine*>(parent);
|
_modelScriptEngine = qobject_cast<QScriptEngine*>(parent);
|
||||||
|
|
||||||
qScriptRegisterSequenceMetaType<QList<MeshProxy*>>(_modelScriptEngine);
|
qScriptRegisterSequenceMetaType<QList<MeshProxy*>>(_modelScriptEngine);
|
||||||
qScriptRegisterMetaType(_modelScriptEngine, meshFaceToScriptValue, meshFaceFromScriptValue);
|
qScriptRegisterMetaType(_modelScriptEngine, meshFaceToScriptValue, meshFaceFromScriptValue);
|
||||||
|
@ -118,7 +118,7 @@ QScriptValue ModelScriptingInterface::appendMeshes(MeshProxyList in) {
|
||||||
(gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL));
|
(gpu::Byte*) parts.data()), gpu::Element::PART_DRAWCALL));
|
||||||
|
|
||||||
|
|
||||||
MeshProxy* resultProxy = new MeshProxy(result);
|
MeshProxy* resultProxy = new SimpleMeshProxy(result);
|
||||||
return meshToScriptValue(_modelScriptEngine, resultProxy);
|
return meshToScriptValue(_modelScriptEngine, resultProxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +134,7 @@ QScriptValue ModelScriptingInterface::transformMesh(glm::mat4 transform, MeshPro
|
||||||
model::MeshPointer result = mesh->map([&](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); },
|
model::MeshPointer result = mesh->map([&](glm::vec3 position){ return glm::vec3(transform * glm::vec4(position, 1.0f)); },
|
||||||
[&](glm::vec3 normal){ return glm::vec3(transform * glm::vec4(normal, 0.0f)); },
|
[&](glm::vec3 normal){ return glm::vec3(transform * glm::vec4(normal, 0.0f)); },
|
||||||
[&](uint32_t index){ return index; });
|
[&](uint32_t index){ return index; });
|
||||||
MeshProxy* resultProxy = new MeshProxy(result);
|
MeshProxy* resultProxy = new SimpleMeshProxy(result);
|
||||||
return meshToScriptValue(_modelScriptEngine, resultProxy);
|
return meshToScriptValue(_modelScriptEngine, resultProxy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,6 +188,6 @@ QScriptValue ModelScriptingInterface::newMesh(const QVector<glm::vec3>& vertices
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MeshProxy* meshProxy = new MeshProxy(mesh);
|
MeshProxy* meshProxy = new SimpleMeshProxy(mesh);
|
||||||
return meshToScriptValue(_modelScriptEngine, meshProxy);
|
return meshToScriptValue(_modelScriptEngine, meshProxy);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,19 +9,13 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
#ifndef hifi_ModelScriptingInterface_h
|
#ifndef hifi_ModelScriptingInterface_h
|
||||||
#define hifi_ModelScriptingInterface_h
|
#define hifi_ModelScriptingInterface_h
|
||||||
|
|
||||||
#include <QtCore/QObject>
|
#include <QtCore/QObject>
|
||||||
#include <QScriptValue>
|
|
||||||
#include <OBJWriter.h>
|
|
||||||
#include <model/Geometry.h>
|
|
||||||
#include <model-networking/MeshProxy.h>
|
|
||||||
#include <model-networking/MeshFace.h>
|
|
||||||
|
|
||||||
using MeshPointer = std::shared_ptr<model::Mesh>;
|
#include <RegisteredMetaTypes.h>
|
||||||
class ScriptEngine;
|
class QScriptEngine;
|
||||||
|
|
||||||
class ModelScriptingInterface : public QObject {
|
class ModelScriptingInterface : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -37,7 +31,7 @@ public:
|
||||||
const QVector<MeshFace>& faces);
|
const QVector<MeshFace>& faces);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ScriptEngine* _modelScriptEngine { nullptr };
|
QScriptEngine* _modelScriptEngine { nullptr };
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_ModelScriptingInterface_h
|
#endif // hifi_ModelScriptingInterface_h
|
||||||
|
|
|
@ -1067,24 +1067,21 @@ void ScriptEngine::run() {
|
||||||
// on shutdown and stop... so we want to loop and sleep until we've spent our time in
|
// on shutdown and stop... so we want to loop and sleep until we've spent our time in
|
||||||
// purgatory, constantly checking to see if our script was asked to end
|
// purgatory, constantly checking to see if our script was asked to end
|
||||||
bool processedEvents = false;
|
bool processedEvents = false;
|
||||||
while (!_isFinished && clock::now() < sleepUntil) {
|
if (!_isFinished) {
|
||||||
|
PROFILE_RANGE(script, "processEvents-sleep");
|
||||||
{
|
std::chrono::milliseconds sleepFor =
|
||||||
PROFILE_RANGE(script, "processEvents-sleep");
|
std::chrono::duration_cast<std::chrono::milliseconds>(sleepUntil - clock::now());
|
||||||
QCoreApplication::processEvents(); // before we sleep again, give events a chance to process
|
if (sleepFor > std::chrono::milliseconds(0)) {
|
||||||
|
QEventLoop loop;
|
||||||
|
QTimer timer;
|
||||||
|
timer.setSingleShot(true);
|
||||||
|
connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
|
||||||
|
timer.start(sleepFor.count());
|
||||||
|
loop.exec();
|
||||||
|
} else {
|
||||||
|
QCoreApplication::processEvents();
|
||||||
}
|
}
|
||||||
processedEvents = true;
|
processedEvents = true;
|
||||||
|
|
||||||
// If after processing events, we're past due, exit asap
|
|
||||||
if (clock::now() >= sleepUntil) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We only want to sleep a small amount so that any pending events (like timers or invokeMethod events)
|
|
||||||
// will be able to process quickly.
|
|
||||||
static const int SMALL_SLEEP_AMOUNT = 100;
|
|
||||||
auto smallSleepUntil = clock::now() + static_cast<std::chrono::microseconds>(SMALL_SLEEP_AMOUNT);
|
|
||||||
std::this_thread::sleep_until(smallSleepUntil);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PROFILE_RANGE(script, "ScriptMainLoop");
|
PROFILE_RANGE(script, "ScriptMainLoop");
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
#include <glm/gtx/quaternion.hpp>
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
#include <glm/gtx/component_wise.hpp>
|
||||||
|
|
||||||
// Bring the most commonly used GLM types into the default namespace
|
// Bring the most commonly used GLM types into the default namespace
|
||||||
using glm::ivec2;
|
using glm::ivec2;
|
||||||
|
|
|
@ -9,6 +9,10 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "RegisteredMetaTypes.h"
|
||||||
|
|
||||||
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
|
||||||
#include <QtCore/QUrl>
|
#include <QtCore/QUrl>
|
||||||
#include <QtCore/QUuid>
|
#include <QtCore/QUuid>
|
||||||
#include <QtCore/QRect>
|
#include <QtCore/QRect>
|
||||||
|
@ -17,10 +21,9 @@
|
||||||
#include <QtGui/QVector2D>
|
#include <QtGui/QVector2D>
|
||||||
#include <QtGui/QVector3D>
|
#include <QtGui/QVector3D>
|
||||||
#include <QtGui/QQuaternion>
|
#include <QtGui/QQuaternion>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <QtNetwork/QAbstractSocket>
|
||||||
#include <QAbstractSocket>
|
#include <QtScript/QScriptValue>
|
||||||
|
#include <QtScript/QScriptValueIterator>
|
||||||
#include "RegisteredMetaTypes.h"
|
|
||||||
|
|
||||||
int vec4MetaTypeId = qRegisterMetaType<glm::vec4>();
|
int vec4MetaTypeId = qRegisterMetaType<glm::vec4>();
|
||||||
int vec3MetaTypeId = qRegisterMetaType<glm::vec3>();
|
int vec3MetaTypeId = qRegisterMetaType<glm::vec3>();
|
||||||
|
@ -34,6 +37,8 @@ int pickRayMetaTypeId = qRegisterMetaType<PickRay>();
|
||||||
int collisionMetaTypeId = qRegisterMetaType<Collision>();
|
int collisionMetaTypeId = qRegisterMetaType<Collision>();
|
||||||
int qMapURLStringMetaTypeId = qRegisterMetaType<QMap<QUrl,QString>>();
|
int qMapURLStringMetaTypeId = qRegisterMetaType<QMap<QUrl,QString>>();
|
||||||
int socketErrorMetaTypeId = qRegisterMetaType<QAbstractSocket::SocketError>();
|
int socketErrorMetaTypeId = qRegisterMetaType<QAbstractSocket::SocketError>();
|
||||||
|
int voidLambdaType = qRegisterMetaType<std::function<void()>>();
|
||||||
|
int variantLambdaType = qRegisterMetaType<std::function<QVariant()>>();
|
||||||
|
|
||||||
void registerMetaTypes(QScriptEngine* engine) {
|
void registerMetaTypes(QScriptEngine* engine) {
|
||||||
qScriptRegisterMetaType(engine, mat4toScriptValue, mat4FromScriptValue);
|
qScriptRegisterMetaType(engine, mat4toScriptValue, mat4FromScriptValue);
|
||||||
|
@ -796,3 +801,101 @@ void qSizeFFromScriptValue(const QScriptValue& object, QSizeF& qSizeF) {
|
||||||
qSizeF.setWidth(object.property("width").toVariant().toFloat());
|
qSizeF.setWidth(object.property("width").toVariant().toFloat());
|
||||||
qSizeF.setHeight(object.property("height").toVariant().toFloat());
|
qSizeF.setHeight(object.property("height").toVariant().toFloat());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnimationDetails::AnimationDetails() :
|
||||||
|
role(), url(), fps(0.0f), priority(0.0f), loop(false), hold(false),
|
||||||
|
startAutomatically(false), firstFrame(0.0f), lastFrame(0.0f), running(false), currentFrame(0.0f) {
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimationDetails::AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop,
|
||||||
|
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame) :
|
||||||
|
role(role), url(url), fps(fps), priority(priority), loop(loop), hold(hold),
|
||||||
|
startAutomatically(startAutomatically), firstFrame(firstFrame), lastFrame(lastFrame),
|
||||||
|
running(running), currentFrame(currentFrame) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& details) {
|
||||||
|
QScriptValue obj = engine->newObject();
|
||||||
|
obj.setProperty("role", details.role);
|
||||||
|
obj.setProperty("url", details.url.toString());
|
||||||
|
obj.setProperty("fps", details.fps);
|
||||||
|
obj.setProperty("priority", details.priority);
|
||||||
|
obj.setProperty("loop", details.loop);
|
||||||
|
obj.setProperty("hold", details.hold);
|
||||||
|
obj.setProperty("startAutomatically", details.startAutomatically);
|
||||||
|
obj.setProperty("firstFrame", details.firstFrame);
|
||||||
|
obj.setProperty("lastFrame", details.lastFrame);
|
||||||
|
obj.setProperty("running", details.running);
|
||||||
|
obj.setProperty("currentFrame", details.currentFrame);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& details) {
|
||||||
|
// nothing for now...
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in) {
|
||||||
|
return engine->newQObject(in, QScriptEngine::QtOwnership,
|
||||||
|
QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects);
|
||||||
|
}
|
||||||
|
|
||||||
|
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out) {
|
||||||
|
out = qobject_cast<MeshProxy*>(value.toQObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in) {
|
||||||
|
// QScriptValueList result;
|
||||||
|
QScriptValue result = engine->newArray();
|
||||||
|
int i = 0;
|
||||||
|
foreach(MeshProxy* const meshProxy, in) {
|
||||||
|
result.setProperty(i++, meshToScriptValue(engine, meshProxy));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out) {
|
||||||
|
QScriptValueIterator itr(value);
|
||||||
|
|
||||||
|
qDebug() << "in meshesFromScriptValue, value.length =" << value.property("length").toInt32();
|
||||||
|
|
||||||
|
while (itr.hasNext()) {
|
||||||
|
itr.next();
|
||||||
|
MeshProxy* meshProxy = qscriptvalue_cast<MeshProxyList::value_type>(itr.value());
|
||||||
|
if (meshProxy) {
|
||||||
|
out.append(meshProxy);
|
||||||
|
} else {
|
||||||
|
qDebug() << "null meshProxy";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QScriptValue meshFaceToScriptValue(QScriptEngine* engine, const MeshFace &meshFace) {
|
||||||
|
QScriptValue obj = engine->newObject();
|
||||||
|
obj.setProperty("vertices", qVectorIntToScriptValue(engine, meshFace.vertexIndices));
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
void meshFaceFromScriptValue(const QScriptValue &object, MeshFace& meshFaceResult) {
|
||||||
|
qVectorIntFromScriptValue(object.property("vertices"), meshFaceResult.vertexIndices);
|
||||||
|
}
|
||||||
|
|
||||||
|
QScriptValue qVectorMeshFaceToScriptValue(QScriptEngine* engine, const QVector<MeshFace>& vector) {
|
||||||
|
QScriptValue array = engine->newArray();
|
||||||
|
for (int i = 0; i < vector.size(); i++) {
|
||||||
|
array.setProperty(i, meshFaceToScriptValue(engine, vector.at(i)));
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector<MeshFace>& result) {
|
||||||
|
int length = array.property("length").toInteger();
|
||||||
|
result.clear();
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
MeshFace meshFace = MeshFace();
|
||||||
|
meshFaceFromScriptValue(array.property(i), meshFace);
|
||||||
|
result << meshFace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <QtScript/QScriptEngine>
|
#include <QtScript/QScriptEngine>
|
||||||
#include <QtCore/QUuid>
|
#include <QtCore/QUuid>
|
||||||
|
#include <QtCore/QUrl>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/quaternion.hpp>
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
@ -33,6 +34,8 @@ Q_DECLARE_METATYPE(xColor)
|
||||||
Q_DECLARE_METATYPE(QVector<glm::vec3>)
|
Q_DECLARE_METATYPE(QVector<glm::vec3>)
|
||||||
Q_DECLARE_METATYPE(QVector<float>)
|
Q_DECLARE_METATYPE(QVector<float>)
|
||||||
Q_DECLARE_METATYPE(AACube)
|
Q_DECLARE_METATYPE(AACube)
|
||||||
|
Q_DECLARE_METATYPE(std::function<void()>);
|
||||||
|
Q_DECLARE_METATYPE(std::function<QVariant()>);
|
||||||
|
|
||||||
void registerMetaTypes(QScriptEngine* engine);
|
void registerMetaTypes(QScriptEngine* engine);
|
||||||
|
|
||||||
|
@ -167,4 +170,73 @@ void quuidFromScriptValue(const QScriptValue& object, QUuid& uuid);
|
||||||
QScriptValue qSizeFToScriptValue(QScriptEngine* engine, const QSizeF& qSizeF);
|
QScriptValue qSizeFToScriptValue(QScriptEngine* engine, const QSizeF& qSizeF);
|
||||||
void qSizeFFromScriptValue(const QScriptValue& object, QSizeF& qSizeF);
|
void qSizeFFromScriptValue(const QScriptValue& object, QSizeF& qSizeF);
|
||||||
|
|
||||||
|
class AnimationDetails {
|
||||||
|
public:
|
||||||
|
AnimationDetails();
|
||||||
|
AnimationDetails(QString role, QUrl url, float fps, float priority, bool loop,
|
||||||
|
bool hold, bool startAutomatically, float firstFrame, float lastFrame, bool running, float currentFrame);
|
||||||
|
|
||||||
|
QString role;
|
||||||
|
QUrl url;
|
||||||
|
float fps;
|
||||||
|
float priority;
|
||||||
|
bool loop;
|
||||||
|
bool hold;
|
||||||
|
bool startAutomatically;
|
||||||
|
float firstFrame;
|
||||||
|
float lastFrame;
|
||||||
|
bool running;
|
||||||
|
float currentFrame;
|
||||||
|
};
|
||||||
|
Q_DECLARE_METATYPE(AnimationDetails);
|
||||||
|
QScriptValue animationDetailsToScriptValue(QScriptEngine* engine, const AnimationDetails& event);
|
||||||
|
void animationDetailsFromScriptValue(const QScriptValue& object, AnimationDetails& event);
|
||||||
|
|
||||||
|
namespace model {
|
||||||
|
class Mesh;
|
||||||
|
}
|
||||||
|
|
||||||
|
using MeshPointer = std::shared_ptr<model::Mesh>;
|
||||||
|
|
||||||
|
|
||||||
|
class MeshProxy : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
virtual MeshPointer getMeshPointer() const = 0;
|
||||||
|
Q_INVOKABLE virtual int getNumVertices() const = 0;
|
||||||
|
Q_INVOKABLE virtual glm::vec3 getPos3(int index) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(MeshProxy*);
|
||||||
|
|
||||||
|
class MeshProxyList : public QList<MeshProxy*> {}; // typedef and using fight with the Qt macros/templates, do this instead
|
||||||
|
Q_DECLARE_METATYPE(MeshProxyList);
|
||||||
|
|
||||||
|
|
||||||
|
QScriptValue meshToScriptValue(QScriptEngine* engine, MeshProxy* const &in);
|
||||||
|
void meshFromScriptValue(const QScriptValue& value, MeshProxy* &out);
|
||||||
|
|
||||||
|
QScriptValue meshesToScriptValue(QScriptEngine* engine, const MeshProxyList &in);
|
||||||
|
void meshesFromScriptValue(const QScriptValue& value, MeshProxyList &out);
|
||||||
|
|
||||||
|
class MeshFace {
|
||||||
|
|
||||||
|
public:
|
||||||
|
MeshFace() {}
|
||||||
|
~MeshFace() {}
|
||||||
|
|
||||||
|
QVector<uint32_t> vertexIndices;
|
||||||
|
// TODO -- material...
|
||||||
|
};
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE(MeshFace)
|
||||||
|
Q_DECLARE_METATYPE(QVector<MeshFace>)
|
||||||
|
|
||||||
|
QScriptValue meshFaceToScriptValue(QScriptEngine* engine, const MeshFace &meshFace);
|
||||||
|
void meshFaceFromScriptValue(const QScriptValue &object, MeshFace& meshFaceResult);
|
||||||
|
QScriptValue qVectorMeshFaceToScriptValue(QScriptEngine* engine, const QVector<MeshFace>& vector);
|
||||||
|
void qVectorMeshFaceFromScriptValue(const QScriptValue& array, QVector<MeshFace>& result);
|
||||||
|
|
||||||
|
|
||||||
#endif // hifi_RegisteredMetaTypes_h
|
#endif // hifi_RegisteredMetaTypes_h
|
||||||
|
|
|
@ -9,11 +9,13 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
#include <NumericalConstants.h>
|
|
||||||
|
|
||||||
#include "AnimationCache.h"
|
|
||||||
#include "AnimationLoop.h"
|
#include "AnimationLoop.h"
|
||||||
|
|
||||||
|
#include "../../NumericalConstants.h"
|
||||||
|
#include "../../SharedUtil.h"
|
||||||
|
#include "../../GLMHelpers.h"
|
||||||
|
#include "../../RegisteredMetaTypes.h"
|
||||||
|
|
||||||
const float AnimationLoop::MAXIMUM_POSSIBLE_FRAME = 100000.0f;
|
const float AnimationLoop::MAXIMUM_POSSIBLE_FRAME = 100000.0f;
|
||||||
|
|
||||||
AnimationLoop::AnimationLoop() :
|
AnimationLoop::AnimationLoop() :
|
||||||
|
@ -62,7 +64,7 @@ AnimationLoop::AnimationLoop(float fps, bool loop, bool hold, bool startAutomati
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnimationLoop::simulateAtTime(quint64 now) {
|
void AnimationLoop::simulateAtTime(uint64_t now) {
|
||||||
float deltaTime = (float)(now - _lastSimulated) / (float)USECS_PER_SECOND;
|
float deltaTime = (float)(now - _lastSimulated) / (float)USECS_PER_SECOND;
|
||||||
_lastSimulated = now;
|
_lastSimulated = now;
|
||||||
simulate(deltaTime);
|
simulate(deltaTime);
|
|
@ -14,6 +14,9 @@
|
||||||
|
|
||||||
class AnimationDetails;
|
class AnimationDetails;
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
class AnimationLoop {
|
class AnimationLoop {
|
||||||
public:
|
public:
|
||||||
static const float MAXIMUM_POSSIBLE_FRAME;
|
static const float MAXIMUM_POSSIBLE_FRAME;
|
||||||
|
@ -58,7 +61,7 @@ public:
|
||||||
void stop() { setRunning(false); }
|
void stop() { setRunning(false); }
|
||||||
void simulate(float deltaTime); /// call this with deltaTime if you as the caller are managing the delta time between calls
|
void simulate(float deltaTime); /// call this with deltaTime if you as the caller are managing the delta time between calls
|
||||||
|
|
||||||
void simulateAtTime(quint64 now); /// call this with "now" if you want the animationLoop to handle delta times
|
void simulateAtTime(uint64_t now); /// call this with "now" if you want the animationLoop to handle delta times
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float _fps;
|
float _fps;
|
||||||
|
@ -71,7 +74,7 @@ private:
|
||||||
float _currentFrame;
|
float _currentFrame;
|
||||||
float _maxFrameIndexHint;
|
float _maxFrameIndexHint;
|
||||||
bool _resetOnRunning;
|
bool _resetOnRunning;
|
||||||
quint64 _lastSimulated;
|
uint64_t _lastSimulated;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AnimationLoop_h
|
#endif // hifi_AnimationLoop_h
|
|
@ -886,12 +886,6 @@ QQmlContext* OffscreenQmlSurface::getSurfaceContext() {
|
||||||
return _qmlContext;
|
return _qmlContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(std::function<void()>);
|
|
||||||
auto VoidLambdaType = qRegisterMetaType<std::function<void()>>();
|
|
||||||
Q_DECLARE_METATYPE(std::function<QVariant()>);
|
|
||||||
auto VariantLambdaType = qRegisterMetaType<std::function<QVariant()>>();
|
|
||||||
|
|
||||||
|
|
||||||
void OffscreenQmlSurface::executeOnUiThread(std::function<void()> function, bool blocking ) {
|
void OffscreenQmlSurface::executeOnUiThread(std::function<void()> function, bool blocking ) {
|
||||||
if (QThread::currentThread() != thread()) {
|
if (QThread::currentThread() != thread()) {
|
||||||
QMetaObject::invokeMethod(this, "executeOnUiThread", blocking ? Qt::BlockingQueuedConnection : Qt::QueuedConnection,
|
QMetaObject::invokeMethod(this, "executeOnUiThread", blocking ? Qt::BlockingQueuedConnection : Qt::QueuedConnection,
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include <gpu/gl/GLTexture.h>
|
#include <gpu/gl/GLTexture.h>
|
||||||
#include <gpu/StandardShaderLib.h>
|
#include <gpu/StandardShaderLib.h>
|
||||||
|
|
||||||
|
#include <AnimationCache.h>
|
||||||
#include <SimpleEntitySimulation.h>
|
#include <SimpleEntitySimulation.h>
|
||||||
#include <EntityDynamicInterface.h>
|
#include <EntityDynamicInterface.h>
|
||||||
#include <EntityDynamicFactoryInterface.h>
|
#include <EntityDynamicFactoryInterface.h>
|
||||||
|
|
27
tools/avatar-json-to-dot.js
Normal file
27
tools/avatar-json-to-dot.js
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
// usage:
|
||||||
|
// node avatar-json-to-dot.js /path/to/avatar-animaton.json > out.dot
|
||||||
|
//
|
||||||
|
// Then if you have graphviz installed you can run the following command to generate a png.
|
||||||
|
// dot -Tpng out.dot > out.png
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
var filename = process.argv[2];
|
||||||
|
|
||||||
|
function dumpNodes(node) {
|
||||||
|
node.children.forEach(function (child) {
|
||||||
|
console.log(' ' + node.id + ' -> ' + child.id + ';');
|
||||||
|
dumpNodes(child);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fs.readFile(filename, 'utf8', function (err, data) {
|
||||||
|
if (err) {
|
||||||
|
console.log('error opening ' + filename + ', err = ' + err);
|
||||||
|
} else {
|
||||||
|
var graph = JSON.parse(data);
|
||||||
|
console.log('digraph graphname {');
|
||||||
|
console.log(' rankdir = "LR";');
|
||||||
|
dumpNodes(graph.root);
|
||||||
|
console.log('}');
|
||||||
|
}
|
||||||
|
});
|
Loading…
Reference in a new issue