trying to take joint information into account when raypicking against models

This commit is contained in:
Seth Alves 2016-06-29 17:02:49 -07:00
parent 98df2770a1
commit 5f9c7b6ea5
3 changed files with 135 additions and 34 deletions

View file

@ -435,6 +435,9 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay&
continue;
}
avatarModel->invalidCalculatedMeshBoxes();
avatarModel->recalculateMeshBoxes(true);
QString extraInfo;
bool intersects = avatarModel->findRayIntersectionAgainstSubMeshes(ray.origin, normDirection,
distance, face, surfaceNormal, extraInfo, true);

View file

@ -20,6 +20,7 @@
#include <PathUtils.h>
#include <PerfStat.h>
#include <ViewFrustum.h>
#include <GLMHelpers.h>
#include "AbstractViewStateInterface.h"
#include "MeshPartPayload.h"
@ -441,32 +442,31 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
PROFILE_RANGE(__FUNCTION__);
bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid;
if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded || (!_calculatedMeshPartBoxesValid && pickAgainstTriangles) ) {
if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded ||
(!_calculatedMeshPartBoxesValid && pickAgainstTriangles) ) {
const FBXGeometry& geometry = getFBXGeometry();
int numberOfMeshes = geometry.meshes.size();
_calculatedMeshBoxes.resize(numberOfMeshes);
_calculatedMeshTriangles.clear();
_calculatedMeshTriangles.resize(numberOfMeshes);
_calculatedMeshPartBoxes.clear();
for (int i = 0; i < numberOfMeshes; i++) {
const FBXMesh& mesh = geometry.meshes.at(i);
int okCount = 0;
int notOkCount = 0;
for (int meshIndex = 0; meshIndex < numberOfMeshes; meshIndex++) {
const FBXMesh& mesh = geometry.meshes.at(meshIndex);
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents, _translation, _rotation);
_calculatedMeshBoxes[i] = AABox(scaledMeshExtents);
_calculatedMeshBoxes[meshIndex] = AABox(scaledMeshExtents);
if (pickAgainstTriangles) {
QVector<Triangle> thisMeshTriangles;
glm::mat4 meshTransform;
if (mesh.clusters.size() > 0) {
int jointIndex = mesh.clusters[0].jointIndex;
meshTransform = _rig->getJointTransform(jointIndex);
} else {
meshTransform = mesh.modelTransform;
}
for (int j = 0; j < mesh.parts.size(); j++) {
const FBXMeshPart& part = mesh.parts.at(j);
for (int partIndex = 0; partIndex < mesh.parts.size(); partIndex++) {
const FBXMeshPart& part = mesh.parts.at(partIndex);
bool atLeastOnePointInBounds = false;
AABox thisPartBounds;
@ -483,10 +483,62 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
int i2 = part.quadIndices[vIndex++];
int i3 = part.quadIndices[vIndex++];
glm::vec3 mv0 = glm::vec3(meshTransform * glm::vec4(mesh.vertices[i0], 1.0f));
glm::vec3 mv1 = glm::vec3(meshTransform * glm::vec4(mesh.vertices[i1], 1.0f));
glm::vec3 mv2 = glm::vec3(meshTransform * glm::vec4(mesh.vertices[i2], 1.0f));
glm::vec3 mv3 = glm::vec3(meshTransform * glm::vec4(mesh.vertices[i3], 1.0f));
glm::vec3 v[3];
int ok = 0;
if (meshIndex < _meshStates.size()) {
int quadPointIndexes[ 4 ] = {i0, i1, i2, i3};
for (int pointInQuadIndex = 0; pointInQuadIndex < 4; pointInQuadIndex++) {
int vertexIndex = quadPointIndexes[pointInQuadIndex];
glm::vec4 clusterIndices = mesh.clusterIndices[vertexIndex];
glm::vec4 clusterWeights = mesh.clusterWeights[vertexIndex];
bool vSet = false;
for (int ci = 0; ci < 4; ci++) {
int clusterIndex = (int) clusterIndices[ci];
float clusterWeight = clusterWeights[ci];
if (clusterIndex < 0 ||
clusterIndex >= mesh.clusters.size() ||
clusterWeight == 0.0f) {
continue;
}
const FBXCluster& cluster = mesh.clusters.at(clusterIndex);
auto clusterMatrix = _meshStates[meshIndex].clusterMatrices[cluster.jointIndex];
glm::vec3 meshVertex = mesh.vertices[vertexIndex];
glm::vec3 fuh = transformPoint(clusterMatrix, meshVertex);
glm::vec3 tpoint = clusterWeight * (_translation + fuh);
v[pointInQuadIndex] += tpoint;
vSet = true;
}
if (vSet) {
ok++;
}
}
}
glm::vec3 v0;
glm::vec3 v1;
glm::vec3 v2;
glm::vec3 v3;
glm::vec3 mv0 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f));
glm::vec3 mv1 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f));
glm::vec3 mv2 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f));
glm::vec3 mv3 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f));
if (ok == 4) {
okCount++;
v0 = v[0];
v1 = v[1];
v2 = v[2];
v3 = v[3];
} else {
notOkCount++;
v0 = calculateScaledOffsetPoint(mv0);
v1 = calculateScaledOffsetPoint(mv1);
v2 = calculateScaledOffsetPoint(mv2);
v3 = calculateScaledOffsetPoint(mv3);
}
// track the mesh parts in model space
if (!atLeastOnePointInBounds) {
@ -499,11 +551,6 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
thisPartBounds += mv2;
thisPartBounds += mv3;
glm::vec3 v0 = calculateScaledOffsetPoint(mv0);
glm::vec3 v1 = calculateScaledOffsetPoint(mv1);
glm::vec3 v2 = calculateScaledOffsetPoint(mv2);
glm::vec3 v3 = calculateScaledOffsetPoint(mv3);
// Sam's recommended triangle slices
Triangle tri1 = { v0, v1, v3 };
Triangle tri2 = { v1, v2, v3 };
@ -514,7 +561,6 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
thisMeshTriangles.push_back(tri1);
thisMeshTriangles.push_back(tri2);
}
}
@ -526,9 +572,57 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
int i1 = part.triangleIndices[vIndex++];
int i2 = part.triangleIndices[vIndex++];
glm::vec3 mv0 = glm::vec3(meshTransform * glm::vec4(mesh.vertices[i0], 1.0f));
glm::vec3 mv1 = glm::vec3(meshTransform * glm::vec4(mesh.vertices[i1], 1.0f));
glm::vec3 mv2 = glm::vec3(meshTransform * glm::vec4(mesh.vertices[i2], 1.0f));
glm::vec3 v[3];
int ok = 0;
if (meshIndex < _meshStates.size()) {
int trianglePointIndexes[ 3 ] = {i0, i1, i2};
for (int pointInTriIndex = 0; pointInTriIndex < 3; pointInTriIndex++) {
int vertexIndex = trianglePointIndexes[pointInTriIndex];
glm::vec4 clusterIndices = mesh.clusterIndices[vertexIndex];
glm::vec4 clusterWeights = mesh.clusterWeights[vertexIndex];
bool vSet = false;
for (int ci = 0; ci < 4; ci++) {
int clusterIndex = (int) clusterIndices[ci];
float clusterWeight = clusterWeights[ci];
if (clusterIndex < 0 ||
clusterIndex >= mesh.clusters.size() ||
clusterWeight == 0.0f) {
continue;
}
const FBXCluster& cluster = mesh.clusters.at(clusterIndex);
auto clusterMatrix = _meshStates[meshIndex].clusterMatrices[cluster.jointIndex];
glm::vec3 meshVertex = mesh.vertices[vertexIndex];
glm::vec3 fuh = transformPoint(clusterMatrix, meshVertex);
glm::vec3 tpoint = clusterWeight * (_translation + fuh);
v[pointInTriIndex] += tpoint;
vSet = true;
}
if (vSet) {
ok++;
}
}
}
glm::vec3 mv0 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i0], 1.0f));
glm::vec3 mv1 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f));
glm::vec3 mv2 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f));
glm::vec3 v0;
glm::vec3 v1;
glm::vec3 v2;
if (ok == 3) {
okCount++;
v0 = v[0];
v1 = v[1];
v2 = v[2];
} else {
notOkCount++;
v0 = calculateScaledOffsetPoint(mv0);
v1 = calculateScaledOffsetPoint(mv1);
v2 = calculateScaledOffsetPoint(mv2);
}
// track the mesh parts in model space
if (!atLeastOnePointInBounds) {
@ -540,21 +634,20 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
thisPartBounds += mv1;
thisPartBounds += mv2;
glm::vec3 v0 = calculateScaledOffsetPoint(mv0);
glm::vec3 v1 = calculateScaledOffsetPoint(mv1);
glm::vec3 v2 = calculateScaledOffsetPoint(mv2);
Triangle tri = { v0, v1, v2 };
thisMeshTriangles.push_back(tri);
}
}
_calculatedMeshPartBoxes[QPair<int,int>(i, j)] = thisPartBounds;
_calculatedMeshPartBoxes[QPair<int,int>(meshIndex, partIndex)] = thisPartBounds;
}
_calculatedMeshTriangles[i] = thisMeshTriangles;
_calculatedMeshTriangles[meshIndex] = thisMeshTriangles;
_calculatedMeshPartBoxesValid = true;
}
}
qDebug() << "ok = " << okCount << " not-ok =" << notOkCount;
_calculatedMeshBoxesValid = true;
_calculatedMeshTrianglesValid = pickAgainstTriangles;
}

View file

@ -316,11 +316,14 @@ protected:
float getLimbLength(int jointIndex) const;
/// Allow sub classes to force invalidating the bboxes
public:
void invalidCalculatedMeshBoxes() {
_calculatedMeshBoxesValid = false;
_calculatedMeshPartBoxesValid = false;
_calculatedMeshTrianglesValid = false;
}
protected:
// hook for derived classes to be notified when setUrl invalidates the current model.
virtual void onInvalidate() {};
@ -357,7 +360,9 @@ protected:
bool _calculatedMeshTrianglesValid;
QMutex _mutex;
public:
void recalculateMeshBoxes(bool pickAgainstTriangles = false);
protected:
void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes
static model::MaterialPointer _collisionHullMaterial;