mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 03:03:35 +02:00
more correct bounding shapes for Models
This commit is contained in:
parent
cfdbdad2d8
commit
26487aad06
1 changed files with 54 additions and 24 deletions
|
@ -60,11 +60,11 @@ Model::SkinLocations Model::_skinNormalMapLocations;
|
||||||
Model::SkinLocations Model::_skinShadowLocations;
|
Model::SkinLocations Model::_skinShadowLocations;
|
||||||
|
|
||||||
void Model::setScale(const glm::vec3& scale) {
|
void Model::setScale(const glm::vec3& scale) {
|
||||||
glm::vec3 deltaScale = _scale - scale;
|
float scaleLength = glm::length(_scale);
|
||||||
|
float relativeDeltaScale = glm::length(_scale - scale) / scaleLength;
|
||||||
|
|
||||||
// decreased epsilon because this wasn't handling scale changes of 0.01
|
const float ONE_PERCENT = 0.01f;
|
||||||
const float SMALLER_EPSILON = EPSILON * 0.0001f;
|
if (relativeDeltaScale > ONE_PERCENT || scaleLength < EPSILON) {
|
||||||
if (glm::length2(deltaScale) > SMALLER_EPSILON) {
|
|
||||||
_scale = scale;
|
_scale = scale;
|
||||||
rebuildShapes();
|
rebuildShapes();
|
||||||
}
|
}
|
||||||
|
@ -468,20 +468,51 @@ void Model::clearShapes() {
|
||||||
|
|
||||||
void Model::rebuildShapes() {
|
void Model::rebuildShapes() {
|
||||||
clearShapes();
|
clearShapes();
|
||||||
|
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||||
|
|
||||||
if (_jointStates.isEmpty()) {
|
if (geometry.joints.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure all the joints are updated correctly before we try to create their shapes
|
int numJoints = geometry.joints.size();
|
||||||
for (int i = 0; i < _jointStates.size(); i++) {
|
QVector<glm::mat4> transforms;
|
||||||
updateJointState(i);
|
transforms.fill(glm::mat4(), numJoints);
|
||||||
}
|
QVector<glm::quat> combinedRotations;
|
||||||
|
combinedRotations.fill(glm::quat(), numJoints);
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
QVector<bool> shapeIsSet;
|
||||||
|
shapeIsSet.fill(false, numJoints);
|
||||||
|
int rootIndex = 0;
|
||||||
|
|
||||||
float uniformScale = extractUniformScale(_scale);
|
float uniformScale = extractUniformScale(_scale);
|
||||||
glm::quat inverseRotation = glm::inverse(_rotation);
|
int numShapesSet = 0;
|
||||||
glm::vec3 rootPosition(0.f);
|
int lastNumShapesSet = -1;
|
||||||
|
while (numShapesSet < numJoints && numShapesSet != lastNumShapesSet) {
|
||||||
|
lastNumShapesSet = numShapesSet;
|
||||||
|
for (int i = 0; i < numJoints; ++i) {
|
||||||
|
if (shapeIsSet[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const FBXJoint& joint = geometry.joints[i];
|
||||||
|
int parentIndex = joint.parentIndex;
|
||||||
|
if (parentIndex == -1) {
|
||||||
|
rootIndex = i;
|
||||||
|
glm::mat4 baseTransform = glm::mat4_cast(_rotation) * uniformScale * glm::translate(_offset);
|
||||||
|
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||||
|
transforms[i] = baseTransform * geometry.offset * glm::translate(joint.translation) * joint.preTransform *
|
||||||
|
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||||
|
combinedRotations[i] = _rotation * combinedRotation;
|
||||||
|
++numShapesSet;
|
||||||
|
shapeIsSet[i] = true;
|
||||||
|
} else if (shapeIsSet[parentIndex]) {
|
||||||
|
glm::quat combinedRotation = joint.preRotation * joint.rotation * joint.postRotation;
|
||||||
|
transforms[i] = transforms[parentIndex] * glm::translate(joint.translation) * joint.preTransform *
|
||||||
|
glm::mat4_cast(combinedRotation) * joint.postTransform;
|
||||||
|
combinedRotations[i] = combinedRotations[parentIndex] * combinedRotation;
|
||||||
|
++numShapesSet;
|
||||||
|
shapeIsSet[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// joint shapes
|
// joint shapes
|
||||||
Extents totalExtents;
|
Extents totalExtents;
|
||||||
|
@ -489,15 +520,10 @@ void Model::rebuildShapes() {
|
||||||
for (int i = 0; i < _jointStates.size(); i++) {
|
for (int i = 0; i < _jointStates.size(); i++) {
|
||||||
const FBXJoint& joint = geometry.joints[i];
|
const FBXJoint& joint = geometry.joints[i];
|
||||||
|
|
||||||
glm::vec3 jointToShapeOffset = uniformScale * (_jointStates[i].combinedRotation * joint.shapePosition);
|
glm::vec3 worldPosition = extractTranslation(transforms[i]);
|
||||||
glm::vec3 worldPosition = extractTranslation(_jointStates[i].transform) + jointToShapeOffset + _translation;
|
|
||||||
Extents shapeExtents;
|
Extents shapeExtents;
|
||||||
shapeExtents.reset();
|
shapeExtents.reset();
|
||||||
|
|
||||||
if (joint.parentIndex == -1) {
|
|
||||||
rootPosition = worldPosition;
|
|
||||||
}
|
|
||||||
|
|
||||||
float radius = uniformScale * joint.boneRadius;
|
float radius = uniformScale * joint.boneRadius;
|
||||||
float halfHeight = 0.5f * uniformScale * joint.distanceToParent;
|
float halfHeight = 0.5f * uniformScale * joint.distanceToParent;
|
||||||
Shape::Type type = joint.shapeType;
|
Shape::Type type = joint.shapeType;
|
||||||
|
@ -508,7 +534,7 @@ void Model::rebuildShapes() {
|
||||||
if (type == Shape::CAPSULE_SHAPE) {
|
if (type == Shape::CAPSULE_SHAPE) {
|
||||||
CapsuleShape* capsule = new CapsuleShape(radius, halfHeight);
|
CapsuleShape* capsule = new CapsuleShape(radius, halfHeight);
|
||||||
capsule->setPosition(worldPosition);
|
capsule->setPosition(worldPosition);
|
||||||
capsule->setRotation(_jointStates[i].combinedRotation * joint.shapeRotation);
|
capsule->setRotation(combinedRotations[i] * joint.shapeRotation);
|
||||||
_jointShapes.push_back(capsule);
|
_jointShapes.push_back(capsule);
|
||||||
|
|
||||||
glm::vec3 endPoint;
|
glm::vec3 endPoint;
|
||||||
|
@ -526,7 +552,6 @@ void Model::rebuildShapes() {
|
||||||
shapeExtents.addPoint(worldPosition + axis);
|
shapeExtents.addPoint(worldPosition + axis);
|
||||||
shapeExtents.addPoint(worldPosition - axis);
|
shapeExtents.addPoint(worldPosition - axis);
|
||||||
|
|
||||||
|
|
||||||
totalExtents.addExtents(shapeExtents);
|
totalExtents.addExtents(shapeExtents);
|
||||||
} else if (type == Shape::SPHERE_SHAPE) {
|
} else if (type == Shape::SPHERE_SHAPE) {
|
||||||
SphereShape* sphere = new SphereShape(radius, worldPosition);
|
SphereShape* sphere = new SphereShape(radius, worldPosition);
|
||||||
|
@ -539,12 +564,11 @@ void Model::rebuildShapes() {
|
||||||
} else {
|
} else {
|
||||||
// this shape type is not handled and the joint shouldn't collide,
|
// this shape type is not handled and the joint shouldn't collide,
|
||||||
// however we must have a shape for each joint,
|
// however we must have a shape for each joint,
|
||||||
// so we make a bogus sphere and put it at the center of the model
|
// so we make a bogus sphere with zero radius.
|
||||||
// TODO: implement collision groups for more control over what collides with what
|
// TODO: implement collision groups for more control over what collides with what
|
||||||
SphereShape* sphere = new SphereShape(0.f, _offset);
|
SphereShape* sphere = new SphereShape(0.f, worldPosition);
|
||||||
_jointShapes.push_back(sphere);
|
_jointShapes.push_back(sphere);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bounding shape
|
// bounding shape
|
||||||
|
@ -554,7 +578,12 @@ void Model::rebuildShapes() {
|
||||||
float capsuleRadius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
|
float capsuleRadius = 0.5f * sqrtf(0.5f * (diagonal.x * diagonal.x + diagonal.z * diagonal.z));
|
||||||
_boundingShape.setRadius(capsuleRadius);
|
_boundingShape.setRadius(capsuleRadius);
|
||||||
_boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius);
|
_boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius);
|
||||||
|
|
||||||
|
glm::quat inverseRotation = glm::inverse(_rotation);
|
||||||
|
glm::vec3 rootPosition = extractTranslation(transforms[rootIndex]);
|
||||||
_boundingShapeLocalOffset = inverseRotation * (0.5f * (totalExtents.maximum + totalExtents.minimum) - rootPosition);
|
_boundingShapeLocalOffset = inverseRotation * (0.5f * (totalExtents.maximum + totalExtents.minimum) - rootPosition);
|
||||||
|
_boundingShape.setPosition(_translation - _rotation * _boundingShapeLocalOffset);
|
||||||
|
_boundingShape.setRotation(_rotation);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::updateShapePositions() {
|
void Model::updateShapePositions() {
|
||||||
|
@ -581,6 +610,7 @@ void Model::updateShapePositions() {
|
||||||
_boundingRadius = sqrtf(_boundingRadius);
|
_boundingRadius = sqrtf(_boundingRadius);
|
||||||
_shapesAreDirty = false;
|
_shapesAreDirty = false;
|
||||||
_boundingShape.setPosition(rootPosition + _rotation * _boundingShapeLocalOffset);
|
_boundingShape.setPosition(rootPosition + _rotation * _boundingShapeLocalOffset);
|
||||||
|
_boundingShape.setRotation(_rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue