mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 18:44:01 +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;
|
||||
}
|
||||
_inPaint = true;
|
||||
_myAvatar->captureAttitude();
|
||||
_myAvatar->startRender(); //FIXME
|
||||
Finally clearFlagLambda([this] { _inPaint = false; });
|
||||
|
||||
auto displayPlugin = getActiveDisplayPlugin();
|
||||
|
@ -1236,6 +1238,7 @@ void Application::paintGL() {
|
|||
gpu::Batch batch;
|
||||
batch.resetStages();
|
||||
renderArgs._context->render(batch);
|
||||
_myAvatar->endRender();
|
||||
}
|
||||
|
||||
void Application::runTests() {
|
||||
|
@ -2152,7 +2155,7 @@ void Application::setAvatarSimrateSample(float sample) {
|
|||
}
|
||||
float Application::getAvatarSimrate() {
|
||||
uint64_t now = usecTimestampNow();
|
||||
|
||||
|
||||
if (now - _lastAvatarSimsPerSecondUpdate > USECS_PER_SECOND) {
|
||||
_avatarSimsPerSecondReport = _avatarSimsPerSecond.getAverage();
|
||||
_lastAvatarSimsPerSecondUpdate = now;
|
||||
|
@ -2444,7 +2447,7 @@ void Application::init() {
|
|||
// Make sure any new sounds are loaded as soon as know about them.
|
||||
connect(tree, &EntityTree::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound);
|
||||
connect(_myAvatar, &MyAvatar::newCollisionSoundURL, DependencyManager::get<SoundCache>().data(), &SoundCache::getSound);
|
||||
|
||||
|
||||
setAvatarUpdateThreading(Menu::getInstance()->isOptionChecked(MenuOption::EnableAvatarUpdateThreading));
|
||||
}
|
||||
|
||||
|
|
|
@ -335,7 +335,7 @@ public:
|
|||
gpu::ContextPointer getGPUContext() const { return _gpuContext; }
|
||||
|
||||
const QRect& getMirrorViewRect() const { return _mirrorViewRect; }
|
||||
|
||||
|
||||
void updateMyAvatarLookAtPosition();
|
||||
AvatarUpdate* getAvatarUpdater() { return _avatarUpdate; }
|
||||
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) {
|
||||
avatarLock.lockForRead();
|
||||
//FIXME: startRender();
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
}
|
||||
|
@ -391,7 +391,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
}
|
||||
|
||||
if (frustum->sphereInFrustum(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) {
|
||||
avatarLock.unlock();
|
||||
//FIXME endRender();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -542,7 +542,7 @@ void Avatar::render(RenderArgs* renderArgs, const glm::vec3& cameraPosition) {
|
|||
if (!isMyAvatar() || cameraMode != CAMERA_MODE_FIRST_PERSON) {
|
||||
renderDisplayName(batch, *renderArgs->_viewFrustum, renderArgs->_viewport);
|
||||
}
|
||||
avatarLock.unlock();
|
||||
//FIXME endRender();
|
||||
}
|
||||
|
||||
glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
|
||||
|
|
|
@ -156,6 +156,7 @@ public:
|
|||
void scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const;
|
||||
|
||||
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
|
||||
// _accurately_ measure position changes and compute the resulting velocity
|
||||
|
|
|
@ -129,9 +129,9 @@ void AvatarManager::updateOtherAvatars(float deltaTime) {
|
|||
_avatarFades.push_back(avatarIterator.value());
|
||||
avatarIterator = _avatarHash.erase(avatarIterator);
|
||||
} else {
|
||||
avatar->avatarLock.lockForWrite();
|
||||
avatar->startUpdate();
|
||||
avatar->simulate(deltaTime);
|
||||
avatar->avatarLock.unlock();
|
||||
avatar->endUpdate();
|
||||
++avatarIterator;
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
|||
render::PendingChanges pendingChanges;
|
||||
while (fadingIterator != _avatarFades.end()) {
|
||||
auto avatar = std::static_pointer_cast<Avatar>(*fadingIterator);
|
||||
avatar->avatarLock.lockForWrite();
|
||||
avatar->startUpdate();
|
||||
avatar->setTargetScale(avatar->getScale() * SHRINK_RATE, true);
|
||||
if (avatar->getTargetScale() < MIN_FADE_SCALE) {
|
||||
avatar->removeFromScene(*fadingIterator, scene, pendingChanges);
|
||||
|
@ -159,7 +159,7 @@ void AvatarManager::simulateAvatarFades(float deltaTime) {
|
|||
avatar->simulate(deltaTime);
|
||||
++fadingIterator;
|
||||
}
|
||||
avatar->avatarLock.unlock();
|
||||
avatar->endUpdate();
|
||||
}
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
}
|
||||
|
|
|
@ -56,17 +56,20 @@ bool AvatarUpdate::process() {
|
|||
_lastAvatarUpdate = start;
|
||||
float deltaSeconds = deltaMicroseconds / (float) USECS_PER_SECOND;
|
||||
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...
|
||||
//gets current lookat data, removes missing avatars, etc.
|
||||
DependencyManager::get<AvatarManager>()->updateOtherAvatars(deltaSeconds);
|
||||
|
||||
Application::getInstance()->getMyAvatar()->avatarLock.lockForWrite();
|
||||
manager->updateOtherAvatars(deltaSeconds);
|
||||
|
||||
myAvatar->startUpdate();
|
||||
Application::getInstance()->updateMyAvatarLookAtPosition();
|
||||
// Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
||||
DependencyManager::get<AvatarManager>()->updateMyAvatar(deltaSeconds);
|
||||
Application::getInstance()->getMyAvatar()->avatarLock.unlock();
|
||||
|
||||
manager->updateMyAvatar(deltaSeconds);
|
||||
myAvatar->endUpdate();
|
||||
|
||||
if (!isThreaded()) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ private:
|
|||
quint64 _lastAvatarUpdate; // microsoeconds
|
||||
quint64 _targetInterval; // microseconds
|
||||
bool _updateBillboard;
|
||||
|
||||
|
||||
// Goes away if Application::getActiveDisplayPlugin() and friends are made thread safe:
|
||||
public:
|
||||
bool isHMDMode() { return _isHMDMode; }
|
||||
|
|
|
@ -192,6 +192,9 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
PerformanceTimer perfTimer("transform");
|
||||
updateOrientation(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()) {
|
||||
// set the body position/orientation to reflect motion due to the head.
|
||||
auto worldMat = _sensorToWorldMatrix * _bodySensorMatrix;
|
||||
setPosition(extractTranslation(worldMat));
|
||||
setOrientation(glm::quat_cast(worldMat));
|
||||
nextAttitude(extractTranslation(worldMat), glm::quat_cast(worldMat));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -40,10 +40,10 @@ SkeletonModel::~SkeletonModel() {
|
|||
}
|
||||
|
||||
void SkeletonModel::avatarLockForWriteIfApplicable() {
|
||||
_owningAvatar->avatarLock.lockForWrite();
|
||||
//FIXME _owningAvatar->avatarLock.lockForWrite();
|
||||
}
|
||||
void SkeletonModel::avatarLockReleaseIfApplicable() {
|
||||
_owningAvatar->avatarLock.unlock();
|
||||
//FIXME _owningAvatar->avatarLock.unlock();
|
||||
}
|
||||
|
||||
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),
|
||||
// but just before head has been simulated.
|
||||
void SkeletonModel::simulate(float deltaTime, bool fullUpdate) {
|
||||
void SkeletonModel::updateAttitude() {
|
||||
setTranslation(_owningAvatar->getSkeletonPosition());
|
||||
static const glm::quat refOrientation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
setRotation(_owningAvatar->getOrientation() * refOrientation);
|
||||
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());
|
||||
|
||||
Model::simulate(deltaTime, fullUpdate);
|
||||
|
|
|
@ -31,6 +31,7 @@ public:
|
|||
|
||||
virtual void simulate(float deltaTime, bool fullUpdate = true);
|
||||
virtual void updateRig(float deltaTime, glm::mat4 parentTransform);
|
||||
void updateAttitude();
|
||||
|
||||
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 {
|
||||
if (_referential) {
|
||||
_referential->update();
|
||||
|
|
|
@ -198,6 +198,14 @@ public:
|
|||
glm::quat getOrientation() const;
|
||||
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(); }
|
||||
void setHeadOrientation(const glm::quat& orientation) { _headData->setOrientation(orientation); }
|
||||
|
||||
|
@ -358,6 +366,11 @@ protected:
|
|||
float _bodyPitch; // degrees
|
||||
float _bodyRoll; // degrees
|
||||
|
||||
glm::vec3 _nextPosition {};
|
||||
glm::quat _nextOrientation {};
|
||||
int _nextPending = 0;
|
||||
bool _nextAllowed = true;
|
||||
|
||||
// Body scale
|
||||
float _targetScale;
|
||||
|
||||
|
|
|
@ -405,14 +405,11 @@ void DynamicCharacterController::preSimulation(btScalar timeStep) {
|
|||
|
||||
void DynamicCharacterController::postSimulation() {
|
||||
if (_enabled && _rigidBody) {
|
||||
_avatarData->avatarLock.lockForWrite();
|
||||
const btTransform& avatarTransform = _rigidBody->getWorldTransform();
|
||||
glm::quat rotation = bulletToGLM(avatarTransform.getRotation());
|
||||
glm::vec3 position = bulletToGLM(avatarTransform.getOrigin());
|
||||
|
||||
_avatarData->setOrientation(rotation);
|
||||
_avatarData->setPosition(position - rotation * _shapeLocalOffset);
|
||||
_avatarData->nextAttitude(position - rotation * _shapeLocalOffset, rotation);
|
||||
_avatarData->setVelocity(bulletToGLM(_rigidBody->getLinearVelocity()));
|
||||
_avatarData->avatarLock.unlock();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1310,7 +1310,7 @@ void Model::updateClusterMatrices() {
|
|||
if (_showTrueJointTransforms) {
|
||||
for (int j = 0; j < mesh.clusters.size(); 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;
|
||||
|
||||
// as an optimization, don't build cautrizedClusterMatrices if the boneSet is empty.
|
||||
|
@ -1324,7 +1324,7 @@ void Model::updateClusterMatrices() {
|
|||
} else {
|
||||
for (int j = 0; j < mesh.clusters.size(); 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;
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
avatarLockForWriteIfApplicable();
|
||||
if (!_calculatedMeshPartOffsetValid)
|
||||
qCDebug(renderutils) << "FIXME surprise!";
|
||||
_calculatedMeshPartOffsetValid = false; // FIXME
|
||||
// We need to make sure we have valid offsets calculated before we can render
|
||||
if (!_calculatedMeshPartOffsetValid) {
|
||||
_mutex.lock();
|
||||
|
@ -1496,10 +1500,10 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran
|
|||
|
||||
// guard against partially loaded meshes
|
||||
if (meshIndex >= (int)networkMeshes.size() || meshIndex >= (int)geometry.meshes.size() || meshIndex >= (int)_meshStates.size() ) {
|
||||
avatarLockReleaseIfApplicable();
|
||||
return;
|
||||
}
|
||||
|
||||
avatarLockForWriteIfApplicable();
|
||||
updateClusterMatrices();
|
||||
|
||||
const NetworkMesh& networkMesh = *(networkMeshes.at(meshIndex).get());
|
||||
|
|
Loading…
Reference in a new issue