diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 91b69d052c..3a12d76626 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -435,13 +435,20 @@ void Model::clearShapes() { void Model::createShapes() { clearShapes(); - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - float uniformScale = extractUniformScale(_scale); - glm::quat inverseRotation = glm::inverse(_rotation); + if (_jointStates.isEmpty()) { + return; + } + + // make sure all the joints are updated correctly before we try to create their shapes for (int i = 0; i < _jointStates.size(); i++) { updateJointState(i); } + + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + float uniformScale = extractUniformScale(_scale); + glm::quat inverseRotation = glm::inverse(_rotation); + glm::vec3 rootPosition(0.f); // joint shapes Extents totalExtents; @@ -454,6 +461,10 @@ void Model::createShapes() { Extents shapeExtents; shapeExtents.reset(); + if (joint.parentIndex == -1) { + rootPosition = worldPosition; + } + float radius = uniformScale * joint.boneRadius; float halfHeight = 0.5f * uniformScale * joint.distanceToParent; if (joint.shapeType == Shape::CAPSULE_SHAPE && halfHeight > EPSILON) { @@ -467,15 +478,15 @@ void Model::createShapes() { glm::vec3 startPoint; capsule->getStartPoint(startPoint); glm::vec3 axis = (halfHeight + radius) * glm::normalize(endPoint - startPoint); - shapeExtents.addPoint(inverseRotation * (worldPosition + axis - _translation)); - shapeExtents.addPoint(inverseRotation * (worldPosition - axis - _translation)); + shapeExtents.addPoint(worldPosition + axis); + shapeExtents.addPoint(worldPosition - axis); } else { SphereShape* sphere = new SphereShape(radius, worldPosition); _jointShapes.push_back(sphere); glm::vec3 axis = glm::vec3(radius); - shapeExtents.addPoint(inverseRotation * (worldPosition + axis - _translation)); - shapeExtents.addPoint(inverseRotation * (worldPosition - axis - _translation)); + shapeExtents.addPoint(worldPosition + axis); + shapeExtents.addPoint(worldPosition - axis); } totalExtents.addExtents(shapeExtents); } @@ -486,11 +497,12 @@ void Model::createShapes() { float capsuleRadius = 0.25f * (diagonal.x + diagonal.z); // half the average of x and z _boundingShape.setRadius(capsuleRadius); _boundingShape.setHalfHeight(0.5f * diagonal.y - capsuleRadius); - _boundingShapeLocalOffset = 0.5f * (totalExtents.maximum + totalExtents.minimum); + _boundingShapeLocalOffset = inverseRotation * (0.5f * (totalExtents.maximum + totalExtents.minimum) - rootPosition); } void Model::updateShapePositions() { if (_shapesAreDirty && _jointShapes.size() == _jointStates.size()) { + glm::vec3 rootPosition(0.f); _boundingRadius = 0.f; float uniformScale = extractUniformScale(_scale); const FBXGeometry& geometry = _geometry->getFBXGeometry(); @@ -505,11 +517,14 @@ void Model::updateShapePositions() { if (distance2 > _boundingRadius) { _boundingRadius = distance2; } + if (joint.parentIndex == -1) { + rootPosition = worldPosition; + } } _boundingRadius = sqrtf(_boundingRadius); _shapesAreDirty = false; + _boundingShape.setPosition(rootPosition + _rotation * _boundingShapeLocalOffset); } - _boundingShape.setPosition(_translation + _rotation * _boundingShapeLocalOffset); } bool Model::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const { diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 205687baa9..43eb7fda67 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -56,7 +56,7 @@ public: void init(); void reset(); - void simulate(float deltaTime); + virtual void simulate(float deltaTime); bool render(float alpha = 1.0f, bool forShadowMap = false); /// Sets the URL of the model to render.