mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 03:58:07 +02:00
Snapshot of no-judder, before cleanup.
This commit is contained in:
parent
d3106de7c1
commit
0065c64b31
14 changed files with 108 additions and 32 deletions
|
@ -1019,6 +1019,8 @@ void Application::paintGL() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_inPaint = true;
|
_inPaint = true;
|
||||||
|
_myAvatar->captureAttitude();
|
||||||
|
_myAvatar->startRender(); //FIXME
|
||||||
Finally clearFlagLambda([this] { _inPaint = false; });
|
Finally clearFlagLambda([this] { _inPaint = false; });
|
||||||
|
|
||||||
auto displayPlugin = getActiveDisplayPlugin();
|
auto displayPlugin = getActiveDisplayPlugin();
|
||||||
|
@ -1236,6 +1238,7 @@ void Application::paintGL() {
|
||||||
gpu::Batch batch;
|
gpu::Batch batch;
|
||||||
batch.resetStages();
|
batch.resetStages();
|
||||||
renderArgs._context->render(batch);
|
renderArgs._context->render(batch);
|
||||||
|
_myAvatar->endRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::runTests() {
|
void Application::runTests() {
|
||||||
|
@ -2152,7 +2155,7 @@ void Application::setAvatarSimrateSample(float sample) {
|
||||||
}
|
}
|
||||||
float Application::getAvatarSimrate() {
|
float Application::getAvatarSimrate() {
|
||||||
uint64_t now = usecTimestampNow();
|
uint64_t now = usecTimestampNow();
|
||||||
|
|
||||||
if (now - _lastAvatarSimsPerSecondUpdate > USECS_PER_SECOND) {
|
if (now - _lastAvatarSimsPerSecondUpdate > USECS_PER_SECOND) {
|
||||||
_avatarSimsPerSecondReport = _avatarSimsPerSecond.getAverage();
|
_avatarSimsPerSecondReport = _avatarSimsPerSecond.getAverage();
|
||||||
_lastAvatarSimsPerSecondUpdate = now;
|
_lastAvatarSimsPerSecondUpdate = now;
|
||||||
|
@ -2444,7 +2447,7 @@ void Application::init() {
|
||||||
// Make sure any new sounds are loaded as soon as know about them.
|
// Make sure any new sounds are loaded as soon as know about them.
|
||||||
connect(tree, &EntityTree::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound);
|
connect(tree, &EntityTree::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound);
|
||||||
connect(_myAvatar, &MyAvatar::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound);
|
connect(_myAvatar, &MyAvatar::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound);
|
||||||
|
|
||||||
setAvatarUpdateThreading(Menu::getInstance()->isOptionChecked(MenuOption::EnableAvatarUpdateThreading));
|
setAvatarUpdateThreading(Menu::getInstance()->isOptionChecked(MenuOption::EnableAvatarUpdateThreading));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -335,7 +335,7 @@ public:
|
||||||
gpu::ContextPointer getGPUContext() const { return _gpuContext; }
|
gpu::ContextPointer getGPUContext() const { return _gpuContext; }
|
||||||
|
|
||||||
const QRect& getMirrorViewRect() const { return _mirrorViewRect; }
|
const QRect& getMirrorViewRect() const { return _mirrorViewRect; }
|
||||||
|
|
||||||
void updateMyAvatarLookAtPosition();
|
void updateMyAvatarLookAtPosition();
|
||||||
AvatarUpdate* getAvatarUpdater() { return _avatarUpdate; }
|
AvatarUpdate* getAvatarUpdater() { return _avatarUpdate; }
|
||||||
MyAvatar* getMyAvatar() { return _myAvatar; }
|
MyAvatar* getMyAvatar() { return _myAvatar; }
|
||||||
|
|
|
@ -316,7 +316,7 @@ void Avatar::removeFromScene(AvatarSharedPointer self, std::shared_ptr<render::S
|
||||||
}
|
}
|
||||||
|
|
||||||
void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||||
avatarLock.lockForRead();
|
//FIXME: startRender();
|
||||||
if (_referential) {
|
if (_referential) {
|
||||||
_referential->update();
|
_referential->update();
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frustum->sphereInFrustum(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) {
|
if (frustum->sphereInFrustum(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) {
|
||||||
avatarLock.unlock();
|
//FIXME endRender();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,7 +542,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
||||||
if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) {
|
if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) {
|
||||||
renderDisplayName(batch, *renderArgs->_viewFrustum, renderArgs->_viewport);
|
renderDisplayName(batch, *renderArgs->_viewFrustum, renderArgs->_viewport);
|
||||||
}
|
}
|
||||||
avatarLock.unlock();
|
//FIXME endRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
||||||
|
|
|
@ -156,6 +156,7 @@ public:
|
||||||
void scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const;
|
void scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const;
|
||||||
|
|
||||||
void slamPosition(const glm::vec3& position);
|
void slamPosition(const glm::vec3& position);
|
||||||
|
virtual void updateAttitude() { _skeletonModel.updateAttitude(); }
|
||||||
|
|
||||||
// Call this when updating Avatar position with a delta. This will allow us to
|
// Call this when updating Avatar position with a delta. This will allow us to
|
||||||
// _accurately_ measure position changes and compute the resulting velocity
|
// _accurately_ measure position changes and compute the resulting velocity
|
||||||
|
|
|
@ -129,9 +129,9 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
||||||
_avatarFades.push_back(avatarIterator.value());
|
_avatarFades.push_back(avatarIterator.value());
|
||||||
avatarIterator = _avatarHash.erase(avatarIterator);
|
avatarIterator = _avatarHash.erase(avatarIterator);
|
||||||
} else {
|
} else {
|
||||||
avatar->avatarLock.lockForWrite();
|
avatar->startUpdate();
|
||||||
avatar->simulate(deltaTime);
|
avatar->simulate(deltaTime);
|
||||||
avatar->avatarLock.unlock();
|
avatar->endUpdate();
|
||||||
++avatarIterator;
|
++avatarIterator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
||||||
render::PendingChanges pendingChanges;
|
render::PendingChanges pendingChanges;
|
||||||
while (fadingIterator != _avatarFades.end()) {
|
while (fadingIterator != _avatarFades.end()) {
|
||||||
auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator);
|
auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator);
|
||||||
avatar->avatarLock.lockForWrite();
|
avatar->startUpdate();
|
||||||
avatar->setTargetScale(avatar->getScale() * SHRINK_RATE, true);
|
avatar->setTargetScale(avatar->getScale() * SHRINK_RATE, true);
|
||||||
if (avatar->getTargetScale() < MIN_FADE_SCALE) {
|
if (avatar->getTargetScale() < MIN_FADE_SCALE) {
|
||||||
avatar->removeFromScene(*fadingIterator, scene, pendingChanges);
|
avatar->removeFromScene(*fadingIterator, scene, pendingChanges);
|
||||||
|
@ -159,7 +159,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
||||||
avatar->simulate(deltaTime);
|
avatar->simulate(deltaTime);
|
||||||
++fadingIterator;
|
++fadingIterator;
|
||||||
}
|
}
|
||||||
avatar->avatarLock.unlock();
|
avatar->endUpdate();
|
||||||
}
|
}
|
||||||
scene->enqueuePendingChanges(pendingChanges);
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,17 +56,20 @@ bool AvatarUpdate::process() {
|
||||||
_lastAvatarUpdate = start;
|
_lastAvatarUpdate = start;
|
||||||
float deltaSeconds = deltaMicroseconds / (float) USECS_PER_SECOND;
|
float deltaSeconds = deltaMicroseconds / (float) USECS_PER_SECOND;
|
||||||
Application::getInstance()->setAvatarSimrateSample(1.0f / deltaSeconds);
|
Application::getInstance()->setAvatarSimrateSample(1.0f / deltaSeconds);
|
||||||
|
|
||||||
|
QSharedPointer<AvatarManager> manager = DependencyManager::get<AvatarManager>();
|
||||||
|
MyAvatar* myAvatar = manager->getMyAvatar();
|
||||||
|
|
||||||
//loop through all the other avatars and simulate them...
|
//loop through all the other avatars and simulate them...
|
||||||
//gets current lookat data, removes missing avatars, etc.
|
//gets current lookat data, removes missing avatars, etc.
|
||||||
DependencyManager::get<AvatarManager>()->updateOtherAvatars(deltaSeconds);
|
manager->updateOtherAvatars(deltaSeconds);
|
||||||
|
|
||||||
Application::getInstance()->getMyAvatar()->avatarLock.lockForWrite();
|
myAvatar->startUpdate();
|
||||||
Application::getInstance()->updateMyAvatarLookAtPosition();
|
Application::getInstance()->updateMyAvatarLookAtPosition();
|
||||||
// Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
// Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
||||||
DependencyManager::get<AvatarManager>()->updateMyAvatar(deltaSeconds);
|
manager->updateMyAvatar(deltaSeconds);
|
||||||
Application::getInstance()->getMyAvatar()->avatarLock.unlock();
|
myAvatar->endUpdate();
|
||||||
|
|
||||||
if (!isThreaded()) {
|
if (!isThreaded()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ private:
|
||||||
quint64 _lastAvatarUpdate; // microsoeconds
|
quint64 _lastAvatarUpdate; // microsoeconds
|
||||||
quint64 _targetInterval; // microseconds
|
quint64 _targetInterval; // microseconds
|
||||||
bool _updateBillboard;
|
bool _updateBillboard;
|
||||||
|
|
||||||
// Goes away if Application::getActiveDisplayPlugin() and friends are made thread safe:
|
// Goes away if Application::getActiveDisplayPlugin() and friends are made thread safe:
|
||||||
public:
|
public:
|
||||||
bool isHMDMode() { return _isHMDMode; }
|
bool isHMDMode() { return _isHMDMode; }
|
||||||
|
|
|
@ -192,6 +192,9 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
PerformanceTimer perfTimer("transform");
|
PerformanceTimer perfTimer("transform");
|
||||||
updateOrientation(deltaTime);
|
updateOrientation(deltaTime);
|
||||||
updatePosition(deltaTime);
|
updatePosition(deltaTime);
|
||||||
|
// The 2 updates set position, orientation, and all manner of physics stuff.
|
||||||
|
// Here we record the results.
|
||||||
|
nextAttitude(getPosition(), getOrientation());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -266,8 +269,7 @@ void MyAvatar::updateFromHMDSensorMatrix(const glm::mat4& hmdSensorMatrix) {
|
||||||
if (getStandingHMDSensorMode()) {
|
if (getStandingHMDSensorMode()) {
|
||||||
// set the body position/orientation to reflect motion due to the head.
|
// set the body position/orientation to reflect motion due to the head.
|
||||||
auto worldMat = _sensorToWorldMatrix * _bodySensorMatrix;
|
auto worldMat = _sensorToWorldMatrix * _bodySensorMatrix;
|
||||||
setPosition(extractTranslation(worldMat));
|
nextAttitude(extractTranslation(worldMat), glm::quat_cast(worldMat));
|
||||||
setOrientation(glm::quat_cast(worldMat));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,10 +40,10 @@ SkeletonModel::~SkeletonModel() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonModel::avatarLockForWriteIfApplicable() {
|
void SkeletonModel::avatarLockForWriteIfApplicable() {
|
||||||
_owningAvatar->avatarLock.lockForWrite();
|
//FIXME _owningAvatar->avatarLock.lockForWrite();
|
||||||
}
|
}
|
||||||
void SkeletonModel::avatarLockReleaseIfApplicable() {
|
void SkeletonModel::avatarLockReleaseIfApplicable() {
|
||||||
_owningAvatar->avatarLock.unlock();
|
//FIXME _owningAvatar->avatarLock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonModel::initJointStates(QVector<JointState> states) {
|
void SkeletonModel::initJointStates(QVector<JointState> states) {
|
||||||
|
@ -154,13 +154,17 @@ void SkeletonModel::updateRig(float deltaTime, glm::mat4 parentTransform) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by Avatar::simulate after it has set the joint states (fullUpdate true if changed),
|
void SkeletonModel::updateAttitude() {
|
||||||
// but just before head has been simulated.
|
|
||||||
void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
|
||||||
setTranslation(_owningAvatar->getSkeletonPosition());
|
setTranslation(_owningAvatar->getSkeletonPosition());
|
||||||
static const glm::quat refOrientation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
static const glm::quat refOrientation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||||
setRotation(_owningAvatar->getOrientation() * refOrientation);
|
setRotation(_owningAvatar->getOrientation() * refOrientation);
|
||||||
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale());
|
setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by Avatar::simulate after it has set the joint states (fullUpdate true if changed),
|
||||||
|
// but just before head has been simulated.
|
||||||
|
void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
||||||
|
updateAttitude();
|
||||||
setBlendshapeCoefficients(_owningAvatar->getHead()->getBlendshapeCoefficients());
|
setBlendshapeCoefficients(_owningAvatar->getHead()->getBlendshapeCoefficients());
|
||||||
|
|
||||||
Model::simulate(deltaTime, fullUpdate);
|
Model::simulate(deltaTime, fullUpdate);
|
||||||
|
|
|
@ -31,6 +31,7 @@ public:
|
||||||
|
|
||||||
virtual void simulate(float deltaTime, bool fullUpdate = true);
|
virtual void simulate(float deltaTime, bool fullUpdate = true);
|
||||||
virtual void updateRig(float deltaTime, glm::mat4 parentTransform);
|
virtual void updateRig(float deltaTime, glm::mat4 parentTransform);
|
||||||
|
void updateAttitude();
|
||||||
|
|
||||||
void renderIKConstraints(gpu::Batch& batch);
|
void renderIKConstraints(gpu::Batch& batch);
|
||||||
|
|
||||||
|
|
|
@ -110,6 +110,54 @@ void AvatarData::setOrientation(const glm::quat& orientation, bool overideRefere
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// There are a number of possible strategies, some more optimal than others in terms of using the latest info
|
||||||
|
// The current one does not update anything until captureAttitude, and then keeps that value until rendered.
|
||||||
|
void AvatarData::nextAttitude(glm::vec3 position, glm::quat orientation) {
|
||||||
|
setPosition(position, true); setOrientation(orientation, true);
|
||||||
|
_nextPending = 1; // FIXME type bool
|
||||||
|
}
|
||||||
|
void AvatarData::captureAttitude() {
|
||||||
|
if (!_nextAllowed) { // We haven't finished rendering the last one
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
avatarLock.lockForWrite();
|
||||||
|
if (_nextPending) {
|
||||||
|
_nextAllowed = false;
|
||||||
|
_nextPosition = getPosition();
|
||||||
|
_nextOrientation = getOrientation();
|
||||||
|
} else {
|
||||||
|
qCDebug(avatars) << "FIXME capture with nothing pending";
|
||||||
|
}
|
||||||
|
avatarLock.unlock();
|
||||||
|
}
|
||||||
|
void AvatarData::startUpdate() {
|
||||||
|
avatarLock.lockForWrite();
|
||||||
|
}
|
||||||
|
void AvatarData::endUpdate() {
|
||||||
|
avatarLock.unlock();
|
||||||
|
}
|
||||||
|
void AvatarData::startRender() {
|
||||||
|
avatarLock.lockForRead();
|
||||||
|
if (!_nextPending) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
glm::vec3 pos = getPosition();
|
||||||
|
glm::quat rot = getOrientation();
|
||||||
|
setPosition(_nextPosition, true);
|
||||||
|
//setOrientation(_nextOrientation, true);
|
||||||
|
updateAttitude();
|
||||||
|
_nextPosition = pos;
|
||||||
|
_nextOrientation = rot;
|
||||||
|
}
|
||||||
|
void AvatarData::endRender() {
|
||||||
|
setPosition(_nextPosition, true);
|
||||||
|
//setOrientation(_nextOrientation, true);
|
||||||
|
updateAttitude();
|
||||||
|
_nextPending = 0;
|
||||||
|
_nextAllowed = true;
|
||||||
|
avatarLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
float AvatarData::getTargetScale() const {
|
float AvatarData::getTargetScale() const {
|
||||||
if (_referential) {
|
if (_referential) {
|
||||||
_referential->update();
|
_referential->update();
|
||||||
|
|
|
@ -198,6 +198,14 @@ public:
|
||||||
glm::quat getOrientation() const;
|
glm::quat getOrientation() const;
|
||||||
virtual void setOrientation(const glm::quat& orientation, bool overideReferential = false);
|
virtual void setOrientation(const glm::quat& orientation, bool overideReferential = false);
|
||||||
|
|
||||||
|
void nextAttitude(glm::vec3 position, glm::quat orientation); // Can be safely called at any time.
|
||||||
|
void captureAttitude(); // Indicates that the latest values are about to be captured for camera, etc.
|
||||||
|
void startUpdate(); // start/end of update iteration
|
||||||
|
void endUpdate();
|
||||||
|
void startRender(); // start/end of rendering
|
||||||
|
void endRender();
|
||||||
|
virtual void updateAttitude() {} // Tell skeleton mesh about changes
|
||||||
|
|
||||||
glm::quat getHeadOrientation() const { return _headData->getOrientation(); }
|
glm::quat getHeadOrientation() const { return _headData->getOrientation(); }
|
||||||
void setHeadOrientation(const glm::quat& orientation) { _headData->setOrientation(orientation); }
|
void setHeadOrientation(const glm::quat& orientation) { _headData->setOrientation(orientation); }
|
||||||
|
|
||||||
|
@ -358,6 +366,11 @@ protected:
|
||||||
float _bodyPitch; // degrees
|
float _bodyPitch; // degrees
|
||||||
float _bodyRoll; // degrees
|
float _bodyRoll; // degrees
|
||||||
|
|
||||||
|
glm::vec3 _nextPosition {};
|
||||||
|
glm::quat _nextOrientation {};
|
||||||
|
int _nextPending = 0;
|
||||||
|
bool _nextAllowed = true;
|
||||||
|
|
||||||
// Body scale
|
// Body scale
|
||||||
float _targetScale;
|
float _targetScale;
|
||||||
|
|
||||||
|
|
|
@ -405,14 +405,11 @@ void DynamicCharacterController::preSimulation(btScalar timeStep) {
|
||||||
|
|
||||||
void DynamicCharacterController::postSimulation() {
|
void DynamicCharacterController::postSimulation() {
|
||||||
if (_enabled && _rigidBody) {
|
if (_enabled && _rigidBody) {
|
||||||
_avatarData->avatarLock.lockForWrite();
|
|
||||||
const btTransform& avatarTransform = _rigidBody->getWorldTransform();
|
const btTransform& avatarTransform = _rigidBody->getWorldTransform();
|
||||||
glm::quat rotation = bulletToGLM(avatarTransform.getRotation());
|
glm::quat rotation = bulletToGLM(avatarTransform.getRotation());
|
||||||
glm::vec3 position = bulletToGLM(avatarTransform.getOrigin());
|
glm::vec3 position = bulletToGLM(avatarTransform.getOrigin());
|
||||||
|
|
||||||
_avatarData->setOrientation(rotation);
|
_avatarData->nextAttitude(position - rotation * _shapeLocalOffset, rotation);
|
||||||
_avatarData->setPosition(position - rotation * _shapeLocalOffset);
|
|
||||||
_avatarData->setVelocity(bulletToGLM(_rigidBody->getLinearVelocity()));
|
_avatarData->setVelocity(bulletToGLM(_rigidBody->getLinearVelocity()));
|
||||||
_avatarData->avatarLock.unlock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1310,7 +1310,7 @@ void Model::updateClusterMatrices() {
|
||||||
if (_showTrueJointTransforms) {
|
if (_showTrueJointTransforms) {
|
||||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||||
auto jointMatrix =_rig->getJointTransform(cluster.jointIndex);
|
auto jointMatrix = _rig->getJointTransform(cluster.jointIndex);
|
||||||
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
|
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
|
||||||
|
|
||||||
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
|
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
|
||||||
|
@ -1324,7 +1324,7 @@ void Model::updateClusterMatrices() {
|
||||||
} else {
|
} else {
|
||||||
for (int j = 0; j < mesh.clusters.size(); j++) {
|
for (int j = 0; j < mesh.clusters.size(); j++) {
|
||||||
const FBXCluster& cluster = mesh.clusters.at(j);
|
const FBXCluster& cluster = mesh.clusters.at(j);
|
||||||
auto jointMatrix = _rig->getJointVisibleTransform(cluster.jointIndex);
|
auto jointMatrix = _rig->getJointVisibleTransform(cluster.jointIndex); // differs from above only in using get...VisibleTransform
|
||||||
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
|
state.clusterMatrices[j] = modelToWorld * jointMatrix * cluster.inverseBindMatrix;
|
||||||
|
|
||||||
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
|
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
|
||||||
|
@ -1472,6 +1472,10 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
|
||||||
return; // bail asap
|
return; // bail asap
|
||||||
}
|
}
|
||||||
|
|
||||||
|
avatarLockForWriteIfApplicable();
|
||||||
|
if (!_calculatedMeshPartOffsetValid)
|
||||||
|
qCDebug(renderutils) << "FIXME surprise!";
|
||||||
|
_calculatedMeshPartOffsetValid = false; // FIXME
|
||||||
// We need to make sure we have valid offsets calculated before we can render
|
// We need to make sure we have valid offsets calculated before we can render
|
||||||
if (!_calculatedMeshPartOffsetValid) {
|
if (!_calculatedMeshPartOffsetValid) {
|
||||||
_mutex.lock();
|
_mutex.lock();
|
||||||
|
@ -1496,10 +1500,10 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
|
||||||
|
|
||||||
// guard against partially loaded meshes
|
// guard against partially loaded meshes
|
||||||
if (meshIndex >= (int)networkMeshes.size() || meshIndex >= (int)geometry.meshes.size() || meshIndex >= (int)_meshStates.size() ) {
|
if (meshIndex >= (int)networkMeshes.size() || meshIndex >= (int)geometry.meshes.size() || meshIndex >= (int)_meshStates.size() ) {
|
||||||
|
avatarLockReleaseIfApplicable();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
avatarLockForWriteIfApplicable();
|
|
||||||
updateClusterMatrices();
|
updateClusterMatrices();
|
||||||
|
|
||||||
const NetworkMesh& networkMesh = *(networkMeshes.at(meshIndex).get());
|
const NetworkMesh& networkMesh = *(networkMeshes.at(meshIndex).get());
|
||||||
|
|
Loading…
Reference in a new issue