History

parabola triangle intersection

SamGondelman committed 8 years ago

Commit ca5ce881 parent fcc523f8 files · +333 −19Browse files

Showing the changes to libraries/render-utils/src/Model.cpp (1 of 8 files). Show all

Unified · Split

libraries/render-utils/src/Model.cpp+112−12
@@ -353,31 +353,27 @@ void Model::initJointStates() { · 352 unmodified lines
353353 bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
354354 BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo,
355355 bool pickAgainstTriangles, bool allowBackface) {
356−
357356 bool intersectedSomething = false;
358357
359− // if we aren't active, we can't ray pick yet...
358+ // if we aren't active, we can't pick yet...
360359 if (!isActive()) {
361360 return intersectedSomething;
362361 }
363362
364363 // extents is the entity relative, scaled, centered extents of the entity
365− glm::vec3 position = _translation;
366− glm::mat4 rotation = glm::mat4_cast(_rotation);
367− glm::mat4 translation = glm::translate(position);
368− glm::mat4 modelToWorldMatrix = translation * rotation;
364+ glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation);
369365 glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix);
370366
371367 Extents modelExtents = getMeshExtents(); // NOTE: unrotated
372368
373369 glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum;
374− glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the ray picking in the model frame of reference
370+ glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the picking in the model frame of reference
375371 AABox modelFrameBox(corner, dimensions);
376372
377373 glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f));
378374 glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f));
379375
380− // we can use the AABox's ray intersection by mapping our origin and direction into the model frame
376+ // we can use the AABox's intersection by mapping our origin and direction into the model frame
381377 // and testing intersection there.
382378 if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face, surfaceNormal)) {
383379 QMutexLocker locker(&_mutex);
@@ -395,7 +391,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g · 11 unmodified lines
395391 }
396392
397393 glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset);
398− glm::mat4 meshToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation) * meshToModelMatrix;
394+ glm::mat4 meshToWorldMatrix = modelToWorldMatrix * meshToModelMatrix;
399395 glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix);
400396
401397 glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f));
@@ -405,11 +401,10 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g · 3 unmodified lines
405401 for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
406402 int partIndex = 0;
407403 for (auto &partTriangleSet : meshTriangleSets) {
408− float triangleSetDistance = 0.0f;
404+ float triangleSetDistance;
409405 BoxFace triangleSetFace;
410406 Triangle triangleSetTriangle;
411407 if (partTriangleSet.findRayIntersection(meshFrameOrigin, meshFrameDirection, triangleSetDistance, triangleSetFace, triangleSetTriangle, pickAgainstTriangles, allowBackface)) {
412−
413408 glm::vec3 meshIntersectionPoint = meshFrameOrigin + (meshFrameDirection * triangleSetDistance);
414409 glm::vec3 worldIntersectionPoint = glm::vec3(meshToWorldMatrix * glm::vec4(meshIntersectionPoint, 1.0f));
415410 float worldDistance = glm::distance(origin, worldIntersectionPoint);
@@ -457,6 +452,111 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g · 41 unmodified lines
457452 return intersectedSomething;
458453 }
459454
455+bool Model::findParabolaIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
456+ float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo,
457+ bool pickAgainstTriangles, bool allowBackface) {
458+ bool intersectedSomething = false;
459+
460+ // if we aren't active, we can't pick yet...
461+ if (!isActive()) {
462+ return intersectedSomething;
463+ }
464+
465+ // extents is the entity relative, scaled, centered extents of the entity
466+ glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation);
467+ glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix);
468+
469+ Extents modelExtents = getMeshExtents(); // NOTE: unrotated
470+
471+ glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum;
472+ glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the picking in the model frame of reference
473+ AABox modelFrameBox(corner, dimensions);
474+
475+ glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f));
476+ glm::vec3 modelFrameVelocity = glm::vec3(worldToModelMatrix * glm::vec4(velocity, 0.0f));
477+ glm::vec3 modelFrameAcceleration = glm::vec3(worldToModelMatrix * glm::vec4(acceleration, 0.0f));
478+
479+ // we can use the AABox's intersection by mapping our origin and direction into the model frame
480+ // and testing intersection there.
481+ if (modelFrameBox.findParabolaIntersection(modelFrameOrigin, modelFrameVelocity, modelFrameAcceleration, parabolicDistance, face, surfaceNormal)) {
482+ QMutexLocker locker(&_mutex);
483+
484+ float bestDistance = FLT_MAX;
485+ Triangle bestModelTriangle;
486+ Triangle bestWorldTriangle;
487+ int bestSubMeshIndex = 0;
488+
489+ int subMeshIndex = 0;
490+ const FBXGeometry& geometry = getFBXGeometry();
491+
492+ if (!_triangleSetsValid) {
493+ calculateTriangleSets(geometry);
494+ }
495+
496+ glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset);
497+ glm::mat4 meshToWorldMatrix = modelToWorldMatrix * meshToModelMatrix;
498+ glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix);
499+
500+ glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f));
501+ glm::vec3 meshFrameVelocity = glm::vec3(worldToMeshMatrix * glm::vec4(velocity, 0.0f));
502+ glm::vec3 meshFrameAcceleration = glm::vec3(worldToMeshMatrix * glm::vec4(acceleration, 0.0f));
503+
504+ int shapeID = 0;
505+ for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
506+ int partIndex = 0;
507+ for (auto &partTriangleSet : meshTriangleSets) {
508+ float triangleSetDistance;
509+ BoxFace triangleSetFace;
510+ Triangle triangleSetTriangle;
511+ if (partTriangleSet.findParabolaIntersection(meshFrameOrigin, meshFrameVelocity, meshFrameAcceleration,
512+ triangleSetDistance, triangleSetFace, triangleSetTriangle, pickAgainstTriangles, allowBackface)) {
513+ if (triangleSetDistance < bestDistance) {
514+ bestDistance = triangleSetDistance;
515+ intersectedSomething = true;
516+ face = triangleSetFace;
517+ bestModelTriangle = triangleSetTriangle;
518+ bestWorldTriangle = triangleSetTriangle * meshToWorldMatrix;
519+ glm::vec3 worldIntersectionPoint = meshFrameOrigin + meshFrameVelocity * triangleSetDistance +
520+ 0.5f * meshFrameAcceleration * triangleSetDistance * triangleSetDistance;
521+ glm::vec3 meshIntersectionPoint = origin + velocity * triangleSetDistance +
522+ 0.5f * acceleration * triangleSetDistance * triangleSetDistance;
523+ extraInfo["worldIntersectionPoint"] = vec3toVariant(worldIntersectionPoint);
524+ extraInfo["meshIntersectionPoint"] = vec3toVariant(meshIntersectionPoint);
525+ extraInfo["partIndex"] = partIndex;
526+ extraInfo["shapeID"] = shapeID;
527+ bestSubMeshIndex = subMeshIndex;
528+ }
529+ }
530+ partIndex++;
531+ shapeID++;
532+ }
533+ subMeshIndex++;
534+ }
535+
536+ if (intersectedSomething) {
537+ parabolicDistance = bestDistance;
538+ surfaceNormal = bestWorldTriangle.getNormal();
539+ if (pickAgainstTriangles) {
540+ extraInfo["subMeshIndex"] = bestSubMeshIndex;
541+ extraInfo["subMeshName"] = geometry.getModelNameOfMesh(bestSubMeshIndex);
542+ extraInfo["subMeshTriangleWorld"] = QVariantMap{
543+ { "v0", vec3toVariant(bestWorldTriangle.v0) },
544+ { "v1", vec3toVariant(bestWorldTriangle.v1) },
545+ { "v2", vec3toVariant(bestWorldTriangle.v2) },
546+ };
547+ extraInfo["subMeshNormal"] = vec3toVariant(bestModelTriangle.getNormal());
548+ extraInfo["subMeshTriangle"] = QVariantMap{
549+ { "v0", vec3toVariant(bestModelTriangle.v0) },
550+ { "v1", vec3toVariant(bestModelTriangle.v1) },
551+ { "v2", vec3toVariant(bestModelTriangle.v2) },
552+ };
553+ }
554+ }
555+ }
556+
557+ return intersectedSomething;
558+}
559+
460560 bool Model::convexHullContains(glm::vec3 point) {
461561 // if we aren't active, we can't compute that yet...
462562 if (!isActive()) {
@@ -594,7 +694,7 @@ bool Model::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointe · 131 unmodified lines
594694 }
595695 scene->enqueueTransaction(transaction);
596696 }
597− // update triangles for ray picking
697+ // update triangles for picking
598698 {
599699 FBXGeometry geometry;
600700 for (const auto& newMesh : meshes) {