Merge branch 'rig' of github.com:howard-stearns/hifi into bromine

Conflicts:
	interface/src/avatar/SkeletonModel.cpp
This commit is contained in:
Andrew Meadows 2015-07-24 10:06:02 -07:00
commit 1bf49d72f1
33 changed files with 263 additions and 443 deletions

View file

@ -77,13 +77,6 @@ const glm::vec3 randVector() {
return glm::vec3(randFloat() - 0.5f, randFloat() - 0.5f, randFloat() - 0.5f) * 2.0f;
}
void renderCollisionOverlay(int width, int height, float magnitude, float red, float blue, float green) {
const float MIN_VISIBLE_COLLISION = 0.01f;
if (magnitude > MIN_VISIBLE_COLLISION) {
DependencyManager::get<GeometryCache>()->renderQuad(0, 0, width, height, glm::vec4(red, blue, green, magnitude));
}
}
// Do some basic timing tests and report the results
void runTimingTests() {
// How long does it take to make a call to get the time?

View file

@ -23,8 +23,6 @@ const glm::vec3 randVector();
void renderWorldBox(gpu::Batch& batch);
void renderCollisionOverlay(int width, int height, float magnitude, float red = 0, float blue = 0, float green = 0);
void runTimingTests();
void runUnitTests();

View file

@ -54,7 +54,7 @@
using namespace std;
const glm::vec3 DEFAULT_UP_DIRECTION(0.0f, 1.0f, 0.0f);
const float YAW_SPEED = 500.0f; // degrees/sec
const float YAW_SPEED = 150.0f; // degrees/sec
const float PITCH_SPEED = 100.0f; // degrees/sec
const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.0f;
@ -103,11 +103,8 @@ MyAvatar::MyAvatar(RigPointer rig) :
_realWorldFieldOfView("realWorldFieldOfView",
DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES),
_rig(rig),
_firstPersonSkeletonModel(this, nullptr, rig),
_prevShouldDrawHead(true)
{
_firstPersonSkeletonModel.setIsFirstPerson(true);
ShapeCollider::initDispatchTable();
for (int i = 0; i < MAX_DRIVE_KEYS; i++) {
_driveKeys[i] = 0.0f;
@ -141,7 +138,6 @@ QByteArray MyAvatar::toByteArray() {
void MyAvatar::reset() {
_skeletonModel.reset();
_firstPersonSkeletonModel.reset();
getHead()->reset();
_targetVelocity = glm::vec3(0.0f);
@ -200,7 +196,6 @@ void MyAvatar::simulate(float deltaTime) {
{
PerformanceTimer perfTimer("skeleton");
_skeletonModel.simulate(deltaTime);
_firstPersonSkeletonModel.simulate(deltaTime);
}
if (!_skeletonModel.hasSkeleton()) {
@ -1028,15 +1023,8 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
if (_useFullAvatar) {
_skeletonModel.setVisibleInScene(_prevShouldDrawHead, scene);
const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst");
_firstPersonSkeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar());
_firstPersonSkeletonModel.setVisibleInScene(!_prevShouldDrawHead, scene);
} else {
_skeletonModel.setVisibleInScene(true, scene);
_firstPersonSkeletonModel.setVisibleInScene(false, scene);
_firstPersonSkeletonModel.reset();
}
}
@ -1254,23 +1242,14 @@ void MyAvatar::preRender(RenderArgs* renderArgs) {
const bool shouldDrawHead = shouldRenderHead(renderArgs);
_skeletonModel.initWhenReady(scene);
if (_useFullAvatar) {
_firstPersonSkeletonModel.initWhenReady(scene);
}
if (shouldDrawHead != _prevShouldDrawHead) {
if (_useFullAvatar) {
if (shouldDrawHead) {
_skeletonModel.setVisibleInScene(true, scene);
_firstPersonSkeletonModel.setVisibleInScene(false, scene);
} else {
_skeletonModel.setVisibleInScene(false, scene);
_firstPersonSkeletonModel.setVisibleInScene(true, scene);
}
_skeletonModel.setVisibleInScene(true, scene);
_rig->setFirstPerson(!shouldDrawHead);
} else {
getHead()->getFaceModel().setVisibleInScene(shouldDrawHead, scene);
}
}
_prevShouldDrawHead = shouldDrawHead;
}
@ -1291,22 +1270,34 @@ bool MyAvatar::shouldRenderHead(const RenderArgs* renderArgs) const {
void MyAvatar::updateOrientation(float deltaTime) {
// Smoothly rotate body with arrow keys
_bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime;
_bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime;
getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime);
float driveLeft = _driveKeys[ROT_LEFT] - _driveKeys[ROT_RIGHT];
float targetSpeed = (_driveKeys[ROT_LEFT] - _driveKeys[ROT_RIGHT]) * YAW_SPEED;
if (targetSpeed != 0.0f) {
const float ROTATION_RAMP_TIMESCALE = 0.1f;
float blend = deltaTime / ROTATION_RAMP_TIMESCALE;
if (blend > 1.0f) {
blend = 1.0f;
}
_bodyYawDelta = (1.0f - blend) * _bodyYawDelta + blend * targetSpeed;
} else if (_bodyYawDelta != 0.0f) {
// attenuate body rotation speed
const float ROTATION_DECAY_TIMESCALE = 0.05f;
float attenuation = 1.0f - deltaTime / ROTATION_DECAY_TIMESCALE;
if (attenuation < 0.0f) {
attenuation = 0.0f;
}
_bodyYawDelta *= attenuation;
float MINIMUM_ROTATION_RATE = 2.0f;
if (fabsf(_bodyYawDelta) < MINIMUM_ROTATION_RATE) {
_bodyYawDelta = 0.0f;
}
}
getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime);
// update body orientation by movement inputs
setOrientation(getOrientation() *
glm::quat(glm::radians(glm::vec3(0.0f, _bodyYawDelta, 0.0f) * deltaTime)));
// decay body rotation momentum
const float BODY_SPIN_FRICTION = 7.5f;
float bodySpinMomentum = 1.0f - BODY_SPIN_FRICTION * deltaTime;
if (bodySpinMomentum < 0.0f) { bodySpinMomentum = 0.0f; }
_bodyYawDelta *= bodySpinMomentum;
float MINIMUM_ROTATION_RATE = 2.0f;
if (fabs(_bodyYawDelta) < MINIMUM_ROTATION_RATE) { _bodyYawDelta = 0.0f; }
glm::quat(glm::radians(glm::vec3(0.0f, _bodyYawDelta * deltaTime, 0.0f))));
if (qApp->isHMDMode()) {
// these angles will be in radians

View file

@ -287,8 +287,6 @@ private:
QString _fullAvatarModelName;
RigPointer _rig;
// used for rendering when in first person view or when in an HMD.
SkeletonModel _firstPersonSkeletonModel;
bool _prevShouldDrawHead;
};

View file

@ -40,8 +40,7 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent, RigPointer r
_standingFoot(NO_FOOT),
_standingOffset(0.0f),
_clampedFootPosition(0.0f),
_headClipDistance(DEFAULT_NEAR_CLIP),
_isFirstPerson(false)
_headClipDistance(DEFAULT_NEAR_CLIP)
{
assert(_rig);
assert(_owningAvatar);
@ -54,7 +53,7 @@ SkeletonModel::~SkeletonModel() {
void SkeletonModel::initJointStates(QVector<JointState> states) {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
_boundingRadius = _rig->initJointStates(states, parentTransform);
_boundingRadius = _rig->initJointStates(states, parentTransform, geometry.neckJointIndex);
// Determine the default eye position for avatar scale = 1.0
int headJointIndex = _geometry->getFBXGeometry().headJointIndex;
@ -98,6 +97,29 @@ void SkeletonModel::initJointStates(QVector<JointState> states) {
const float PALM_PRIORITY = DEFAULT_PRIORITY;
const float LEAN_PRIORITY = DEFAULT_PRIORITY;
void SkeletonModel::updateClusterMatrices() {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 modelToWorld = glm::mat4_cast(_rotation);
for (int i = 0; i < _meshStates.size(); i++) {
MeshState& state = _meshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i);
if (_showTrueJointTransforms) {
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
state.clusterMatrices[j] =
modelToWorld * _rig->getJointTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
}
} else {
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
state.clusterMatrices[j] =
modelToWorld * _rig->getJointVisibleTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
}
}
}
}
void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
setTranslation(_owningAvatar->getSkeletonPosition());
static const glm::quat refOrientation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
@ -154,8 +176,11 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
}
}
if (_isFirstPerson) {
cauterizeHead();
// if (_isFirstPerson) {
// cauterizeHead();
// updateClusterMatrices();
// }
if (_rig->getJointsAreDirty()) {
updateClusterMatrices();
}
@ -347,13 +372,15 @@ void SkeletonModel::renderJointConstraints(gpu::Batch& batch, int jointIndex) {
}
renderOrientationDirections(jointIndex, position, _rotation * jointState.getRotation(), directionSize);
renderOrientationDirections(batch, jointIndex, position, _rotation * jointState.getRotation(), directionSize);
jointIndex = joint.parentIndex;
} while (jointIndex != -1 && geometry.joints.at(jointIndex).isFree);
}
void SkeletonModel::renderOrientationDirections(int jointIndex, glm::vec3 position, const glm::quat& orientation, float size) {
void SkeletonModel::renderOrientationDirections(gpu::Batch& batch, int jointIndex,
glm::vec3 position, const glm::quat& orientation, float size) {
auto geometryCache = DependencyManager::get<GeometryCache>();
if (!_jointOrientationLines.contains(jointIndex)) {
@ -370,13 +397,13 @@ void SkeletonModel::renderOrientationDirections(int jointIndex, glm::vec3 positi
glm::vec3 pFront = position + orientation * IDENTITY_FRONT * size;
glm::vec3 red(1.0f, 0.0f, 0.0f);
geometryCache->renderLine(position, pRight, red, jointLineIDs._right);
geometryCache->renderLine(batch, position, pRight, red, jointLineIDs._right);
glm::vec3 green(0.0f, 1.0f, 0.0f);
geometryCache->renderLine(position, pUp, green, jointLineIDs._up);
geometryCache->renderLine(batch, position, pUp, green, jointLineIDs._up);
glm::vec3 blue(0.0f, 0.0f, 1.0f);
geometryCache->renderLine(position, pFront, blue, jointLineIDs._front);
geometryCache->renderLine(batch, position, pFront, blue, jointLineIDs._front);
}
@ -689,7 +716,7 @@ void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float alpha
// draw a green cylinder between the two points
glm::vec3 origin(0.0f);
Avatar::renderJointConnectingCone(batch, origin, axis, _boundingShape.getRadius(), _boundingShape.getRadius(),
Avatar::renderJointConnectingCone(batch, origin, axis, _boundingShape.getRadius(), _boundingShape.getRadius(),
glm::vec4(0.6f, 0.8f, 0.6f, alpha));
}
@ -697,56 +724,5 @@ bool SkeletonModel::hasSkeleton() {
return isActive() ? _geometry->getFBXGeometry().rootJointIndex != -1 : false;
}
void SkeletonModel::initHeadBones() {
_headBones.clear();
const FBXGeometry& fbxGeometry = _geometry->getFBXGeometry();
const int neckJointIndex = fbxGeometry.neckJointIndex;
std::queue<int> q;
q.push(neckJointIndex);
_headBones.push_back(neckJointIndex);
// fbxJoints only hold links to parents not children, so we have to do a bit of extra work here.
while (q.size() > 0) {
int jointIndex = q.front();
for (int i = 0; i < fbxGeometry.joints.size(); i++) {
const FBXJoint& fbxJoint = fbxGeometry.joints[i];
if (jointIndex == fbxJoint.parentIndex) {
_headBones.push_back(i);
q.push(i);
}
}
q.pop();
}
}
void SkeletonModel::invalidateHeadBones() {
_headBones.clear();
}
void SkeletonModel::cauterizeHead() {
if (isActive()) {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
const int neckJointIndex = geometry.neckJointIndex;
if (neckJointIndex > 0 && neckJointIndex < _rig->getJointStateCount()) {
// lazy init of headBones
if (_headBones.size() == 0) {
initHeadBones();
}
// preserve the translation for the neck
// glm::vec4 trans = _jointStates[neckJointIndex].getTransform()[3];
glm::vec4 trans = _rig->getJointTransform(neckJointIndex)[3];
glm::vec4 zero(0, 0, 0, 0);
for (const int &i : _headBones) {
glm::mat4 newXform(zero, zero, zero, trans);
_rig->setJointTransform(i, newXform);
_rig->setJointVisibleTransform(i, newXform);
}
}
}
}
void SkeletonModel::onInvalidate() {
invalidateHeadBones();
}

View file

@ -106,9 +106,6 @@ public:
float getHeadClipDistance() const { return _headClipDistance; }
void setIsFirstPerson(bool value) { _isFirstPerson = value; }
bool getIsFirstPerson() const { return _isFirstPerson; }
virtual void onInvalidate() override;
signals:
@ -132,6 +129,7 @@ protected:
void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, int index);
void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, int index);
void updateClusterMatrices();
void cauterizeHead();
void initHeadBones();
void invalidateHeadBones();
@ -139,7 +137,8 @@ protected:
private:
void renderJointConstraints(gpu::Batch& batch, int jointIndex);
void renderOrientationDirections(int jointIndex, glm::vec3 position, const glm::quat& orientation, float size);
void renderOrientationDirections(gpu::Batch& batch, int jointIndex,
glm::vec3 position, const glm::quat& orientation, float size);
struct OrientationLineIDs {
int _up;
@ -167,9 +166,6 @@ private:
glm::vec3 _clampedFootPosition;
float _headClipDistance; // Near clip distance to use if no separate head model
bool _isFirstPerson;
std::vector<int> _headBones;
};
#endif // hifi_SkeletonModel_h

View file

@ -529,7 +529,7 @@ void ApplicationCompositor::renderControllerPointers(gpu::Batch& batch) {
glm::vec2 texCoordTopLeft(0.0f, 0.0f);
glm::vec2 texCoordBottomRight(1.0f, 1.0f);
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
glm::vec4(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f));
}

View file

@ -1,6 +1,6 @@
//
// AnimationCache.cpp
// libraries/script-engine/src/
// libraries/animation/src/
//
// Created by Andrzej Kapolka on 4/14/14.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.

View file

@ -1,6 +1,6 @@
//
// AnimationCache.h
// libraries/script-engine/src/
// libraries/animation/src/
//
// Created by Andrzej Kapolka on 4/14/14.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.

View file

@ -1,6 +1,6 @@
//
// AnimationHandle.cpp
// interface/src/renderer
// libraries/animation/src/
//
// Created by Andrzej Kapolka on 10/18/13.
// Copyright 2013 High Fidelity, Inc.
@ -176,8 +176,7 @@ void AnimationHandle::replaceMatchingPriorities(float newPriority) {
for (int i = 0; i < _jointMappings.size(); i++) {
int mapping = _jointMappings.at(i);
if (mapping != -1) {
JointState state = _rig->getJointState(mapping);
if (_priority == state._animationPriority) {
if (_priority == _rig->getJointAnimatinoPriority(mapping)) {
_rig->setJointAnimatinoPriority(mapping, newPriority);
}
}
@ -188,8 +187,7 @@ void AnimationHandle::restoreJoints() {
for (int i = 0; i < _jointMappings.size(); i++) {
int mapping = _jointMappings.at(i);
if (mapping != -1) {
JointState state = _rig->getJointState(mapping);
_rig->restoreJointRotation(mapping, 1.0f, state._animationPriority);
_rig->restoreJointRotation(mapping, 1.0f, _rig->getJointAnimatinoPriority(mapping));
}
}
}

View file

@ -1,6 +1,6 @@
//
// AnimationHandle.h
// interface/src/renderer
// libraries/animation/src/
//
// Created by Andrzej Kapolka on 10/18/13.
// Copyright 2013 High Fidelity, Inc.

View file

@ -1,6 +1,6 @@
//
// AnimationLoop.cpp
// libraries/animation
// libraries/animation/src/
//
// Created by Brad Hefta-Gaub on 11/12/14.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.

View file

@ -1,6 +1,6 @@
//
// AnimationLoop.h
// libraries/script-engine/src/
// libraries/animation/src/
//
// Created by Brad Hefta-Gaub on 11/12/14.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.

View file

@ -1,6 +1,6 @@
//
// AnimationObject.cpp
// libraries/script-engine/src/
// libraries/animation/src/
//
// Created by Andrzej Kapolka on 4/17/14.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.

View file

@ -1,6 +1,6 @@
//
// AnimationObject.h
// libraries/script-engine/src/
// libraries/animation/src/
//
// Created by Andrzej Kapolka on 4/17/14.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.

View file

@ -1,6 +1,6 @@
//
// JointState.cpp
// interface/src/renderer
// libraries/animation/src/
//
// Created by Andrzej Kapolka on 10/18/13.
// Copyright 2013 High Fidelity, Inc.

View file

@ -1,6 +1,6 @@
//
// JointState.h
// interface/src/renderer
// libraries/animation/src/
//
// Created by Andrzej Kapolka on 10/18/13.
// Copyright 2013 High Fidelity, Inc.

View file

@ -1,6 +1,6 @@
//
// Rig.cpp
// libraries/script-engine/src/
// libraries/animation/src/
//
// Created by Howard Stearns, Seth Alves, Anthony Thibault, Andrew Meadows on 7/15/15.
// Copyright (c) 2015 High Fidelity, Inc. All rights reserved.
@ -9,6 +9,8 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <queue>
#include "AnimationHandle.h"
#include "Rig.h"
@ -48,9 +50,9 @@ void Rig::deleteAnimations() {
}
}
float Rig::initJointStates(QVector<JointState> states, glm::mat4 parentTransform) {
float Rig::initJointStates(QVector<JointState> states, glm::mat4 parentTransform, int neckJointIndex) {
_jointStates = states;
_neckJointIndex = neckJointIndex;
initJointTransforms(parentTransform);
int numStates = _jointStates.size();
@ -66,6 +68,8 @@ float Rig::initJointStates(QVector<JointState> states, glm::mat4 parentTransform
_jointStates[i].slaveVisibleTransform();
}
initHeadBones();
return radius;
}
@ -106,7 +110,8 @@ JointState Rig::getJointState(int jointIndex) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return JointState();
}
return _jointStates[jointIndex];
// return _jointStates[jointIndex];
return maybeCauterizeHead(jointIndex);
}
bool Rig::getJointStateRotation(int index, glm::quat& rotation) const {
@ -144,6 +149,13 @@ void Rig::clearJointAnimationPriority(int index) {
}
}
float Rig::getJointAnimatinoPriority(int index) {
if (index != -1 && index < _jointStates.size()) {
return _jointStates[index]._animationPriority;
}
return 0.0f;
}
void Rig::setJointAnimatinoPriority(int index, float newPriority) {
if (index != -1 && index < _jointStates.size()) {
_jointStates[index]._animationPriority = newPriority;
@ -173,7 +185,8 @@ bool Rig::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position,
return false;
}
// position is in world-frame
position = translation + rotation * _jointStates[jointIndex].getPosition();
// position = translation + rotation * _jointStates[jointIndex].getPosition();
position = translation + rotation * maybeCauterizeHead(jointIndex).getPosition();
return true;
}
@ -182,7 +195,7 @@ bool Rig::getJointPosition(int jointIndex, glm::vec3& position) const {
return false;
}
// position is in model-frame
position = extractTranslation(_jointStates[jointIndex].getTransform());
position = extractTranslation(maybeCauterizeHead(jointIndex).getTransform());
return true;
}
@ -190,7 +203,7 @@ bool Rig::getJointRotationInWorldFrame(int jointIndex, glm::quat& result, const
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false;
}
result = rotation * _jointStates[jointIndex].getRotation();
result = rotation * maybeCauterizeHead(jointIndex).getRotation();
return true;
}
@ -198,7 +211,7 @@ bool Rig::getJointRotation(int jointIndex, glm::quat& rotation) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false;
}
rotation = _jointStates[jointIndex].getRotation();
rotation = maybeCauterizeHead(jointIndex).getRotation();
return true;
}
@ -206,7 +219,7 @@ bool Rig::getJointCombinedRotation(int jointIndex, glm::quat& result, const glm:
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false;
}
result = rotation * _jointStates[jointIndex].getRotation();
result = rotation * maybeCauterizeHead(jointIndex).getRotation();
return true;
}
@ -217,7 +230,7 @@ bool Rig::getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& positio
return false;
}
// position is in world-frame
position = translation + rotation * _jointStates[jointIndex].getVisiblePosition();
position = translation + rotation * maybeCauterizeHead(jointIndex).getVisiblePosition();
return true;
}
@ -225,7 +238,7 @@ bool Rig::getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& result,
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false;
}
result = rotation * _jointStates[jointIndex].getVisibleRotation();
result = rotation * maybeCauterizeHead(jointIndex).getVisibleRotation();
return true;
}
@ -233,14 +246,14 @@ glm::mat4 Rig::getJointTransform(int jointIndex) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return glm::mat4();
}
return _jointStates[jointIndex].getTransform();
return maybeCauterizeHead(jointIndex).getTransform();
}
glm::mat4 Rig::getJointVisibleTransform(int jointIndex) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return glm::mat4();
}
return _jointStates[jointIndex].getVisibleTransform();
return maybeCauterizeHead(jointIndex).getVisibleTransform();
}
void Rig::simulateInternal(float deltaTime, glm::mat4 parentTransform) {
@ -492,7 +505,7 @@ glm::vec3 Rig::getJointDefaultTranslationInConstrainedFrame(int jointIndex) {
if (jointIndex == -1 || _jointStates.isEmpty()) {
return glm::vec3();
}
return _jointStates[jointIndex].getDefaultTranslationInConstrainedFrame();
return maybeCauterizeHead(jointIndex).getDefaultTranslationInConstrainedFrame();
}
glm::quat Rig::setJointRotationInConstrainedFrame(int jointIndex, glm::quat targetRotation, float priority, bool constrain) {
@ -537,5 +550,53 @@ glm::quat Rig::getJointDefaultRotationInParentFrame(int jointIndex) {
if (jointIndex == -1 || _jointStates.isEmpty()) {
return glm::quat();
}
return _jointStates[jointIndex].getDefaultRotationInParentFrame();
return maybeCauterizeHead(jointIndex).getDefaultRotationInParentFrame();
}
void Rig::initHeadBones() {
if (_neckJointIndex == -1) {
return;
}
_headBones.clear();
std::queue<int> q;
q.push(_neckJointIndex);
_headBones.push_back(_neckJointIndex);
// fbxJoints only hold links to parents not children, so we have to do a bit of extra work here.
while (q.size() > 0) {
int jointIndex = q.front();
for (int i = 0; i < _jointStates.size(); i++) {
const FBXJoint& fbxJoint = _jointStates[i].getFBXJoint();
if (jointIndex == fbxJoint.parentIndex) {
_headBones.push_back(i);
q.push(i);
}
}
q.pop();
}
}
JointState Rig::maybeCauterizeHead(int jointIndex) const {
// if (_headBones.contains(jointIndex)) {
// XXX fix this... make _headBones a hash? add a flag to JointState?
if (_neckJointIndex != -1 &&
_isFirstPerson &&
std::find(_headBones.begin(), _headBones.end(), jointIndex) != _headBones.end()) {
glm::vec4 trans = _jointStates[jointIndex].getTransform()[3];
glm::vec4 zero(0, 0, 0, 0);
glm::mat4 newXform(zero, zero, zero, trans);
JointState jointStateCopy = _jointStates[jointIndex];
jointStateCopy.setTransform(newXform);
jointStateCopy.setVisibleTransform(newXform);
return jointStateCopy;
} else {
return _jointStates[jointIndex];
}
}
void Rig::setFirstPerson(bool isFirstPerson) {
if (_isFirstPerson != isFirstPerson) {
_isFirstPerson = isFirstPerson;
_jointsAreDirty = true;
}
}

View file

@ -1,6 +1,6 @@
//
// Rig.h
// libraries/script-engine/src/
// libraries/animation/src/
//
// Produces animation data and hip placement for the current timestamp.
//
@ -11,14 +11,18 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/* TBD:
- What iare responsibilities of Animation/AnimationPointer/AnimationCache/AnimationDetails/AnimationObject/AnimationLoop?
- What are responsibilities of Animation/AnimationPointer/AnimationCache/AnimationDetails/AnimationObject/AnimationLoop?
Is there common/copied code (e.g., ScriptableAvatar::update)?
- How do attachments interact with the physics of the attached entity? E.g., do hand joints need to reflect held object physics?
- Is there any current need (i.e., for initial campatability) to have multiple animations per role (e.g., idle) with the system choosing randomly?
- How do attachments interact with the physics of the attached entity? E.g., do hand joints need to reflect held object
physics?
- Is there any current need (i.e., for initial campatability) to have multiple animations per role (e.g., idle) with the
system choosing randomly?
- Distribute some doc from here to the right files if it turns out to be correct:
- AnimationDetails is a script-useable copy of animation state, analogous to EntityItemProperties, but without anything equivalent to editEntity.
But what's the intended difference vs AnimationObjection? Maybe AnimationDetails is to Animation as AnimationObject is to AnimationPointer?
- AnimationDetails is a script-useable copy of animation state, analogous to EntityItemProperties, but without anything
equivalent to editEntity.
But what's the intended difference vs AnimationObjection? Maybe AnimationDetails is to Animation as AnimationObject
is to AnimationPointer?
*/
#ifndef __hifi__Rig__
@ -51,7 +55,7 @@ public:
const QList<AnimationHandlePointer>& getRunningAnimations() const { return _runningAnimations; }
void deleteAnimations();
float initJointStates(QVector<JointState> states, glm::mat4 parentTransform);
float initJointStates(QVector<JointState> states, glm::mat4 parentTransform, int neckJointIndex);
bool jointStatesEmpty() { return _jointStates.isEmpty(); };
int getJointStateCount() const { return _jointStates.size(); }
@ -60,11 +64,12 @@ public:
void reset(const QVector<FBXJoint>& fbxJoints);
bool getJointStateRotation(int index, glm::quat& rotation) const;
void applyJointRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, float priority);
JointState getJointState(int jointIndex) const;
JointState getJointState(int jointIndex) const; // XXX
bool getVisibleJointState(int index, glm::quat& rotation) const;
void clearJointState(int index);
void clearJointStates();
void clearJointAnimationPriority(int index);
float getJointAnimatinoPriority(int index);
void setJointAnimatinoPriority(int index, float newPriority);
void setJointState(int index, bool valid, const glm::quat& rotation, float priority);
void restoreJointRotation(int index, float fraction, float priority);
@ -102,11 +107,23 @@ public:
virtual void updateJointState(int index, glm::mat4 parentTransform) = 0;
virtual void updateFaceJointState(int index, glm::mat4 parentTransform) = 0;
virtual void setFirstPerson(bool isFirstPerson);
virtual bool getIsFirstPerson() const { return _isFirstPerson; }
bool getJointsAreDirty() { return _jointsAreDirty; }
protected:
QVector<JointState> _jointStates;
QSet<AnimationHandlePointer> _animationHandles;
QList<AnimationHandlePointer> _runningAnimations;
JointState maybeCauterizeHead(int jointIndex) const;
void initHeadBones();
bool _isFirstPerson = false;
std::vector<int> _headBones;
bool _jointsAreDirty = false;
int _neckJointIndex = -1;
};
#endif /* defined(__hifi__Rig__) */

View file

@ -1087,7 +1087,7 @@ void AvatarData::setJointMappingsFromNetworkReply() {
}
networkReply->deleteLater();
emit jointsLoaded();
emit jointMappingLoaded();
}
void AvatarData::sendAvatarDataPacket() {

View file

@ -313,7 +313,7 @@ public:
bool shouldDie() const { return _owningAvatarMixer.isNull() || getUsecsSinceLastUpdate() > AVATAR_SILENCE_THRESHOLD_USECS; }
signals:
void jointsLoaded(); // So that test cases or anyone waiting on asynchronous loading can be informed.
void jointMappingLoaded(); // So that test cases or anyone waiting on asynchronous loading can be informed.
public slots:
void sendAvatarDataPacket();

View file

@ -92,9 +92,12 @@ GLBackend::GLBackend() :
{
static std::once_flag once;
std::call_once(once, [] {
qCDebug(gpulogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
qCDebug(gpulogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
qCDebug(gpulogging) << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR));
qCDebug(gpulogging) << "GL Version: " << QString((const char*) glGetString(GL_VERSION));
qCDebug(gpulogging) << "GL Shader Language Version: " << QString((const char*) glGetString(GL_SHADING_LANGUAGE_VERSION));
qCDebug(gpulogging) << "GL Vendor: " << QString((const char*) glGetString(GL_VENDOR));
qCDebug(gpulogging) << "GL Renderer: " << QString((const char*) glGetString(GL_RENDERER));
#ifdef WIN32
@ -143,15 +146,6 @@ void GLBackend::render(Batch& batch) {
}
}
void GLBackend::renderBatch(Batch& batch, bool syncCache) {
qCDebug(gpulogging) << "GLBackend::renderBatch : Deprecated call, don;t do it!!!";
GLBackend backend;
if (syncCache) {
backend.syncCache();
}
backend.render(batch);
}
bool GLBackend::checkGLError(const char* name) {
GLenum error = glGetError();
if (!error) {

View file

@ -38,15 +38,6 @@ public:
// Let's try to avoid to do that as much as possible!
virtual void syncCache();
// Render Batch create a local Context and execute the batch with it
// WARNING:
// if syncCache is true, then the gpu::GLBackend will synchornize
// its cache with the current gl state and it's BAD
// If you know you don't rely on any state changed by naked gl calls then
// leave to false where it belongs
// if true, the needed resync IS EXPENSIVE
static void renderBatch(Batch& batch, bool syncCache = false);
static bool checkGLError(const char* name = nullptr);
// Only checks in debug builds

View file

@ -21,7 +21,6 @@
#include "AbstractViewStateInterface.h"
#include "GeometryCache.h"
#include "RenderUtil.h"
#include "TextureCache.h"
#include "FramebufferCache.h"
@ -542,30 +541,34 @@ void DeferredLightingEffect::copyBack(RenderArgs* args) {
auto framebufferCache = DependencyManager::get<FramebufferCache>();
QSize framebufferSize = framebufferCache->getFrameBufferSize();
batch.setFramebuffer(framebufferCache->getPrimaryFramebuffer());
batch.setPipeline(_blitLightBuffer);
batch.setResourceTexture(0, _copyFBO->getRenderBuffer(0));
// TODO why doesn't this blit work? It only seems to affect a small area below the rear view mirror.
auto destFbo = framebufferCache->getPrimaryFramebuffer();
// gpu::Vec4i vp = args->_viewport;
// batch.blit(_copyFBO, vp, framebufferCache->getPrimaryFramebuffer(), vp);
batch.setFramebuffer(destFbo);
batch.setViewportTransform(args->_viewport);
batch.setProjectionTransform(glm::mat4());
batch.setViewTransform(Transform());
float sMin = args->_viewport.x / (float)framebufferSize.width();
float sWidth = args->_viewport.z / (float)framebufferSize.width();
float tMin = args->_viewport.y / (float)framebufferSize.height();
float tHeight = args->_viewport.w / (float)framebufferSize.height();
{
float sMin = args->_viewport.x / (float)framebufferSize.width();
float sWidth = args->_viewport.z / (float)framebufferSize.width();
float tMin = args->_viewport.y / (float)framebufferSize.height();
float tHeight = args->_viewport.w / (float)framebufferSize.height();
Transform model;
batch.setPipeline(_blitLightBuffer);
model.setTranslation(glm::vec3(sMin, tMin, 0.0));
model.setScale(glm::vec3(sWidth, tHeight, 1.0));
batch.setModelTransform(model);
}
batch.setViewportTransform(args->_viewport);
Transform model;
model.setTranslation(glm::vec3(sMin, tMin, 0.0));
model.setScale(glm::vec3(sWidth, tHeight, 1.0));
batch.setModelTransform(model);
GLenum buffers[3];
int bufferCount = 0;
buffers[bufferCount++] = GL_COLOR_ATTACHMENT0;
batch._glDrawBuffers(bufferCount, buffers);
batch.setResourceTexture(0, _copyFBO->getRenderBuffer(0));
batch.draw(gpu::TRIANGLE_STRIP, 4);
args->_context->syncCache();
args->_context->render(batch);
framebufferCache->releaseFramebuffer(_copyFBO);
}

View file

@ -54,12 +54,6 @@ const int NUM_TRIANGLES_PER_QUAD = 2;
const int NUM_VERTICES_PER_TRIANGULATED_QUAD = NUM_VERTICES_PER_TRIANGLE * NUM_TRIANGLES_PER_QUAD;
const int NUM_COORDS_PER_VERTEX = 3;
void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid, int id) {
gpu::Batch batch;
renderSphere(batch, radius, slices, stacks, color, solid, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color, bool solid, int id) {
bool registered = (id != UNKNOWN_ID);
@ -304,12 +298,6 @@ void GeometryCache::renderSphere(gpu::Batch& batch, float radius, int slices, in
}
}
void GeometryCache::renderGrid(int xDivisions, int yDivisions, const glm::vec4& color) {
gpu::Batch batch;
renderGrid(batch, xDivisions, yDivisions, color);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color) {
IntPair key(xDivisions, yDivisions);
Vec3Pair colorKey(glm::vec3(color.x, color.y, yDivisions), glm::vec3(color.z, color.y, xDivisions));
@ -384,12 +372,6 @@ void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions
batch.draw(gpu::LINES, vertices, 0);
}
void GeometryCache::renderGrid(int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id) {
gpu::Batch batch;
renderGrid(batch, x, y, width, height, rows, cols, color, id);
gpu::GLBackend::renderBatch(batch);
}
// TODO: why do we seem to create extra BatchItemDetails when we resize the window?? what's that??
void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id) {
#ifdef WANT_DEBUG
@ -691,12 +673,6 @@ void GeometryCache::updateVertices(int id, const QVector<glm::vec3>& points, con
#endif
}
void GeometryCache::renderVertices(gpu::Primitive primitiveType, int id) {
gpu::Batch batch;
renderVertices(batch, primitiveType, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderVertices(gpu::Batch& batch, gpu::Primitive primitiveType, int id) {
BatchItemDetails& details = _registeredVertices[id];
if (details.isCreated) {
@ -706,12 +682,6 @@ void GeometryCache::renderVertices(gpu::Batch& batch, gpu::Primitive primitiveTy
}
}
void GeometryCache::renderSolidCube(float size, const glm::vec4& color) {
gpu::Batch batch;
renderSolidCube(batch, size, color);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color) {
Vec2Pair colorKey(glm::vec2(color.x, color.y), glm::vec2(color.z, color.y));
const int FLOATS_PER_VERTEX = 3;
@ -833,12 +803,6 @@ void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::ve
batch.drawIndexed(gpu::TRIANGLES, indices);
}
void GeometryCache::renderWireCube(float size, const glm::vec4& color) {
gpu::Batch batch;
renderWireCube(batch, size, color);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color) {
Vec2Pair colorKey(glm::vec2(color.x, color.y),glm::vec2(color.z, color.y));
const int FLOATS_PER_VERTEX = 3;
@ -922,12 +886,6 @@ void GeometryCache::renderWireCube(gpu::Batch& batch, float size, const glm::vec
batch.drawIndexed(gpu::LINES, indices);
}
void GeometryCache::renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id) {
gpu::Batch batch;
renderBevelCornersRect(batch, x, y, width, height, bevelDistance, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id) {
bool registered = (id != UNKNOWN_ID);
Vec3Pair key(glm::vec3(x, y, 0.0f), glm::vec3(width, height, bevelDistance));
@ -1029,12 +987,6 @@ void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int
batch.draw(gpu::TRIANGLE_STRIP, details.vertices, 0);
}
void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id) {
gpu::Batch batch;
renderQuad(batch, minCorner, maxCorner, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id) {
bool registered = (id != UNKNOWN_ID);
Vec4Pair key(glm::vec4(minCorner.x, minCorner.y, maxCorner.x, maxCorner.y), color);
@ -1111,12 +1063,6 @@ void GeometryCache::renderUnitCube(gpu::Batch& batch) {
renderSolidCube(batch, 1, color);
}
void GeometryCache::renderUnitQuad(const glm::vec4& color, int id) {
gpu::Batch batch;
renderUnitQuad(batch, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, int id) {
static const glm::vec2 topLeft(-1, 1);
static const glm::vec2 bottomRight(1, -1);
@ -1126,14 +1072,6 @@ void GeometryCache::renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, in
}
void GeometryCache::renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner,
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
const glm::vec4& color, int id) {
gpu::Batch batch;
renderQuad(batch, minCorner, maxCorner, texCoordMinCorner, texCoordMaxCorner, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
const glm::vec4& color, int id) {
@ -1214,12 +1152,6 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co
batch.draw(gpu::QUADS, 4, 0);
}
void GeometryCache::renderQuad(const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id) {
gpu::Batch batch;
renderQuad(batch, minCorner, maxCorner, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id) {
bool registered = (id != UNKNOWN_ID);
Vec3PairVec4 key(Vec3Pair(minCorner, maxCorner), color);
@ -1291,17 +1223,6 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, co
batch.draw(gpu::QUADS, 4, 0);
}
void GeometryCache::renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomLeft,
const glm::vec3& bottomRight, const glm::vec3& topRight,
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight,
const glm::vec4& color, int id) {
gpu::Batch batch;
renderQuad(batch, topLeft, bottomLeft, bottomRight, topRight, texCoordTopLeft, texCoordBottomLeft,
texCoordBottomRight, texCoordTopRight, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, const glm::vec3& bottomLeft,
const glm::vec3& bottomRight, const glm::vec3& topRight,
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
@ -1395,12 +1316,6 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, cons
batch.draw(gpu::QUADS, 4, 0);
}
void GeometryCache::renderDashedLine(const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id) {
gpu::Batch batch;
renderDashedLine(batch, start, end, color, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id) {
bool registered = (id != UNKNOWN_ID);
Vec3PairVec2Pair key(Vec3Pair(start, end), Vec2Pair(glm::vec2(color.x, color.y), glm::vec2(color.z, color.w)));
@ -1555,13 +1470,6 @@ void GeometryCache::BatchItemDetails::clear() {
stream.reset();
}
void GeometryCache::renderLine(const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2, int id) {
gpu::Batch batch;
renderLine(batch, p1, p2, color1, color2, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2, int id) {
@ -1646,12 +1554,6 @@ void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm
batch.draw(gpu::LINES, 2, 0);
}
void GeometryCache::renderLine(const glm::vec2& p1, const glm::vec2& p2, const glm::vec4& color1, const glm::vec4& color2, int id) {
gpu::Batch batch;
renderLine(batch, p1, p2, color1, color2, id);
gpu::GLBackend::renderBatch(batch);
}
void GeometryCache::renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2,
const glm::vec4& color1, const glm::vec4& color2, int id) {

View file

@ -129,56 +129,35 @@ public:
int allocateID() { return _nextID++; }
static const int UNKNOWN_ID;
void renderSphere(float radius, int slices, int stacks, const glm::vec3& color, bool solid = true, int id = UNKNOWN_ID)
{ renderSphere(radius, slices, stacks, glm::vec4(color, 1.0f), solid, id); }
void renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec3& color, bool solid = true, int id = UNKNOWN_ID)
{ renderSphere(batch, radius, slices, stacks, glm::vec4(color, 1.0f), solid, id); }
void renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid = true, int id = UNKNOWN_ID);
void renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color, bool solid = true, int id = UNKNOWN_ID);
void renderGrid(int xDivisions, int yDivisions, const glm::vec4& color);
void renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color);
void renderGrid(int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id = UNKNOWN_ID);
void renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id = UNKNOWN_ID);
void renderSolidCube(float size, const glm::vec4& color);
void renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color);
void renderWireCube(float size, const glm::vec4& color);
void renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color);
void renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID);
void renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID);
void renderUnitCube(gpu::Batch& batch);
void renderUnitQuad(const glm::vec4& color = glm::vec4(1), int id = UNKNOWN_ID);
void renderUnitQuad(gpu::Batch& batch, const glm::vec4& color = glm::vec4(1), int id = UNKNOWN_ID);
void renderQuad(int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID)
{ renderQuad(glm::vec2(x,y), glm::vec2(x + width, y + height), color, id); }
void renderQuad(gpu::Batch& batch, int x, int y, int width, int height, const glm::vec4& color, int id = UNKNOWN_ID)
{ renderQuad(batch, glm::vec2(x,y), glm::vec2(x + width, y + height), color, id); }
// TODO: I think there's a bug in this version of the renderQuad() that's not correctly rebuilding the vbos
// if the color changes by the corners are the same, as evidenced by the audio meter which should turn white
// when it's clipping
void renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(const glm::vec2& minCorner, const glm::vec2& maxCorner,
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
const glm::vec2& texCoordMinCorner, const glm::vec2& texCoordMaxCorner,
const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(gpu::Batch& batch, const glm::vec3& minCorner, const glm::vec3& maxCorner, const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(const glm::vec3& topLeft, const glm::vec3& bottomLeft,
const glm::vec3& bottomRight, const glm::vec3& topRight,
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
const glm::vec2& texCoordBottomRight, const glm::vec2& texCoordTopRight,
const glm::vec4& color, int id = UNKNOWN_ID);
void renderQuad(gpu::Batch& batch, const glm::vec3& topLeft, const glm::vec3& bottomLeft,
const glm::vec3& bottomRight, const glm::vec3& topRight,
const glm::vec2& texCoordTopLeft, const glm::vec2& texCoordBottomLeft,
@ -186,53 +165,33 @@ public:
const glm::vec4& color, int id = UNKNOWN_ID);
void renderLine(const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& color, int id = UNKNOWN_ID)
{ renderLine(p1, p2, color, color, id); }
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2, const glm::vec3& color, int id = UNKNOWN_ID)
{ renderLine(batch, p1, p2, color, color, id); }
void renderLine(const glm::vec3& p1, const glm::vec3& p2,
const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID)
{ renderLine(p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID)
{ renderLine(batch, p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
void renderLine(const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color, int id = UNKNOWN_ID)
{ renderLine(p1, p2, color, color, id); }
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color, int id = UNKNOWN_ID)
{ renderLine(batch, p1, p2, color, color, id); }
void renderLine(const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
void renderLine(gpu::Batch& batch, const glm::vec3& p1, const glm::vec3& p2,
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
void renderDashedLine(const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id = UNKNOWN_ID);
void renderDashedLine(gpu::Batch& batch, const glm::vec3& start, const glm::vec3& end, const glm::vec4& color, int id = UNKNOWN_ID);
void renderLine(const glm::vec2& p1, const glm::vec2& p2, const glm::vec3& color, int id = UNKNOWN_ID)
{ renderLine(p1, p2, glm::vec4(color, 1.0f), id); }
void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, const glm::vec3& color, int id = UNKNOWN_ID)
{ renderLine(batch, p1, p2, glm::vec4(color, 1.0f), id); }
void renderLine(const glm::vec2& p1, const glm::vec2& p2, const glm::vec4& color, int id = UNKNOWN_ID)
{ renderLine(p1, p2, color, color, id); }
void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2, const glm::vec4& color, int id = UNKNOWN_ID)
{ renderLine(batch, p1, p2, color, color, id); }
void renderLine(const glm::vec2& p1, const glm::vec2& p2,
const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID)
{ renderLine(p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2,
const glm::vec3& color1, const glm::vec3& color2, int id = UNKNOWN_ID)
{ renderLine(batch, p1, p2, glm::vec4(color1, 1.0f), glm::vec4(color2, 1.0f), id); }
void renderLine(const glm::vec2& p1, const glm::vec2& p2,
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
void renderLine(gpu::Batch& batch, const glm::vec2& p1, const glm::vec2& p2,
const glm::vec4& color1, const glm::vec4& color2, int id = UNKNOWN_ID);
@ -240,7 +199,6 @@ public:
void updateVertices(int id, const QVector<glm::vec3>& points, const glm::vec4& color);
void updateVertices(int id, const QVector<glm::vec3>& points, const QVector<glm::vec2>& texCoords, const glm::vec4& color);
void renderVertices(gpu::Batch& batch, gpu::Primitive primitiveType, int id);
void renderVertices(gpu::Primitive primitiveType, int id);
/// Loads geometry from the specified URL.
/// \param fallback a fallback URL to load if the desired one is unavailable

View file

@ -478,7 +478,7 @@ bool Model::updateGeometry() {
void Model::initJointStates(QVector<JointState> states) {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 parentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
_boundingRadius = _rig->initJointStates(states, parentTransform);
_boundingRadius = _rig->initJointStates(states, parentTransform, geometry.neckJointIndex);
}
bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
@ -916,7 +916,7 @@ void Model::removeFromScene(std::shared_ptr<render::Scene> scene, render::Pendin
_readyWhenAdded = false;
}
void Model::renderDebugMeshBoxes() {
void Model::renderDebugMeshBoxes(gpu::Batch& batch) {
int colorNdx = 0;
_mutex.lock();
foreach(AABox box, _calculatedMeshBoxes) {
@ -965,7 +965,7 @@ void Model::renderDebugMeshBoxes() {
{ 0.0f, 0.5f, 0.5f, 1.0f } };
DependencyManager::get<GeometryCache>()->updateVertices(_debugMeshBoxesID, points, color[colorNdx]);
DependencyManager::get<GeometryCache>()->renderVertices(gpu::LINES, _debugMeshBoxesID);
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINES, _debugMeshBoxesID);
colorNdx++;
}
_mutex.unlock();
@ -1341,28 +1341,6 @@ void Model::simulate(float deltaTime, bool fullUpdate) {
}
}
void Model::updateClusterMatrices() {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
glm::mat4 modelToWorld = glm::mat4_cast(_rotation);
for (int i = 0; i < _meshStates.size(); i++) {
MeshState& state = _meshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i);
if (_showTrueJointTransforms) {
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
state.clusterMatrices[j] =
modelToWorld * _rig->getJointTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
}
} else {
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
state.clusterMatrices[j] =
modelToWorld * _rig->getJointVisibleTransform(cluster.jointIndex) * cluster.inverseBindMatrix;
}
}
}
}
void Model::simulateInternal(float deltaTime) {
// update the world space transforms for all joints

View file

@ -308,9 +308,6 @@ protected:
_calculatedMeshTrianglesValid = false;
}
// rebuild the clusterMatrices from the current jointStates
void updateClusterMatrices();
// hook for derived classes to be notified when setUrl invalidates the current model.
virtual void onInvalidate() {};
@ -386,7 +383,7 @@ private:
// debug rendering support
void renderDebugMeshBoxes();
void renderDebugMeshBoxes(gpu::Batch& batch);
int _debugMeshBoxesID = GeometryCache::UNKNOWN_ID;
// helper functions used by render() or renderInScene()

View file

@ -1,25 +0,0 @@
//
// RenderUtil.cpp
// interface/src/renderer
//
// Created by Andrzej Kapolka on 8/15/13.
// Copyright 2013 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 <DependencyManager.h>
#include "GeometryCache.h"
#include "RenderUtil.h"
void renderFullscreenQuad(float sMin, float sMax, float tMin, float tMax) {
glm::vec4 color(1.0f, 1.0f, 1.0f, 1.0f);
glm::vec2 topLeft(-1.0f, -1.0f);
glm::vec2 bottomRight(1.0f, 1.0f);
glm::vec2 texCoordTopLeft(sMin, tMin);
glm::vec2 texCoordBottomRight(sMax, tMax);
DependencyManager::get<GeometryCache>()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, color);
}

View file

@ -1,18 +0,0 @@
//
// RenderUtil.h
// interface/src/renderer
//
// Created by Andrzej Kapolka on 8/15/13.
// Copyright 2013 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_RenderUtil_h
#define hifi_RenderUtil_h
/// Renders a quad from (-1, -1, 0) to (1, 1, 0) with texture coordinates from (sMin, tMin) to (sMax, tMax).
void renderFullscreenQuad(float sMin = 0.0f, float sMax = 1.0f, float tMin = 0.0f, float tMax = 1.0f);
#endif // hifi_RenderUtil_h

View file

@ -325,19 +325,6 @@ void ImageReader::run() {
auto ntex = dynamic_cast<NetworkTexture*>(&*texture);
if (ntex && (ntex->getType() == CUBE_TEXTURE)) {
qCDebug(renderutils) << "Cube map size:" << _url << image.width() << image.height();
} else {
// enforce a fixed maximum area (1024 * 2048)
const int MAXIMUM_AREA_SIZE = 2097152;
if (imageArea > MAXIMUM_AREA_SIZE) {
float scaleRatio = sqrtf((float)MAXIMUM_AREA_SIZE) / sqrtf((float)imageArea);
int resizeWidth = static_cast<int>(std::floor(scaleRatio * static_cast<float>(image.width())));
int resizeHeight = static_cast<int>(std::floor(scaleRatio * static_cast<float>(image.height())));
qCDebug(renderutils) << "Image greater than maximum size:" << _url << image.width() << image.height() <<
" scaled to:" << resizeWidth << resizeHeight;
image = image.scaled(resizeWidth, resizeHeight, Qt::IgnoreAspectRatio);
imageArea = image.width() * image.height();
}
}
int opaquePixels = 0;

View file

@ -40,30 +40,55 @@
*/
#include <iostream>
//#include "FSTReader.h"
// There are two good ways we could organize this:
// 1. Create a MyAvatar the same way that Interface does, and poke at it.
// We can't do that because MyAvatar (and even Avatar) are in interface, not a library, and our build system won't allow that dependency.
// 2. Create just the minimum skeleton in the most direct way possible, using only very basic library APIs (such as fbx).
// I don't think we can do that because not everything we need is exposed directly from, e.g., the fst and fbx readers.
// So here we do neither. Using as much as we can from AvatarData (which is in the avatar and further requires network and audio), and
// duplicating whatever other code we need from (My)Avatar. Ugh. We may refactor that later, but right now, cleaning this up is not on our critical path.
#include <PathUtils.h>
#include "AvatarData.h"
#include "OBJReader.h"
#include "FBXReader.h"
#include "AvatarRig.h" // We might later test Rig vs AvatarRig separately, but for now, we're concentrating on the main use case.
#include "RigTests.h"
QTEST_MAIN(RigTests)
void RigTests::initTestCase() {
AvatarData avatar;
QEventLoop loop; // Create an event loop that will quit when we get the finished signal
QObject::connect(&avatar, &AvatarData::jointsLoaded, &loop, &QEventLoop::quit);
avatar.setSkeletonModelURL(QUrl("https://hifi-public.s3.amazonaws.com/marketplace/contents/4a690585-3fa3-499e-9f8b-fd1226e561b1/e47e6898027aa40f1beb6adecc6a7db5.fst")); // Zach
//std::cout << "sleep start" << std::endl;
loop.exec(); // Nothing is going to happen on this whole run thread until we get this
_rig = new Rig();
}
void RigTests::dummyPassTest() {
// There are two good ways we could organize this:
// 1. Create a MyAvatar the same way that Interface does, and poke at it.
// We can't do that because MyAvatar (and even Avatar) are in interface, not a library, and our build system won't allow that dependency.
// 2. Create just the minimum skeleton in the most direct way possible, using only very basic library APIs (such as fbx).
// I don't think we can do that because not everything we need is exposed directly from, e.g., the fst and fbx readers.
// So here we do neither. Using as much as we can from AvatarData (which is in the avatar and further requires network and audio), and
// duplicating whatever other code we need from (My)Avatar. Ugh. We may refactor that later, but right now, cleaning this up is not on our critical path.
// Joint mapping from fst
auto avatar = std::make_shared<AvatarData>();
QEventLoop loop; // Create an event loop that will quit when we get the finished signal
QObject::connect(avatar.get(), &AvatarData::jointMappingLoaded, &loop, &QEventLoop::quit);
avatar->setSkeletonModelURL(QUrl("https://hifi-public.s3.amazonaws.com/marketplace/contents/4a690585-3fa3-499e-9f8b-fd1226e561b1/e47e6898027aa40f1beb6adecc6a7db5.fst")); // Zach fst
loop.exec(); // Blocking all further tests until signalled.
// Joint geometry from fbx.
QUrl fbxUrl("https://s3.amazonaws.com/hifi-public/models/skeletons/Zack/Zack.fbx");
QNetworkReply* netReply = OBJReader().request(fbxUrl, false); // Just a convenience hack for synchronoud http request
QCOMPARE(netReply->isFinished() && (netReply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200), true);
FBXGeometry geometry = readFBX(netReply->readAll(), QVariantHash());
QCOMPARE(geometry.joints.count(), avatar->getJointNames().count());
QVector<JointState> jointStates;
for (int i = 0; i < geometry.joints.size(); ++i) {
const FBXJoint& joint = geometry.joints[i];
JointState state;
state.setFBXJoint(&joint);
jointStates.append(state);
}
_rig = std::make_shared<AvatarRig>();
_rig->initJointStates(jointStates, glm::mat4(), geometry.neckJointIndex);
std::cout << "Rig is ready " << geometry.joints.count() << " joints " << std::endl;
}
/*void RigTests::dummyPassTest() {
bool x = true;
std::cout << "dummyPassTest x=" << x << std::endl;
QCOMPARE(x, true);
@ -73,4 +98,4 @@ void RigTests::dummyFailTest() {
bool x = false;
std::cout << "dummyFailTest x=" << x << std::endl;
QCOMPARE(x, true);
}
}*/

View file

@ -46,11 +46,11 @@ class RigTests : public QObject {
private slots:
void initTestCase();
void dummyPassTest();
void dummyFailTest();
/*void dummyPassTest();
void dummyFailTest();*/
private:
Rig* _rig;
RigPointer _rig;
};
#endif // hifi_RigTests_h