mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
Merge pull request #2773 from ey6es/master
Fix for head/eye rotation on models without separate heads.
This commit is contained in:
commit
5918899cf7
8 changed files with 61 additions and 38 deletions
|
@ -555,41 +555,42 @@ void Application::paintGL() {
|
|||
_myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
|
||||
_myCamera.setTargetRotation(_myAvatar->getHead()->getCameraOrientation());
|
||||
|
||||
glm::vec3 planeNormal = _myCamera.getTargetRotation() * IDENTITY_FRONT;
|
||||
const float BASE_PUSHBACK_RADIUS = 0.25f;
|
||||
float pushbackRadius = _myCamera.getNearClip() + _myAvatar->getScale() * BASE_PUSHBACK_RADIUS;
|
||||
glm::vec4 plane(planeNormal, -glm::dot(planeNormal, _myCamera.getTargetPosition()) - pushbackRadius);
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) {
|
||||
glm::vec3 planeNormal = _myCamera.getTargetRotation() * IDENTITY_FRONT;
|
||||
const float BASE_PUSHBACK_RADIUS = 0.25f;
|
||||
float pushbackRadius = _myCamera.getNearClip() + _myAvatar->getScale() * BASE_PUSHBACK_RADIUS;
|
||||
glm::vec4 plane(planeNormal, -glm::dot(planeNormal, _myCamera.getTargetPosition()) - pushbackRadius);
|
||||
|
||||
// push camera out of any intersecting avatars
|
||||
foreach (const AvatarSharedPointer& avatarData, _avatarManager.getAvatarHash()) {
|
||||
Avatar* avatar = static_cast<Avatar*>(avatarData.data());
|
||||
if (avatar->isMyAvatar()) {
|
||||
continue;
|
||||
}
|
||||
if (glm::distance(avatar->getPosition(), _myCamera.getTargetPosition()) >
|
||||
avatar->getBoundingRadius() + pushbackRadius) {
|
||||
continue;
|
||||
}
|
||||
float angle = angleBetween(avatar->getPosition() - _myCamera.getTargetPosition(), planeNormal);
|
||||
if (angle > PI_OVER_TWO) {
|
||||
continue;
|
||||
}
|
||||
float scale = 1.0f - angle / PI_OVER_TWO;
|
||||
scale = qMin(1.0f, scale * 2.5f);
|
||||
static CollisionList collisions(64);
|
||||
collisions.clear();
|
||||
if (!avatar->findPlaneCollisions(plane, collisions)) {
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < collisions.size(); i++) {
|
||||
pushback = qMax(pushback, glm::length(collisions.getCollision(i)->_penetration) * scale);
|
||||
// push camera out of any intersecting avatars
|
||||
foreach (const AvatarSharedPointer& avatarData, _avatarManager.getAvatarHash()) {
|
||||
Avatar* avatar = static_cast<Avatar*>(avatarData.data());
|
||||
if (avatar->isMyAvatar()) {
|
||||
continue;
|
||||
}
|
||||
if (glm::distance(avatar->getPosition(), _myCamera.getTargetPosition()) >
|
||||
avatar->getBoundingRadius() + pushbackRadius) {
|
||||
continue;
|
||||
}
|
||||
float angle = angleBetween(avatar->getPosition() - _myCamera.getTargetPosition(), planeNormal);
|
||||
if (angle > PI_OVER_TWO) {
|
||||
continue;
|
||||
}
|
||||
float scale = 1.0f - angle / PI_OVER_TWO;
|
||||
scale = qMin(1.0f, scale * 2.5f);
|
||||
static CollisionList collisions(64);
|
||||
collisions.clear();
|
||||
if (!avatar->findPlaneCollisions(plane, collisions)) {
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < collisions.size(); i++) {
|
||||
pushback = qMax(pushback, glm::length(collisions.getCollision(i)->_penetration) * scale);
|
||||
}
|
||||
}
|
||||
const float MAX_PUSHBACK = 0.35f;
|
||||
pushback = qMin(pushback, MAX_PUSHBACK * _myAvatar->getScale());
|
||||
const float BASE_PUSHBACK_FOCAL_LENGTH = 0.5f;
|
||||
pushbackFocalLength = BASE_PUSHBACK_FOCAL_LENGTH * _myAvatar->getScale();
|
||||
}
|
||||
const float MAX_PUSHBACK = 0.35f;
|
||||
pushback = qMin(pushback, MAX_PUSHBACK * _myAvatar->getScale());
|
||||
const float BASE_PUSHBACK_FOCAL_LENGTH = 0.5f;
|
||||
pushbackFocalLength = BASE_PUSHBACK_FOCAL_LENGTH * _myAvatar->getScale();
|
||||
|
||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||
_myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
|
||||
_myCamera.setTargetPosition(_myAvatar->getUprightHeadPosition());
|
||||
|
|
|
@ -153,7 +153,7 @@ bool ModelUploader::zip() {
|
|||
|
||||
// mixamo/autodesk defaults
|
||||
if (!mapping.contains(SCALE_FIELD)) {
|
||||
mapping.insert(SCALE_FIELD, 10.0);
|
||||
mapping.insert(SCALE_FIELD, 15.0);
|
||||
}
|
||||
QVariantHash joints = mapping.value(JOINT_FIELD).toHash();
|
||||
if (!joints.contains("jointEyeLeft")) {
|
||||
|
@ -600,7 +600,7 @@ static void setJointText(QComboBox* box, const QString& text) {
|
|||
void ModelPropertiesDialog::reset() {
|
||||
_name->setText(_originalMapping.value(NAME_FIELD).toString());
|
||||
_textureDirectory->setText(_originalMapping.value(TEXDIR_FIELD).toString());
|
||||
_scale->setValue(_originalMapping.value(SCALE_FIELD, 1.0).toDouble());
|
||||
_scale->setValue(_originalMapping.value(SCALE_FIELD).toDouble());
|
||||
|
||||
QVariantHash jointHash = _originalMapping.value(JOINT_FIELD).toHash();
|
||||
setJointText(_leftEyeJoint, jointHash.value("jointEyeLeft").toString());
|
||||
|
|
|
@ -776,7 +776,16 @@ float Avatar::getSkeletonHeight() const {
|
|||
|
||||
float Avatar::getHeadHeight() const {
|
||||
Extents extents = getHead()->getFaceModel().getBindExtents();
|
||||
return extents.maximum.y - extents.minimum.y;
|
||||
if (!extents.isEmpty()) {
|
||||
return extents.maximum.y - extents.minimum.y;
|
||||
}
|
||||
glm::vec3 neckPosition;
|
||||
glm::vec3 headPosition;
|
||||
if (_skeletonModel.getNeckPosition(neckPosition) && _skeletonModel.getHeadPosition(headPosition)) {
|
||||
return glm::distance(neckPosition, headPosition);
|
||||
}
|
||||
const float DEFAULT_HEAD_HEIGHT = 0.1f;
|
||||
return DEFAULT_HEAD_HEIGHT;
|
||||
}
|
||||
|
||||
bool Avatar::collisionWouldMoveAvatar(CollisionInfo& collision) const {
|
||||
|
|
|
@ -26,8 +26,6 @@ public:
|
|||
|
||||
virtual void simulate(float deltaTime, bool fullUpdate = true);
|
||||
|
||||
protected:
|
||||
|
||||
virtual void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
|
||||
virtual void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
|
||||
|
||||
|
|
|
@ -161,7 +161,9 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
|||
_leftEyePosition = _rightEyePosition = getPosition();
|
||||
if (!billboard) {
|
||||
_faceModel.simulate(deltaTime);
|
||||
_faceModel.getEyePositions(_leftEyePosition, _rightEyePosition);
|
||||
if (!_faceModel.getEyePositions(_leftEyePosition, _rightEyePosition)) {
|
||||
static_cast<Avatar*>(_owningAvatar)->getSkeletonModel().getEyePositions(_leftEyePosition, _rightEyePosition);
|
||||
}
|
||||
}
|
||||
_eyePosition = calculateAverageEyePosition();
|
||||
}
|
||||
|
|
|
@ -221,6 +221,14 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const
|
|||
glm::normalize(inverse * axes[0])) * joint.rotation;
|
||||
}
|
||||
|
||||
void SkeletonModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
||||
_owningAvatar->getHead()->getFaceModel().maybeUpdateNeckRotation(parentState, joint, state);
|
||||
}
|
||||
|
||||
void SkeletonModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
|
||||
_owningAvatar->getHead()->getFaceModel().maybeUpdateEyeRotation(parentState, joint, state);
|
||||
}
|
||||
|
||||
void SkeletonModel::renderJointConstraints(int jointIndex) {
|
||||
if (jointIndex == -1) {
|
||||
return;
|
||||
|
|
|
@ -46,6 +46,8 @@ protected:
|
|||
virtual void updateJointState(int index);
|
||||
|
||||
virtual void maybeUpdateLeanRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
|
||||
virtual void maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
|
||||
virtual void maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -47,6 +47,9 @@ public:
|
|||
/// \return true if point is within current limits
|
||||
bool containsPoint(const glm::vec3& point) const;
|
||||
|
||||
/// \return whether or not the extents are empty
|
||||
bool isEmpty() { return minimum == maximum; }
|
||||
|
||||
glm::vec3 minimum;
|
||||
glm::vec3 maximum;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue