mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 12:12:32 +02:00
Only simulate() Avatar Models when necessary
Also: rebuild collision shapes when Model scale changes
This commit is contained in:
parent
515593e41c
commit
97ba5250a5
8 changed files with 59 additions and 35 deletions
|
@ -117,20 +117,29 @@ void Avatar::simulate(float deltaTime) {
|
||||||
getHand()->simulate(deltaTime, false);
|
getHand()->simulate(deltaTime, false);
|
||||||
_skeletonModel.setLODDistance(getLODDistance());
|
_skeletonModel.setLODDistance(getLODDistance());
|
||||||
|
|
||||||
// copy joint data to skeleton
|
|
||||||
for (int i = 0; i < _jointData.size(); i++) {
|
|
||||||
const JointData& data = _jointData.at(i);
|
|
||||||
_skeletonModel.setJointState(i, data.valid, data.rotation);
|
|
||||||
}
|
|
||||||
glm::vec3 headPosition = _position;
|
|
||||||
if (!_shouldRenderBillboard && inViewFrustum) {
|
if (!_shouldRenderBillboard && inViewFrustum) {
|
||||||
_skeletonModel.simulate(deltaTime);
|
glm::vec3 headPosition = _position;
|
||||||
_skeletonModel.getHeadPosition(headPosition);
|
|
||||||
|
_skeletonModel.updateGeometry();
|
||||||
|
if (_skeletonModel.isActive()) {
|
||||||
|
// copy joint data to skeleton
|
||||||
|
if (_hasNewJointRotations) {
|
||||||
|
for (int i = 0; i < _jointData.size(); i++) {
|
||||||
|
const JointData& data = _jointData.at(i);
|
||||||
|
_skeletonModel.setJointState(i, data.valid, data.rotation);
|
||||||
|
}
|
||||||
|
_skeletonModel.simulate(deltaTime);
|
||||||
|
_hasNewJointRotations = false;
|
||||||
|
}
|
||||||
|
_skeletonModel.getHeadPosition(headPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
Head* head = getHead();
|
||||||
|
head->setPosition(headPosition);
|
||||||
|
head->setScale(_scale);
|
||||||
|
head->getFaceModel().updateGeometry();
|
||||||
|
head->simulate(deltaTime, false, _shouldRenderBillboard);
|
||||||
}
|
}
|
||||||
Head* head = getHead();
|
|
||||||
head->setPosition(headPosition);
|
|
||||||
head->setScale(_scale);
|
|
||||||
head->simulate(deltaTime, false, _shouldRenderBillboard);
|
|
||||||
|
|
||||||
// use speed and angular velocity to determine walking vs. standing
|
// use speed and angular velocity to determine walking vs. standing
|
||||||
if (_speed + fabs(_bodyYawDelta) > 0.2) {
|
if (_speed + fabs(_bodyYawDelta) > 0.2) {
|
||||||
|
|
|
@ -19,8 +19,7 @@ FaceModel::FaceModel(Head* owningHead) :
|
||||||
}
|
}
|
||||||
|
|
||||||
void FaceModel::simulate(float deltaTime) {
|
void FaceModel::simulate(float deltaTime) {
|
||||||
bool geometryIsUpToDate = updateGeometry();
|
if (!isActive()) {
|
||||||
if (!geometryIsUpToDate) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Avatar* owningAvatar = static_cast<Avatar*>(_owningHead->_owningAvatar);
|
Avatar* owningAvatar = static_cast<Avatar*>(_owningHead->_owningAvatar);
|
||||||
|
@ -42,7 +41,7 @@ void FaceModel::simulate(float deltaTime) {
|
||||||
setPupilDilation(_owningHead->getPupilDilation());
|
setPupilDilation(_owningHead->getPupilDilation());
|
||||||
setBlendshapeCoefficients(_owningHead->getBlendshapeCoefficients());
|
setBlendshapeCoefficients(_owningHead->getBlendshapeCoefficients());
|
||||||
|
|
||||||
Model::simulateInternal(deltaTime);
|
Model::simulate(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
||||||
|
|
|
@ -289,6 +289,7 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
getHand()->collideAgainstOurself();
|
getHand()->collideAgainstOurself();
|
||||||
getHand()->simulate(deltaTime, true);
|
getHand()->simulate(deltaTime, true);
|
||||||
|
|
||||||
|
_skeletonModel.updateGeometry();
|
||||||
_skeletonModel.simulate(deltaTime);
|
_skeletonModel.simulate(deltaTime);
|
||||||
|
|
||||||
// copy out the skeleton joints from the model
|
// copy out the skeleton joints from the model
|
||||||
|
@ -305,6 +306,7 @@ void MyAvatar::simulate(float deltaTime) {
|
||||||
}
|
}
|
||||||
head->setPosition(headPosition);
|
head->setPosition(headPosition);
|
||||||
head->setScale(_scale);
|
head->setScale(_scale);
|
||||||
|
head->getFaceModel().updateGeometry();
|
||||||
head->simulate(deltaTime, true);
|
head->simulate(deltaTime, true);
|
||||||
|
|
||||||
// Zero thrust out now that we've added it to velocity in this frame
|
// Zero thrust out now that we've added it to velocity in this frame
|
||||||
|
|
|
@ -19,6 +19,9 @@ SkeletonModel::SkeletonModel(Avatar* owningAvatar) :
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkeletonModel::simulate(float deltaTime) {
|
void SkeletonModel::simulate(float deltaTime) {
|
||||||
|
if (!isActive()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
setTranslation(_owningAvatar->getPosition());
|
setTranslation(_owningAvatar->getPosition());
|
||||||
setRotation(_owningAvatar->getOrientation() * glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)));
|
setRotation(_owningAvatar->getOrientation() * glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)));
|
||||||
const float MODEL_SCALE = 0.0006f;
|
const float MODEL_SCALE = 0.0006f;
|
||||||
|
|
|
@ -56,6 +56,14 @@ Model::SkinLocations Model::_skinLocations;
|
||||||
Model::SkinLocations Model::_skinNormalMapLocations;
|
Model::SkinLocations Model::_skinNormalMapLocations;
|
||||||
Model::SkinLocations Model::_skinShadowLocations;
|
Model::SkinLocations Model::_skinShadowLocations;
|
||||||
|
|
||||||
|
void Model::setScale(const glm::vec3& scale) {
|
||||||
|
glm::vec3 deltaScale = _scale - scale;
|
||||||
|
if (glm::length2(deltaScale) > EPSILON) {
|
||||||
|
_scale = scale;
|
||||||
|
rebuildShapes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations) {
|
void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations) {
|
||||||
program.bind();
|
program.bind();
|
||||||
locations.clusterMatrices = program.uniformLocation("clusterMatrices");
|
locations.clusterMatrices = program.uniformLocation("clusterMatrices");
|
||||||
|
@ -182,10 +190,14 @@ void Model::reset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return 'true' if geometry is up to date
|
void Model::updateGeometry() {
|
||||||
bool Model::updateGeometry() {
|
// NOTE: this is a recursive call that walks all attachments, and their attachments
|
||||||
bool needToRebuild = false;
|
for (int i = 0; i < _attachments.size(); i++) {
|
||||||
|
Model* model = _attachments.at(i);
|
||||||
|
model->updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool needToRebuild = false;
|
||||||
if (_nextGeometry) {
|
if (_nextGeometry) {
|
||||||
_nextGeometry = _nextGeometry->getLODOrFallback(_lodDistance, _nextLODHysteresis);
|
_nextGeometry = _nextGeometry->getLODOrFallback(_lodDistance, _nextLODHysteresis);
|
||||||
_nextGeometry->setLoadPriority(this, -_lodDistance);
|
_nextGeometry->setLoadPriority(this, -_lodDistance);
|
||||||
|
@ -197,7 +209,7 @@ bool Model::updateGeometry() {
|
||||||
}
|
}
|
||||||
if (!_geometry) {
|
if (!_geometry) {
|
||||||
// geometry is not ready
|
// geometry is not ready
|
||||||
return false;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QSharedPointer<NetworkGeometry> geometry = _geometry->getLODOrFallback(_lodDistance, _lodHysteresis);
|
QSharedPointer<NetworkGeometry> geometry = _geometry->getLODOrFallback(_lodDistance, _lodHysteresis);
|
||||||
|
@ -260,9 +272,9 @@ bool Model::updateGeometry() {
|
||||||
model->setURL(attachment.url);
|
model->setURL(attachment.url);
|
||||||
_attachments.append(model);
|
_attachments.append(model);
|
||||||
}
|
}
|
||||||
createShapes();
|
rebuildShapes();
|
||||||
}
|
}
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::render(float alpha, bool forShadowMap) {
|
bool Model::render(float alpha, bool forShadowMap) {
|
||||||
|
@ -440,7 +452,7 @@ void Model::clearShapes() {
|
||||||
_jointShapes.clear();
|
_jointShapes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::createShapes() {
|
void Model::rebuildShapes() {
|
||||||
clearShapes();
|
clearShapes();
|
||||||
|
|
||||||
if (_jointStates.isEmpty()) {
|
if (_jointStates.isEmpty()) {
|
||||||
|
@ -670,20 +682,16 @@ void Blender::run() {
|
||||||
Q_ARG(const QVector<glm::vec3>&, vertices), Q_ARG(const QVector<glm::vec3>&, normals));
|
Q_ARG(const QVector<glm::vec3>&, vertices), Q_ARG(const QVector<glm::vec3>&, normals));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Model::simulate(float deltaTime) {
|
void Model::simulate(float deltaTime) {
|
||||||
bool geometryIsUpToDate = updateGeometry();
|
// NOTE: this is a recursive call that walks all attachments, and their attachments
|
||||||
if (!geometryIsUpToDate) {
|
if (!isActive()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
simulateInternal(deltaTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Model::simulateInternal(float deltaTime) {
|
|
||||||
// update the world space transforms for all joints
|
// update the world space transforms for all joints
|
||||||
for (int i = 0; i < _jointStates.size(); i++) {
|
for (int i = 0; i < _jointStates.size(); i++) {
|
||||||
updateJointState(i);
|
updateJointState(i);
|
||||||
}
|
}
|
||||||
|
_shapesAreDirty = true;
|
||||||
|
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
|
|
||||||
|
@ -720,7 +728,6 @@ void Model::simulateInternal(float deltaTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::updateJointState(int index) {
|
void Model::updateJointState(int index) {
|
||||||
_shapesAreDirty = true;
|
|
||||||
JointState& state = _jointStates[index];
|
JointState& state = _jointStates[index];
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
const FBXJoint& joint = geometry.joints.at(index);
|
const FBXJoint& joint = geometry.joints.at(index);
|
||||||
|
@ -838,6 +845,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position, int last
|
||||||
for (int j = freeLineage.size() - 1; j >= 0; j--) {
|
for (int j = freeLineage.size() - 1; j >= 0; j--) {
|
||||||
updateJointState(freeLineage.at(j));
|
updateJointState(freeLineage.at(j));
|
||||||
}
|
}
|
||||||
|
_shapesAreDirty = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
void setRotation(const glm::quat& rotation) { _rotation = rotation; }
|
void setRotation(const glm::quat& rotation) { _rotation = rotation; }
|
||||||
const glm::quat& getRotation() const { return _rotation; }
|
const glm::quat& getRotation() const { return _rotation; }
|
||||||
|
|
||||||
void setScale(const glm::vec3& scale) { _scale = scale; }
|
void setScale(const glm::vec3& scale);
|
||||||
const glm::vec3& getScale() const { return _scale; }
|
const glm::vec3& getScale() const { return _scale; }
|
||||||
|
|
||||||
void setOffset(const glm::vec3& offset) { _offset = offset; }
|
void setOffset(const glm::vec3& offset) { _offset = offset; }
|
||||||
|
@ -156,7 +156,7 @@ public:
|
||||||
float getRightArmLength() const;
|
float getRightArmLength() const;
|
||||||
|
|
||||||
void clearShapes();
|
void clearShapes();
|
||||||
void createShapes();
|
void rebuildShapes();
|
||||||
void updateShapePositions();
|
void updateShapePositions();
|
||||||
void renderJointCollisionShapes(float alpha);
|
void renderJointCollisionShapes(float alpha);
|
||||||
void renderBoundingCollisionShapes(float alpha);
|
void renderBoundingCollisionShapes(float alpha);
|
||||||
|
@ -185,6 +185,8 @@ public:
|
||||||
/// Sets blended vertices computed in a separate thread.
|
/// Sets blended vertices computed in a separate thread.
|
||||||
void setBlendedVertices(const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals);
|
void setBlendedVertices(const QVector<glm::vec3>& vertices, const QVector<glm::vec3>& normals);
|
||||||
|
|
||||||
|
void updateGeometry();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
QSharedPointer<NetworkGeometry> _geometry;
|
QSharedPointer<NetworkGeometry> _geometry;
|
||||||
|
@ -217,9 +219,6 @@ protected:
|
||||||
|
|
||||||
QVector<MeshState> _meshStates;
|
QVector<MeshState> _meshStates;
|
||||||
|
|
||||||
bool updateGeometry();
|
|
||||||
void simulateInternal(float deltaTime);
|
|
||||||
|
|
||||||
/// Updates the state of the joint at the specified index.
|
/// Updates the state of the joint at the specified index.
|
||||||
virtual void updateJointState(int index);
|
virtual void updateJointState(int index);
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ AvatarData::AvatarData() :
|
||||||
_handState(0),
|
_handState(0),
|
||||||
_keyState(NO_KEY_DOWN),
|
_keyState(NO_KEY_DOWN),
|
||||||
_isChatCirclingEnabled(false),
|
_isChatCirclingEnabled(false),
|
||||||
|
_hasNewJointRotations(true),
|
||||||
_headData(NULL),
|
_headData(NULL),
|
||||||
_handData(NULL),
|
_handData(NULL),
|
||||||
_displayNameBoundingRect(),
|
_displayNameBoundingRect(),
|
||||||
|
@ -483,6 +484,7 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // numJoints * 8 bytes
|
} // numJoints * 8 bytes
|
||||||
|
_hasNewJointRotations = true;
|
||||||
|
|
||||||
return sourceBuffer - startPosition;
|
return sourceBuffer - startPosition;
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,6 +242,8 @@ protected:
|
||||||
|
|
||||||
bool _isChatCirclingEnabled;
|
bool _isChatCirclingEnabled;
|
||||||
|
|
||||||
|
bool _hasNewJointRotations; // set in AvatarData, cleared in Avatar
|
||||||
|
|
||||||
HeadData* _headData;
|
HeadData* _headData;
|
||||||
HandData* _handData;
|
HandData* _handData;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue