fist cut at basic TriangleSet class

This commit is contained in:
ZappoMan 2017-03-03 22:27:38 -08:00
parent 807e15ade9
commit 9908723bb9
5 changed files with 144 additions and 28 deletions

View file

@ -376,24 +376,26 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
}
for (const auto& subMeshBox : _calculatedMeshBoxes) {
bool intersectedSubMesh = false;
float subMeshDistance = std::numeric_limits<float>::max();
if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace, subMeshSurfaceNormal)) {
if (distanceToSubMesh < bestDistance) {
if (pickAgainstTriangles) {
// check our triangles here....
const QVector<Triangle>& meshTriangles = _calculatedMeshTriangles[subMeshIndex];
for(const auto& triangle : meshTriangles) {
float thisTriangleDistance;
if (findRayTriangleIntersection(origin, direction, triangle, thisTriangleDistance)) {
if (thisTriangleDistance < bestDistance) {
bestDistance = thisTriangleDistance;
intersectedSomething = true;
face = subMeshFace;
surfaceNormal = triangle.getNormal();
extraInfo = geometry.getModelNameOfMesh(subMeshIndex);
}
}
float subMeshDistance;
glm::vec3 subMeshNormal;
const auto& meshTriangleSet = _meshTriangleSets[subMeshIndex];
bool intersectedMesh = meshTriangleSet.findRayIntersection(origin, direction, subMeshDistance, subMeshNormal);
if (intersectedMesh && subMeshDistance < bestDistance) {
bestDistance = subMeshDistance;
intersectedSomething = true;
face = subMeshFace;
surfaceNormal = subMeshNormal;
extraInfo = geometry.getModelNameOfMesh(subMeshIndex);
}
} else {
// this is the non-triangle picking case...
bestDistance = distanceToSubMesh;
@ -401,9 +403,13 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g
face = subMeshFace;
surfaceNormal = subMeshSurfaceNormal;
extraInfo = geometry.getModelNameOfMesh(subMeshIndex);
intersectedSubMesh = true;
}
}
}
subMeshIndex++;
}
_mutex.unlock();
@ -451,18 +457,8 @@ bool Model::convexHullContains(glm::vec3 point) {
int subMeshIndex = 0;
foreach(const AABox& subMeshBox, _calculatedMeshBoxes) {
if (subMeshBox.contains(point)) {
bool insideMesh = true;
// To be inside the sub mesh, we need to be behind every triangles' planes
const QVector<Triangle>& meshTriangles = _calculatedMeshTriangles[subMeshIndex];
foreach (const Triangle& triangle, meshTriangles) {
if (!isPointBehindTrianglesPlane(point, triangle.v0, triangle.v1, triangle.v2)) {
// it's not behind at least one so we bail
insideMesh = false;
break;
}
}
if (insideMesh) {
if (_meshTriangleSets[subMeshIndex].convexHullContains(point)) {
// It's inside this mesh, return true.
_mutex.unlock();
return true;
@ -486,12 +482,20 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid;
if (!_calculatedMeshBoxesValid || calculatedMeshTrianglesNeeded || (!_calculatedMeshPartBoxesValid && pickAgainstTriangles) ) {
if (pickAgainstTriangles) {
qDebug() << "RECALCULATING triangles!";
} else {
qDebug() << "RECALCULATING boxes!";
}
const FBXGeometry& geometry = getFBXGeometry();
int numberOfMeshes = geometry.meshes.size();
_calculatedMeshBoxes.resize(numberOfMeshes);
_calculatedMeshTriangles.clear();
_calculatedMeshTriangles.resize(numberOfMeshes);
_calculatedMeshPartBoxes.clear();
_meshTriangleSets.clear();
_meshTriangleSets.resize(numberOfMeshes);
for (int i = 0; i < numberOfMeshes; i++) {
const FBXMesh& mesh = geometry.meshes.at(i);
Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents, _translation, _rotation);
@ -499,6 +503,8 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
_calculatedMeshBoxes[i] = AABox(scaledMeshExtents);
if (pickAgainstTriangles) {
auto& thisMeshTriangleSet = _meshTriangleSets[i];
QVector<Triangle> thisMeshTriangles;
for (int j = 0; j < mesh.parts.size(); j++) {
const FBXMeshPart& part = mesh.parts.at(j);
@ -550,6 +556,9 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
thisMeshTriangles.push_back(tri1);
thisMeshTriangles.push_back(tri2);
thisMeshTriangleSet.insertTriangle(tri1);
thisMeshTriangleSet.insertTriangle(tri2);
}
}
@ -582,11 +591,13 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) {
Triangle tri = { v0, v1, v2 };
thisMeshTriangles.push_back(tri);
thisMeshTriangleSet.insertTriangle(tri);
}
}
_calculatedMeshPartBoxes[QPair<int,int>(i, j)] = thisPartBounds;
}
_calculatedMeshTriangles[i] = thisMeshTriangles;
_calculatedMeshPartBoxesValid = true;
}
}

View file

@ -28,6 +28,7 @@
#include <render/Scene.h>
#include <Transform.h>
#include <SpatiallyNestable.h>
#include <TriangleSet.h>
#include "GeometryCache.h"
#include "TextureCache.h"
@ -362,8 +363,8 @@ protected:
bool _calculatedMeshPartBoxesValid;
QVector<AABox> _calculatedMeshBoxes; // world coordinate AABoxes for all sub mesh boxes
bool _calculatedMeshBoxesValid;
QVector< TriangleSet > _meshTriangleSets; // world coordinate triangles for all sub meshes
QVector< QVector<Triangle> > _calculatedMeshTriangles; // world coordinate triangles for all sub meshes
bool _calculatedMeshTrianglesValid;
QMutex _mutex;

View file

@ -109,6 +109,8 @@ public:
bool isInvalid() const { return _corner == INFINITY_VECTOR; }
void clear() { _corner = INFINITY_VECTOR; _scale = glm::vec3(0.0f); }
private:
glm::vec3 getClosestPointOnFace(const glm::vec3& point, BoxFace face) const;
glm::vec3 getClosestPointOnFace(const glm::vec4& origin, const glm::vec4& direction, BoxFace face) const;

View file

@ -0,0 +1,69 @@
//
// TriangleSet.cpp
// libraries/entities/src
//
// Created by Brad Hefta-Gaub on 3/2/2017.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "GLMHelpers.h"
#include "TriangleSet.h"
void TriangleSet::insertTriangle(const Triangle& t) {
_triangles.push_back(t);
_bounds += t.v0;
_bounds += t.v1;
_bounds += t.v2;
}
void TriangleSet::clear() {
_triangles.clear();
_bounds.clear();
}
// Determine of the given ray (origin/direction) in model space intersects with any triangles
// in the set. If an intersection occurs, the distance and surface normal will be provided.
bool TriangleSet::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, glm::vec3& surfaceNormal) const {
float bestDistance = std::numeric_limits<float>::max();
float thisTriangleDistance;
bool intersectedSomething = false;
for (const auto& triangle : _triangles) {
if (findRayTriangleIntersection(origin, direction, triangle, thisTriangleDistance)) {
if (thisTriangleDistance < bestDistance) {
bestDistance = thisTriangleDistance;
intersectedSomething = true;
surfaceNormal = triangle.getNormal();
distance = bestDistance;
//face = subMeshFace;
//extraInfo = geometry.getModelNameOfMesh(subMeshIndex);
}
}
}
return intersectedSomething;
}
bool TriangleSet::convexHullContains(const glm::vec3& point) const {
if (!_bounds.contains(point)) {
return false;
}
bool insideMesh = true; // optimistic
for (const auto& triangle : _triangles) {
if (!isPointBehindTrianglesPlane(point, triangle.v0, triangle.v1, triangle.v2)) {
// it's not behind at least one so we bail
insideMesh = false;
break;
}
}
return insideMesh;
}

View file

@ -0,0 +1,33 @@
//
// TriangleSet.h
// libraries/entities/src
//
// Created by Brad Hefta-Gaub on 3/2/2017.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QVector>
#include "AABox.h"
#include "GeometryUtil.h"
class TriangleSet {
public:
void insertTriangle(const Triangle& t);
void clear();
// Determine of the given ray (origin/direction) in model space intersects with any triangles
// in the set. If an intersection occurs, the distance and surface normal will be provided.
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
float& distance, glm::vec3& surfaceNormal) const;
bool convexHullContains(const glm::vec3& point) const; // this point is "inside" all triangles
const AABox& getBounds() const;
private:
QVector<Triangle> _triangles;
AABox _bounds;
};