mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
pick against avatar's capsule and then against the T-pose mesh
This commit is contained in:
parent
6786a07ac2
commit
11542aeca2
5 changed files with 52 additions and 132 deletions
|
@ -1085,6 +1085,15 @@ void Avatar::computeShapeInfo(ShapeInfo& shapeInfo) {
|
|||
shapeInfo.setOffset(uniformScale * _skeletonModel->getBoundingCapsuleOffset());
|
||||
}
|
||||
|
||||
void Avatar::getCapsule(glm::vec3& start, glm::vec3& end, float& radius) {
|
||||
ShapeInfo shapeInfo;
|
||||
computeShapeInfo(shapeInfo);
|
||||
glm::vec3 halfExtents = shapeInfo.getHalfExtents(); // x = radius, y = halfHeight
|
||||
start = getPosition() - glm::vec3(0, halfExtents.y, 0) + shapeInfo.getOffset();
|
||||
end = getPosition() + glm::vec3(0, halfExtents.y, 0) + shapeInfo.getOffset();
|
||||
radius = halfExtents.x;
|
||||
}
|
||||
|
||||
void Avatar::setMotionState(AvatarMotionState* motionState) {
|
||||
_motionState = motionState;
|
||||
}
|
||||
|
|
|
@ -154,6 +154,7 @@ public:
|
|||
virtual void rebuildCollisionShape();
|
||||
|
||||
virtual void computeShapeInfo(ShapeInfo& shapeInfo);
|
||||
void getCapsule(glm::vec3& start, glm::vec3& end, float& radius);
|
||||
|
||||
AvatarMotionState* getMotionState() { return _motionState; }
|
||||
|
||||
|
|
|
@ -429,18 +429,34 @@ RayToAvatarIntersectionResult AvatarManager::findRayIntersection(const PickRay&
|
|||
glm::vec3 surfaceNormal;
|
||||
|
||||
SkeletonModelPointer avatarModel = avatar->getSkeletonModel();
|
||||
AABox avatarBounds = avatarModel->getRenderableMeshBound();
|
||||
if (!avatarBounds.findRayIntersection(ray.origin, normDirection, distance, face, surfaceNormal)) {
|
||||
// ray doesn't intersect avatar's bounding-box
|
||||
|
||||
// It's better to intersect the ray against the avatar's actual mesh, but this is currently difficult to
|
||||
// do, because the transformed mesh data only exists over in GPU-land. As a compromise, this code
|
||||
// intersects against the avatars capsule and then against the (T-pose) mesh. The end effect is that picking
|
||||
// against the avatar is sort-of right, but you likely wont be able to pick against the arms.
|
||||
|
||||
// TODO -- find a way to extract transformed avatar mesh data from the rendering engine.
|
||||
|
||||
// if we weren't picking against the capsule, we would want to pick against the avatarBounds...
|
||||
// AABox avatarBounds = avatarModel->getRenderableMeshBound();
|
||||
// if (!avatarBounds.findRayIntersection(ray.origin, normDirection, distance, face, surfaceNormal)) {
|
||||
// // ray doesn't intersect avatar's bounding-box
|
||||
// continue;
|
||||
// }
|
||||
|
||||
glm::vec3 start;
|
||||
glm::vec3 end;
|
||||
float radius;
|
||||
avatar->getCapsule(start, end, radius);
|
||||
bool intersects = findRayCapsuleIntersection(ray.origin, normDirection, start, end, radius, distance);
|
||||
if (!intersects) {
|
||||
// ray doesn't intersect avatar's capsule
|
||||
continue;
|
||||
}
|
||||
|
||||
avatarModel->invalidCalculatedMeshBoxes();
|
||||
avatarModel->recalculateMeshBoxes(true);
|
||||
|
||||
QString extraInfo;
|
||||
bool intersects = avatarModel->findRayIntersectionAgainstSubMeshes(ray.origin, normDirection,
|
||||
distance, face, surfaceNormal, extraInfo, true);
|
||||
intersects = avatarModel->findRayIntersectionAgainstSubMeshes(ray.origin, normDirection,
|
||||
distance, face, surfaceNormal, extraInfo, true);
|
||||
|
||||
if (intersects && (!result.intersects || distance < result.distance)) {
|
||||
result.intersects = true;
|
||||
|
|
|
@ -442,31 +442,23 @@ 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();
|
||||
|
||||
|
||||
|
||||
int okCount = 0;
|
||||
int notOkCount = 0;
|
||||
|
||||
|
||||
for (int meshIndex = 0; meshIndex < numberOfMeshes; meshIndex++) {
|
||||
const FBXMesh& mesh = geometry.meshes.at(meshIndex);
|
||||
for (int i = 0; i < numberOfMeshes; i++) {
|
||||
const FBXMesh& mesh = geometry.meshes.at(i);
|
||||
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents, _translation, _rotation);
|
||||
|
||||
_calculatedMeshBoxes[meshIndex] = AABox(scaledMeshExtents);
|
||||
_calculatedMeshBoxes[i] = AABox(scaledMeshExtents);
|
||||
|
||||
if (pickAgainstTriangles) {
|
||||
QVector<Triangle> thisMeshTriangles;
|
||||
for (int partIndex = 0; partIndex < mesh.parts.size(); partIndex++) {
|
||||
const FBXMeshPart& part = mesh.parts.at(partIndex);
|
||||
for (int j = 0; j < mesh.parts.size(); j++) {
|
||||
const FBXMeshPart& part = mesh.parts.at(j);
|
||||
|
||||
bool atLeastOnePointInBounds = false;
|
||||
AABox thisPartBounds;
|
||||
|
@ -483,63 +475,11 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
|||
int i2 = part.quadIndices[vIndex++];
|
||||
int i3 = part.quadIndices[vIndex++];
|
||||
|
||||
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) {
|
||||
thisPartBounds.setBox(mv0, 0.0f);
|
||||
|
@ -551,6 +491,11 @@ 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 };
|
||||
|
@ -561,6 +506,7 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
|||
|
||||
thisMeshTriangles.push_back(tri1);
|
||||
thisMeshTriangles.push_back(tri2);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,58 +518,10 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
|
|||
int i1 = part.triangleIndices[vIndex++];
|
||||
int i2 = part.triangleIndices[vIndex++];
|
||||
|
||||
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) {
|
||||
thisPartBounds.setBox(mv0, 0.0f);
|
||||
|
@ -634,20 +532,21 @@ 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>(meshIndex, partIndex)] = thisPartBounds;
|
||||
_calculatedMeshPartBoxes[QPair<int,int>(i, j)] = thisPartBounds;
|
||||
}
|
||||
_calculatedMeshTriangles[meshIndex] = thisMeshTriangles;
|
||||
_calculatedMeshTriangles[i] = thisMeshTriangles;
|
||||
_calculatedMeshPartBoxesValid = true;
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "ok = " << okCount << " not-ok =" << notOkCount;
|
||||
|
||||
_calculatedMeshBoxesValid = true;
|
||||
_calculatedMeshTrianglesValid = pickAgainstTriangles;
|
||||
}
|
||||
|
|
|
@ -316,14 +316,11 @@ 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() {};
|
||||
|
@ -360,9 +357,7 @@ 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;
|
||||
|
|
Loading…
Reference in a new issue