Showing the changes to libraries/render-utils/src/Model.cpp (1 of 5 files). Show all
Unified · Split
| @@ -96,9 +96,6 @@ Model::Model(RigPointer rig, QObject* parent, SpatiallyNestable* spatiallyNestab · 95 unmodified lines | ||
| 96 | 96 | _isVisible(true), |
| 97 | 97 | _blendNumber(0), |
| 98 | 98 | _appliedBlendNumber(0), |
| 99 | − _calculatedMeshPartBoxesValid(false), | |
| 100 | − _calculatedMeshBoxesValid(false), | |
| 101 | − _calculatedMeshTrianglesValid(false), | |
| 102 | 99 | _isWireframe(false), |
| 103 | 100 | _rig(rig) |
| 104 | 101 | { |
| @@ -360,19 +357,14 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g · 255 unmodified lines | ||
| 360 | 357 | // we can use the AABox's ray intersection by mapping our origin and direction into the model frame |
| 361 | 358 | // and testing intersection there. |
| 362 | 359 | if (modelFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face, surfaceNormal)) { |
| 363 | − float bestDistance = std::numeric_limits<float>::max(); | |
| 360 | + QMutexLocker locker(&_mutex); | |
| 364 | 361 | |
| 365 | − float distanceToSubMesh; | |
| 366 | − BoxFace subMeshFace; | |
| 367 | − glm::vec3 subMeshSurfaceNormal; | |
| 362 | + float bestDistance = std::numeric_limits<float>::max(); | |
| 368 | 363 | int subMeshIndex = 0; |
| 369 | − | |
| 370 | 364 | const FBXGeometry& geometry = getFBXGeometry(); |
| 371 | 365 | |
| 372 | − // If we hit the models box, then consider the submeshes... | |
| 373 | − _mutex.lock(); | |
| 374 | − if (!_calculatedMeshBoxesValid || (pickAgainstTriangles && !_calculatedMeshTrianglesValid)) { | |
| 375 | − recalculateMeshBoxes(pickAgainstTriangles); | |
| 366 | + if (!_triangleSetsValid) { | |
| 367 | + calculateTriangleSets(); | |
| 376 | 368 | } |
| 377 | 369 | |
| 378 | 370 | glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset); |
| @@ -382,50 +374,26 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g · 3 unmodified lines | ||
| 382 | 374 | glm::vec3 meshFrameOrigin = glm::vec3(worldToMeshMatrix * glm::vec4(origin, 1.0f)); |
| 383 | 375 | glm::vec3 meshFrameDirection = glm::vec3(worldToMeshMatrix * glm::vec4(direction, 0.0f)); |
| 384 | 376 | |
| 385 | − | |
| 386 | − for (const auto& subMeshBox : _calculatedMeshBoxes) { | |
| 387 | − bool intersectedSubMesh = false; | |
| 388 | − float subMeshDistance = std::numeric_limits<float>::max(); | |
| 389 | − | |
| 390 | − if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace, subMeshSurfaceNormal)) { | |
| 391 | − if (distanceToSubMesh < bestDistance) { | |
| 392 | − if (pickAgainstTriangles) { | |
| 393 | − | |
| 394 | − float subMeshDistance = 0.0f; | |
| 395 | − glm::vec3 subMeshNormal; | |
| 396 | − const auto& meshTriangleSet = _modelSpaceMeshTriangleSets[subMeshIndex]; | |
| 397 | − bool intersectedMesh = meshTriangleSet.findRayIntersection(meshFrameOrigin, meshFrameDirection, subMeshDistance, subMeshNormal); | |
| 398 | − | |
| 399 | − if (intersectedMesh) { | |
| 400 | − glm::vec3 meshIntersectionPoint = meshFrameOrigin + (meshFrameDirection * subMeshDistance); | |
| 401 | − glm::vec3 worldIntersectionPoint = glm::vec3(meshToWorldMatrix * glm::vec4(meshIntersectionPoint, 1.0f)); | |
| 402 | − float worldDistance = glm::distance(origin, worldIntersectionPoint); | |
| 403 | − | |
| 404 | − if (worldDistance < bestDistance) { | |
| 405 | − bestDistance = subMeshDistance; | |
| 406 | − intersectedSomething = true; | |
| 407 | − face = subMeshFace; | |
| 408 | − surfaceNormal = glm::vec3(meshToWorldMatrix * glm::vec4(subMeshNormal, 0.0f)); | |
| 409 | − extraInfo = geometry.getModelNameOfMesh(subMeshIndex); | |
| 410 | − } | |
| 411 | − } | |
| 412 | − } else { | |
| 413 | − // this is the non-triangle picking case... | |
| 414 | − bestDistance = distanceToSubMesh; | |
| 415 | − intersectedSomething = true; | |
| 416 | − face = subMeshFace; | |
| 417 | − surfaceNormal = subMeshSurfaceNormal; | |
| 418 | − extraInfo = geometry.getModelNameOfMesh(subMeshIndex); | |
| 419 | − | |
| 420 | − intersectedSubMesh = true; | |
| 421 | − } | |
| 377 | + for (const auto& triangleSet : _modelSpaceMeshTriangleSets) { | |
| 378 | + float triangleSetDistance = 0.0f; | |
| 379 | + BoxFace triangleSetFace; | |
| 380 | + glm::vec3 triangleSetNormal; | |
| 381 | + if (triangleSet.findRayIntersection(meshFrameOrigin, meshFrameDirection, triangleSetDistance, triangleSetFace, triangleSetNormal, pickAgainstTriangles)) { | |
| 382 | + | |
| 383 | + glm::vec3 meshIntersectionPoint = meshFrameOrigin + (meshFrameDirection * triangleSetDistance); | |
| 384 | + glm::vec3 worldIntersectionPoint = glm::vec3(meshToWorldMatrix * glm::vec4(meshIntersectionPoint, 1.0f)); | |
| 385 | + float worldDistance = glm::distance(origin, worldIntersectionPoint); | |
| 386 | + | |
| 387 | + if (worldDistance < bestDistance) { | |
| 388 | + bestDistance = worldDistance; | |
| 389 | + intersectedSomething = true; | |
| 390 | + face = triangleSetFace; | |
| 391 | + surfaceNormal = glm::vec3(meshToWorldMatrix * glm::vec4(triangleSetNormal, 0.0f)); | |
| 392 | + extraInfo = geometry.getModelNameOfMesh(subMeshIndex); | |
| 422 | 393 | } |
| 423 | 394 | } |
| 424 | − | |
| 425 | − | |
| 426 | 395 | subMeshIndex++; |
| 427 | 396 | } |
| 428 | − _mutex.unlock(); | |
| 429 | 397 | |
| 430 | 398 | if (intersectedSomething) { |
| 431 | 399 | distance = bestDistance; |
| @@ -461,183 +429,98 @@ bool Model::convexHullContains(glm::vec3 point) { · 29 unmodified lines | ||
| 461 | 429 | // we can use the AABox's contains() by mapping our point into the model frame |
| 462 | 430 | // and testing there. |
| 463 | 431 | if (modelFrameBox.contains(modelFramePoint)){ |
| 464 | − _mutex.lock(); | |
| 465 | − if (!_calculatedMeshTrianglesValid) { | |
| 466 | − recalculateMeshBoxes(true); | |
| 432 | + QMutexLocker locker(&_mutex); | |
| 433 | + | |
| 434 | + if (!_triangleSetsValid) { | |
| 435 | + calculateTriangleSets(); | |
| 467 | 436 | } |
| 468 | 437 | |
| 469 | 438 | // If we are inside the models box, then consider the submeshes... |
| 470 | − int subMeshIndex = 0; | |
| 471 | − foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { | |
| 472 | − if (subMeshBox.contains(point)) { | |
| 473 | − | |
| 474 | − glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset); | |
| 475 | − glm::mat4 meshToWorldMatrix = meshToModelMatrix * glm::translate(_translation) * glm::mat4_cast(_rotation); | |
| 476 | − glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix); | |
| 477 | − | |
| 478 | − glm::vec3 meshFramePoint = glm::vec3(worldToMeshMatrix * glm::vec4(point, 1.0f)); | |
| 439 | + glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset); | |
| 440 | + glm::mat4 meshToWorldMatrix = meshToModelMatrix * glm::translate(_translation) * glm::mat4_cast(_rotation); | |
| 441 | + glm::mat4 worldToMeshMatrix = glm::inverse(meshToWorldMatrix); | |
| 442 | + glm::vec3 meshFramePoint = glm::vec3(worldToMeshMatrix * glm::vec4(point, 1.0f)); | |
| 479 | 443 | |
| 480 | − if (_modelSpaceMeshTriangleSets[subMeshIndex].convexHullContains(meshFramePoint)) { | |
| 444 | + for (const auto& triangleSet : _modelSpaceMeshTriangleSets) { | |
| 445 | + const AABox& box = triangleSet.getBounds(); | |
| 446 | + if (box.contains(meshFramePoint)) { | |
| 447 | + if (triangleSet.convexHullContains(meshFramePoint)) { | |
| 481 | 448 | // It's inside this mesh, return true. |
| 482 | − _mutex.unlock(); | |
| 483 | 449 | return true; |
| 484 | 450 | } |
| 485 | 451 | } |
| 486 | − subMeshIndex++; | |
| 487 | 452 | } |
| 488 | − _mutex.unlock(); | |
| 453 | + | |
| 454 | + | |
| 489 | 455 | } |
| 490 | 456 | // It wasn't in any mesh, return false. |
| 491 | 457 | return false; |
| 492 | 458 | } |
| 493 | 459 | |
| 494 | −// TODO: we seem to call this too often when things haven't actually changed... look into optimizing this | |
| 495 | −// Any script might trigger findRayIntersectionAgainstSubMeshes (and maybe convexHullContains), so these | |
| 496 | −// can occur multiple times. In addition, rendering does it's own ray picking in order to decide which | |
| 497 | −// entity-scripts to call. I think it would be best to do the picking once-per-frame (in cpu, or gpu if possible) | |
| 498 | −// and then the calls use the most recent such result. | |
| 499 | −void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { | |
| 460 | +void Model::calculateTriangleSets() { | |
| 500 | 461 | PROFILE_RANGE(render, __FUNCTION__); |
| 501 | − bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; | |
| 502 | 462 | |
| 503 | − if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded || (!_calculatedMeshPartBoxesValid && pickAgainstTriangles) ) { | |
| 463 | + const FBXGeometry& geometry = getFBXGeometry(); | |
| 464 | + int numberOfMeshes = geometry.meshes.size(); | |
| 504 | 465 | |
| 505 | − if (pickAgainstTriangles) { | |
| 506 | − qDebug() << "RECALCULATING triangles!"; | |
| 507 | − } else { | |
| 508 | − qDebug() << "RECALCULATING boxes!"; | |
| 509 | − } | |
| 466 | + _triangleSetsValid = true; | |
| 467 | + _modelSpaceMeshTriangleSets.clear(); | |
| 468 | + _modelSpaceMeshTriangleSets.resize(numberOfMeshes); | |
| 510 | 469 | |
| 511 | − const FBXGeometry& geometry = getFBXGeometry(); | |
| 512 | − int numberOfMeshes = geometry.meshes.size(); | |
| 513 | − _calculatedMeshBoxes.resize(numberOfMeshes); | |
| 514 | − _calculatedMeshPartBoxes.clear(); | |
| 515 | − | |
| 516 | − _modelSpaceMeshTriangleSets.clear(); | |
| 517 | − _modelSpaceMeshTriangleSets.resize(numberOfMeshes); | |
| 518 | − | |
| 519 | − for (int i = 0; i < numberOfMeshes; i++) { | |
| 520 | − const FBXMesh& mesh = geometry.meshes.at(i); | |
| 521 | − Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents, _translation, _rotation); | |
| 522 | − | |
| 523 | − _calculatedMeshBoxes[i] = AABox(scaledMeshExtents); | |
| 524 | − | |
| 525 | − if (pickAgainstTriangles) { | |
| 526 | − | |
| 527 | − for (int j = 0; j < mesh.parts.size(); j++) { | |
| 528 | − const FBXMeshPart& part = mesh.parts.at(j); | |
| 529 | − | |
| 530 | − bool atLeastOnePointInBounds = false; | |
| 531 | − AABox thisPartBounds; | |
| 532 | − | |
| 533 | − const int INDICES_PER_TRIANGLE = 3; | |
| 534 | − const int INDICES_PER_QUAD = 4; | |
| 535 | − | |
| 536 | − if (part.quadIndices.size() > 0) { | |
| 537 | − int numberOfQuads = part.quadIndices.size() / INDICES_PER_QUAD; | |
| 538 | − int vIndex = 0; | |
| 539 | − for (int q = 0; q < numberOfQuads; q++) { | |
| 540 | − int i0 = part.quadIndices[vIndex++]; | |
| 541 | − int i1 = part.quadIndices[vIndex++]; | |
| 542 | − int i2 = part.quadIndices[vIndex++]; | |
| 543 | − int i3 = part.quadIndices[vIndex++]; | |
| 544 | − | |
| 545 | − glm::vec3 mv0 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f)); | |
| 546 | − glm::vec3 mv1 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f)); | |
| 547 | − glm::vec3 mv2 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f)); | |
| 548 | − glm::vec3 mv3 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f)); | |
| 549 | − | |
| 550 | − // track the mesh parts in model space | |
| 551 | − if (!atLeastOnePointInBounds) { | |
| 552 | − thisPartBounds.setBox(mv0, 0.0f); | |
| 553 | − atLeastOnePointInBounds = true; | |
| 554 | − } else { | |
| 555 | − thisPartBounds += mv0; | |
| 556 | − } | |
| 557 | − thisPartBounds += mv1; | |
| 558 | − thisPartBounds += mv2; | |
| 559 | − thisPartBounds += mv3; | |
| 560 | − | |
| 561 | − // let's also track the model space version... (eventually using only this!) | |
| 562 | − // these points will be transformed by the FST's offset, which includes the | |
| 563 | − // scaling, rotation, and translation specified by the FST/FBX, this can't change | |
| 564 | − // at runtime, so we can safely store these in our TriangleSet | |
| 565 | − { | |
| 566 | − glm::vec3 v0 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i0], 1.0f)); | |
| 567 | − glm::vec3 v1 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i1], 1.0f)); | |
| 568 | − glm::vec3 v2 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i2], 1.0f)); | |
| 569 | − glm::vec3 v3 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i3], 1.0f)); | |
| 570 | − | |
| 571 | − Triangle tri1 = { v0, v1, v3 }; | |
| 572 | − Triangle tri2 = { v1, v2, v3 }; | |
| 573 | − _modelSpaceMeshTriangleSets[i].insertTriangle(tri1); | |
| 574 | − _modelSpaceMeshTriangleSets[i].insertTriangle(tri2); | |
| 575 | − } | |
| 576 | − | |
| 577 | − } | |
| 578 | − } | |
| 470 | + for (int i = 0; i < numberOfMeshes; i++) { | |
| 471 | + const FBXMesh& mesh = geometry.meshes.at(i); | |
| 579 | 472 | |
| 580 | − if (part.triangleIndices.size() > 0) { | |
| 581 | − int numberOfTris = part.triangleIndices.size() / INDICES_PER_TRIANGLE; | |
| 582 | − int vIndex = 0; | |
| 583 | − for (int t = 0; t < numberOfTris; t++) { | |
| 584 | − int i0 = part.triangleIndices[vIndex++]; | |
| 585 | − int i1 = part.triangleIndices[vIndex++]; | |
| 586 | − int i2 = part.triangleIndices[vIndex++]; | |
| 587 | − | |
| 588 | − glm::vec3 mv0 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f)); | |
| 589 | − glm::vec3 mv1 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f)); | |
| 590 | − glm::vec3 mv2 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f)); | |
| 591 | − | |
| 592 | − // track the mesh parts in model space | |
| 593 | − if (!atLeastOnePointInBounds) { | |
| 594 | − thisPartBounds.setBox(mv0, 0.0f); | |
| 595 | − atLeastOnePointInBounds = true; | |
| 596 | − } else { | |
| 597 | − thisPartBounds += mv0; | |
| 598 | − } | |
| 599 | − thisPartBounds += mv1; | |
| 600 | − thisPartBounds += mv2; | |
| 601 | − | |
| 602 | − // let's also track the model space version... (eventually using only this!) | |
| 603 | − // these points will be transformed by the FST's offset, which includes the | |
| 604 | − // scaling, rotation, and translation specified by the FST/FBX, this can't change | |
| 605 | − // at runtime, so we can safely store these in our TriangleSet | |
| 606 | − { | |
| 607 | − glm::vec3 v0 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i0], 1.0f)); | |
| 608 | − glm::vec3 v1 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i1], 1.0f)); | |
| 609 | − glm::vec3 v2 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i2], 1.0f)); | |
| 610 | − | |
| 611 | − Triangle tri = { v0, v1, v2 }; | |
| 612 | − _modelSpaceMeshTriangleSets[i].insertTriangle(tri); | |
| 613 | − } | |
| 614 | − | |
| 615 | − } | |
| 616 | − } | |
| 617 | − _calculatedMeshPartBoxes[QPair<int,int>(i, j)] = thisPartBounds; | |
| 473 | + for (int j = 0; j < mesh.parts.size(); j++) { | |
| 474 | + const FBXMeshPart& part = mesh.parts.at(j); | |
| 475 | + | |
| 476 | + const int INDICES_PER_TRIANGLE = 3; | |
| 477 | + const int INDICES_PER_QUAD = 4; | |
| 478 | + | |
| 479 | + if (part.quadIndices.size() > 0) { | |
| 480 | + int numberOfQuads = part.quadIndices.size() / INDICES_PER_QUAD; | |
| 481 | + int vIndex = 0; | |
| 482 | + for (int q = 0; q < numberOfQuads; q++) { | |
| 483 | + int i0 = part.quadIndices[vIndex++]; | |
| 484 | + int i1 = part.quadIndices[vIndex++]; | |
| 485 | + int i2 = part.quadIndices[vIndex++]; | |
| 486 | + int i3 = part.quadIndices[vIndex++]; | |
| 487 | + | |
| 488 | + // track the model space version... these points will be transformed by the FST's offset, | |
| 489 | + // which includes the scaling, rotation, and translation specified by the FST/FBX, | |
| 490 | + // this can't change at runtime, so we can safely store these in our TriangleSet | |
| 491 | + glm::vec3 v0 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i0], 1.0f)); | |
| 492 | + glm::vec3 v1 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i1], 1.0f)); | |
| 493 | + glm::vec3 v2 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i2], 1.0f)); | |
| 494 | + glm::vec3 v3 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i3], 1.0f)); | |
| 495 | + | |
| 496 | + Triangle tri1 = { v0, v1, v3 }; | |
| 497 | + Triangle tri2 = { v1, v2, v3 }; | |
| 498 | + _modelSpaceMeshTriangleSets[i].insertTriangle(tri1); | |
| 499 | + _modelSpaceMeshTriangleSets[i].insertTriangle(tri2); | |
| 618 | 500 | } |
| 619 | − _calculatedMeshPartBoxesValid = true; | |
| 620 | 501 | } |
| 621 | − } | |
| 622 | − _calculatedMeshBoxesValid = true; | |
| 623 | − _calculatedMeshTrianglesValid = pickAgainstTriangles; | |
| 624 | − } | |
| 625 | −} | |
| 626 | 502 | |
| 627 | −void Model::renderSetup(RenderArgs* args) { | |
| 628 | − // set up dilated textures on first render after load/simulate | |
| 629 | − const FBXGeometry& geometry = getFBXGeometry(); | |
| 630 | − if (_dilatedTextures.isEmpty()) { | |
| 631 | − foreach (const FBXMesh& mesh, geometry.meshes) { | |
| 632 | − QVector<QSharedPointer<Texture> > dilated; | |
| 633 | − dilated.resize(mesh.parts.size()); | |
| 634 | − _dilatedTextures.append(dilated); | |
| 503 | + if (part.triangleIndices.size() > 0) { | |
| 504 | + int numberOfTris = part.triangleIndices.size() / INDICES_PER_TRIANGLE; | |
| 505 | + int vIndex = 0; | |
| 506 | + for (int t = 0; t < numberOfTris; t++) { | |
| 507 | + int i0 = part.triangleIndices[vIndex++]; | |
| 508 | + int i1 = part.triangleIndices[vIndex++]; | |
| 509 | + int i2 = part.triangleIndices[vIndex++]; | |
| 510 | + | |
| 511 | + // track the model space version... these points will be transformed by the FST's offset, | |
| 512 | + // which includes the scaling, rotation, and translation specified by the FST/FBX, | |
| 513 | + // this can't change at runtime, so we can safely store these in our TriangleSet | |
| 514 | + glm::vec3 v0 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i0], 1.0f)); | |
| 515 | + glm::vec3 v1 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i1], 1.0f)); | |
| 516 | + glm::vec3 v2 = glm::vec3(getFBXGeometry().offset * glm::vec4(mesh.vertices[i2], 1.0f)); | |
| 517 | + | |
| 518 | + Triangle tri = { v0, v1, v2 }; | |
| 519 | + _modelSpaceMeshTriangleSets[i].insertTriangle(tri); | |
| 520 | + } | |
| 521 | + } | |
| 635 | 522 | } |
| 636 | 523 | } |
| 637 | − | |
| 638 | − if (!_addedToScene && isLoaded()) { | |
| 639 | − createRenderItemSet(); | |
| 640 | − } | |
| 641 | 524 | } |
| 642 | 525 | |
| 643 | 526 | void Model::setVisibleInScene(bool newValue, std::shared_ptr<render::Scene> scene) { |
| @@ -752,7 +635,15 @@ void Model::removeFromScene(std::shared_ptr<render::Scene> scene, render::Pendin · 108 unmodified lines | ||
| 752 | 635 | void Model::renderDebugMeshBoxes(gpu::Batch& batch) { |
| 753 | 636 | int colorNdx = 0; |
| 754 | 637 | _mutex.lock(); |
| 755 | − foreach(AABox box, _calculatedMeshBoxes) { | |
| 638 | + | |
| 639 | + glm::mat4 meshToModelMatrix = glm::scale(_scale) * glm::translate(_offset); | |
| 640 | + glm::mat4 meshToWorldMatrix = meshToModelMatrix * glm::translate(_translation) * glm::mat4_cast(_rotation); | |
| 641 | + Transform meshToWorld(meshToWorldMatrix); | |
| 642 | + batch.setModelTransform(meshToWorld); | |
| 643 | + | |
| 644 | + for(const auto& triangleSet : _modelSpaceMeshTriangleSets) { | |
| 645 | + auto box = triangleSet.getBounds(); | |
| 646 | + | |
| 756 | 647 | if (_debugMeshBoxesID == GeometryCache::UNKNOWN_ID) { |
| 757 | 648 | _debugMeshBoxesID = DependencyManager::get<GeometryCache>()->allocateID(); |
| 758 | 649 | } |
| @@ -784,8 +675,8 @@ void Model::renderDebugMeshBoxes(gpu::Batch& batch) { · 25 unmodified lines | ||
| 784 | 675 | points << blf << tlf; |
| 785 | 676 | |
| 786 | 677 | glm::vec4 color[] = { |
| 787 | − { 1.0f, 0.0f, 0.0f, 1.0f }, // red | |
| 788 | 678 | { 0.0f, 1.0f, 0.0f, 1.0f }, // green |
| 679 | + { 1.0f, 0.0f, 0.0f, 1.0f }, // red | |
| 789 | 680 | { 0.0f, 0.0f, 1.0f, 1.0f }, // blue |
| 790 | 681 | { 1.0f, 0.0f, 1.0f, 1.0f }, // purple |
| 791 | 682 | { 1.0f, 1.0f, 0.0f, 1.0f }, // yellow |
| @@ -843,37 +734,6 @@ Extents Model::getUnscaledMeshExtents() const { · 51 unmodified lines | ||
| 843 | 734 | return scaledExtents; |
| 844 | 735 | } |
| 845 | 736 | |
| 846 | −Extents Model::calculateScaledOffsetExtents(const Extents& extents, | |
| 847 | − glm::vec3 modelPosition, glm::quat modelOrientation) const { | |
| 848 | − // we need to include any fst scaling, translation, and rotation, which is captured in the offset matrix | |
| 849 | − glm::vec3 minimum = glm::vec3(getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0f)); | |
| 850 | − glm::vec3 maximum = glm::vec3(getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0f)); | |
| 851 | − | |
| 852 | − Extents scaledOffsetExtents = { ((minimum + _offset) * _scale), | |
| 853 | − ((maximum + _offset) * _scale) }; | |
| 854 | − | |
| 855 | − Extents rotatedExtents = scaledOffsetExtents.getRotated(modelOrientation); | |
| 856 | − | |
| 857 | − Extents translatedExtents = { rotatedExtents.minimum + modelPosition, | |
| 858 | − rotatedExtents.maximum + modelPosition }; | |
| 859 | − | |
| 860 | − return translatedExtents; | |
| 861 | −} | |
| 862 | − | |
| 863 | −/// Returns the world space equivalent of some box in model space. | |
| 864 | −AABox Model::calculateScaledOffsetAABox(const AABox& box, glm::vec3 modelPosition, glm::quat modelOrientation) const { | |
| 865 | − return AABox(calculateScaledOffsetExtents(Extents(box), modelPosition, modelOrientation)); | |
| 866 | −} | |
| 867 | − | |
| 868 | −glm::vec3 Model::calculateScaledOffsetPoint(const glm::vec3& point) const { | |
| 869 | − // we need to include any fst scaling, translation, and rotation, which is captured in the offset matrix | |
| 870 | − glm::vec3 offsetPoint = glm::vec3(getFBXGeometry().offset * glm::vec4(point, 1.0f)); | |
| 871 | − glm::vec3 scaledPoint = ((offsetPoint + _offset) * _scale); | |
| 872 | − glm::vec3 rotatedPoint = _rotation * scaledPoint; | |
| 873 | − glm::vec3 translatedPoint = rotatedPoint + _translation; | |
| 874 | − return translatedPoint; | |
| 875 | −} | |
| 876 | − | |
| 877 | 737 | void Model::clearJointState(int index) { |
| 878 | 738 | _rig->clearJointState(index); |
| 879 | 739 | } |
| @@ -1159,8 +1019,11 @@ void Model::simulate(float deltaTime, bool fullUpdate) { · 279 unmodified lines | ||
| 1159 | 1019 | // they really only become invalid if something about the transform to world space has changed. This is |
| 1160 | 1020 | // not too bad at this point, because it doesn't impact rendering. However it does slow down ray picking |
| 1161 | 1021 | // because ray picking needs valid boxes to work |
| 1162 | − _calculatedMeshBoxesValid = false; | |
| 1163 | − _calculatedMeshTrianglesValid = false; | |
| 1022 | + //_calculatedMeshBoxesValid = false; | |
| 1023 | + //_calculatedMeshTrianglesValid = false; | |
| 1024 | + | |
| 1025 | + // FIXME -- if the model URL changes, then we need to recalculate the triangle sets??!!!! | |
| 1026 | + | |
| 1164 | 1027 | onInvalidate(); |
| 1165 | 1028 | |
| 1166 | 1029 | // check for scale to fit |