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
353bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,353bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance,
354 BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo,354 BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo,
355 bool pickAgainstTriangles, bool allowBackface) {355 bool pickAgainstTriangles, bool allowBackface) {
356
357 bool intersectedSomething = false;356 bool intersectedSomething = false;
358 357
359 // if we aren't active, we can't ray pick yet...358 // if we aren't active, we can't pick yet...
360 if (!isActive()) {359 if (!isActive()) {
361 return intersectedSomething;360 return intersectedSomething;
362 }361 }
363 362
364 // extents is the entity relative, scaled, centered extents of the entity363 // extents is the entity relative, scaled, centered extents of the entity
365 glm::vec3 position = _translation;364 glm::mat4 modelToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation);
366 glm::mat4 rotation = glm::mat4_cast(_rotation);
367 glm::mat4 translation = glm::translate(position);
368 glm::mat4 modelToWorldMatrix = translation * rotation;
369 glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix);365 glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix);
370 366
371 Extents modelExtents = getMeshExtents(); // NOTE: unrotated367 Extents modelExtents = getMeshExtents(); // NOTE: unrotated
372 368
373 glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum;369 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 reference370 glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the picking in the model frame of reference
375 AABox modelFrameBox(corner, dimensions);371 AABox modelFrameBox(corner, dimensions);
376 372
377 glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f));373 glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f));
378 glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f));374 glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f));
379 375
380 // we can use the AABox's ray intersection by mapping our origin and direction into the model frame376 // we can use the AABox's intersection by mapping our origin and direction into the model frame
381 // and testing intersection there.377 // and testing intersection there.
382 if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face, surfaceNormal)) {378 if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face, surfaceNormal)) {
383 QMutexLocker locker(&_mutex);379 QMutexLocker locker(&_mutex);
@@ -395,7 +391,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g · 11 unmodified lines
395 }391 }
396 392
397 glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset);393 glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset);
398 glm::mat4 meshToWorldMatrix = createMatFromQuatAndPos(_rotation, _translation) * meshToModelMatrix;394 glm::mat4 meshToWorldMatrix = modelToWorldMatrix * meshToModelMatrix;
399 glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix);395 glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix);
400 396
401 glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f));397 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
405 for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {401 for (auto& meshTriangleSets : _modelSpaceMeshTriangleSets) {
406 int partIndex = 0;402 int partIndex = 0;
407 for (auto &partTriangleSet : meshTriangleSets) {403 for (auto &partTriangleSet : meshTriangleSets) {
408 float triangleSetDistance = 0.0f;404 float triangleSetDistance;
409 BoxFace triangleSetFace;405 BoxFace triangleSetFace;
410 Triangle triangleSetTriangle;406 Triangle triangleSetTriangle;
411 if (partTriangleSet.findRayIntersection(meshFrameOrigin, meshFrameDirection, triangleSetDistance, triangleSetFace, triangleSetTriangle, pickAgainstTriangles, allowBackface)) {407 if (partTriangleSet.findRayIntersection(meshFrameOrigin, meshFrameDirection, triangleSetDistance, triangleSetFace, triangleSetTriangle, pickAgainstTriangles, allowBackface)) {
412
413 glm::vec3 meshIntersectionPoint = meshFrameOrigin + (meshFrameDirection * triangleSetDistance);408 glm::vec3 meshIntersectionPoint = meshFrameOrigin + (meshFrameDirection * triangleSetDistance);
414 glm::vec3 worldIntersectionPoint = glm::vec3(meshToWorldMatrix * glm::vec4(meshIntersectionPoint, 1.0f));409 glm::vec3 worldIntersectionPoint = glm::vec3(meshToWorldMatrix * glm::vec4(meshIntersectionPoint, 1.0f));
415 float worldDistance = glm::distance(origin, worldIntersectionPoint);410 float worldDistance = glm::distance(origin, worldIntersectionPoint);
@@ -457,6 +452,111 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g · 41 unmodified lines
457 return intersectedSomething;452 return intersectedSomething;
458}453}
459 454
455bool 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
460bool Model::convexHullContains(glm::vec3 point) {560bool Model::convexHullContains(glm::vec3 point) {
461 // if we aren't active, we can't compute that yet...561 // if we aren't active, we can't compute that yet...
462 if (!isActive()) {562 if (!isActive()) {
@@ -594,7 +694,7 @@ bool Model::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointe · 131 unmodified lines
594 }694 }
595 scene->enqueueTransaction(transaction);695 scene->enqueueTransaction(transaction);
596 }696 }
597 // update triangles for ray picking697 // update triangles for picking
598 {698 {
599 FBXGeometry geometry;699 FBXGeometry geometry;
600 for (const auto& newMesh : meshes) {700 for (const auto& newMesh : meshes) {