Simplest fix for the grab crash that occurs with animated complex models.

(e.g., clicking on air hockey props in front of a spinning windmill).
This commit is contained in:
Howard Stearns 2015-05-18 13:08:11 -07:00
parent 5a388a0c14
commit f2a66f3106
2 changed files with 16 additions and 1 deletions

View file

@ -527,12 +527,13 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
const FBXGeometry& geometry = _geometry->getFBXGeometry(); const FBXGeometry& geometry = _geometry->getFBXGeometry();
// If we hit the models box, then consider the submeshes... // If we hit the models box, then consider the submeshes...
_mutex.lock();
foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { foreach(const AABox& subMeshBox, _calculatedMeshBoxes) {
if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) {
if (distanceToSubMesh < bestDistance) { if (distanceToSubMesh < bestDistance) {
if (pickAgainstTriangles) { if (pickAgainstTriangles) {
if (!_calculatedMeshTrianglesValid) { if (!_calculatedMeshTrianglesValid) {
recalculateMeshBoxes(pickAgainstTriangles); recalculateMeshBoxes(pickAgainstTriangles);
} }
// check our triangles here.... // check our triangles here....
@ -562,6 +563,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
} }
subMeshIndex++; subMeshIndex++;
} }
_mutex.unlock();
if (intersectedSomething) { if (intersectedSomething) {
distance = bestDistance; distance = bestDistance;
@ -597,6 +599,7 @@ bool Model::convexHullContains(glm::vec3 point) {
// we can use the AABox's contains() by mapping our point into the model frame // we can use the AABox's contains() by mapping our point into the model frame
// and testing there. // and testing there.
if (modelFrameBox.contains(modelFramePoint)){ if (modelFrameBox.contains(modelFramePoint)){
_mutex.lock();
if (!_calculatedMeshTrianglesValid) { if (!_calculatedMeshTrianglesValid) {
recalculateMeshBoxes(true); recalculateMeshBoxes(true);
} }
@ -618,17 +621,23 @@ bool Model::convexHullContains(glm::vec3 point) {
} }
if (insideMesh) { if (insideMesh) {
// It's inside this mesh, return true. // It's inside this mesh, return true.
_mutex.unlock();
return true; return true;
} }
} }
subMeshIndex++; subMeshIndex++;
} }
_mutex.unlock();
} }
// It wasn't in any mesh, return false. // It wasn't in any mesh, return false.
return false; return false;
} }
// TODO: we seem to call this too often when things haven't actually changed... look into optimizing this // TODO: we seem to call this too often when things haven't actually changed... look into optimizing this
// Any script might trigger findRayIntersectionAgainstSubMeshes (and maybe convexHullContains), so these
// can occur multiple times. In addition, rendering does it's own ray picking in order to decide which
// entity-scripts to call. I think it would be best to do the picking once-per-frame (in cpu, or gpu if possible)
// and then the calls use the most recent such result.
void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid;
@ -711,7 +720,9 @@ void Model::renderSetup(RenderArgs* args) {
// against. We cache the results of these calculations so long as the model hasn't been // against. We cache the results of these calculations so long as the model hasn't been
// simulated and the mesh hasn't changed. // simulated and the mesh hasn't changed.
if (args && !_calculatedMeshBoxesValid) { if (args && !_calculatedMeshBoxesValid) {
_mutex.lock();
recalculateMeshBoxes(); recalculateMeshBoxes();
_mutex.unlock();
} }
// set up dilated textures on first render after load/simulate // set up dilated textures on first render after load/simulate
@ -935,6 +946,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) {
void Model::renderDebugMeshBoxes() { void Model::renderDebugMeshBoxes() {
int colorNdx = 0; int colorNdx = 0;
_mutex.unlock();
foreach(AABox box, _calculatedMeshBoxes) { foreach(AABox box, _calculatedMeshBoxes) {
if (_debugMeshBoxesID == GeometryCache::UNKNOWN_ID) { if (_debugMeshBoxesID == GeometryCache::UNKNOWN_ID) {
_debugMeshBoxesID = DependencyManager::get<GeometryCache>()->allocateID(); _debugMeshBoxesID = DependencyManager::get<GeometryCache>()->allocateID();
@ -984,6 +996,7 @@ void Model::renderDebugMeshBoxes() {
DependencyManager::get<GeometryCache>()->renderVertices(gpu::LINES, _debugMeshBoxesID); DependencyManager::get<GeometryCache>()->renderVertices(gpu::LINES, _debugMeshBoxesID);
colorNdx++; colorNdx++;
} }
_mutex.unlock();
} }
Extents Model::getBindExtents() const { Extents Model::getBindExtents() const {

View file

@ -17,6 +17,7 @@
#include <QBitArray> #include <QBitArray>
#include <QObject> #include <QObject>
#include <QUrl> #include <QUrl>
#include <QMutex>
#include <unordered_map> #include <unordered_map>
#include <functional> #include <functional>
@ -344,6 +345,7 @@ private:
QVector< QVector<Triangle> > _calculatedMeshTriangles; // world coordinate triangles for all sub meshes QVector< QVector<Triangle> > _calculatedMeshTriangles; // world coordinate triangles for all sub meshes
bool _calculatedMeshTrianglesValid; bool _calculatedMeshTrianglesValid;
QMutex _mutex;
void recalculateMeshBoxes(bool pickAgainstTriangles = false); void recalculateMeshBoxes(bool pickAgainstTriangles = false);