mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 10:17:40 +02:00
Merge pull request #4561 from sethalves/island
scaling hints to hash, larger collision shapes
This commit is contained in:
commit
e27f800c75
5 changed files with 111 additions and 35 deletions
|
@ -21,9 +21,12 @@
|
||||||
#include "Shape.h"
|
#include "Shape.h"
|
||||||
|
|
||||||
|
|
||||||
|
QHash<QString, float> COMMENT_SCALE_HINTS;
|
||||||
|
|
||||||
|
|
||||||
class OBJTokenizer {
|
class OBJTokenizer {
|
||||||
public:
|
public:
|
||||||
OBJTokenizer(QIODevice* device) : _device(device), _pushedBackToken(-1) { }
|
OBJTokenizer(QIODevice* device);
|
||||||
enum SpecialToken {
|
enum SpecialToken {
|
||||||
NO_TOKEN = -1,
|
NO_TOKEN = -1,
|
||||||
NO_PUSHBACKED_TOKEN = -1,
|
NO_PUSHBACKED_TOKEN = -1,
|
||||||
|
@ -46,6 +49,15 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
OBJTokenizer::OBJTokenizer(QIODevice* device) : _device(device), _pushedBackToken(-1) {
|
||||||
|
// This is a list of comments that exports use to hint at scaling
|
||||||
|
if (COMMENT_SCALE_HINTS.isEmpty()) {
|
||||||
|
COMMENT_SCALE_HINTS["This file uses centimeters as units"] = 1.0f / 100.0f;
|
||||||
|
COMMENT_SCALE_HINTS["This file uses millimeters as units"] = 1.0f / 1000.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int OBJTokenizer::nextToken() {
|
int OBJTokenizer::nextToken() {
|
||||||
if (_pushedBackToken != NO_PUSHBACKED_TOKEN) {
|
if (_pushedBackToken != NO_PUSHBACKED_TOKEN) {
|
||||||
int token = _pushedBackToken;
|
int token = _pushedBackToken;
|
||||||
|
@ -60,7 +72,7 @@ int OBJTokenizer::nextToken() {
|
||||||
}
|
}
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
case '#': {
|
case '#': {
|
||||||
_comment = _device->readLine(); // skip the comment
|
_comment = _device->readLine(); // stash comment for a future call to getComment
|
||||||
qDebug() << "COMMENT:" << _comment;
|
qDebug() << "COMMENT:" << _comment;
|
||||||
return COMMENT_TOKEN;
|
return COMMENT_TOKEN;
|
||||||
}
|
}
|
||||||
|
@ -136,11 +148,15 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
|
||||||
while (true) {
|
while (true) {
|
||||||
int tokenType = tokenizer.nextToken();
|
int tokenType = tokenizer.nextToken();
|
||||||
if (tokenType == OBJTokenizer::COMMENT_TOKEN) {
|
if (tokenType == OBJTokenizer::COMMENT_TOKEN) {
|
||||||
if (tokenizer.getComment().contains("This file uses centimeters as units")) {
|
// loop through the list of known comments which suggest a scaling factor.
|
||||||
scaleGuess = 1.0f / 100.0f;
|
// if we find one, save the scaling hint into scaleGuess
|
||||||
|
QString comment = tokenizer.getComment();
|
||||||
|
QHashIterator<QString, float> i(COMMENT_SCALE_HINTS);
|
||||||
|
while (i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
if (comment.contains(i.key())) {
|
||||||
|
scaleGuess = i.value();
|
||||||
}
|
}
|
||||||
if (tokenizer.getComment().contains("This file uses millimeters as units")) {
|
|
||||||
scaleGuess = 1.0f / 1000.0f;
|
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) {
|
||||||
// Very small or large objects are not supported.
|
// Very small or large objects are not supported.
|
||||||
float diagonal = 4.0f * glm::length2(info.getHalfExtents());
|
float diagonal = 4.0f * glm::length2(info.getHalfExtents());
|
||||||
const float MIN_SHAPE_DIAGONAL_SQUARED = 3.0e-4f; // 1 cm cube
|
const float MIN_SHAPE_DIAGONAL_SQUARED = 3.0e-4f; // 1 cm cube
|
||||||
const float MAX_SHAPE_DIAGONAL_SQUARED = 3.0e4f; // 100 m cube
|
const float MAX_SHAPE_DIAGONAL_SQUARED = 3.0e6f; // 1000 m cube
|
||||||
if (diagonal < MIN_SHAPE_DIAGONAL_SQUARED || diagonal > MAX_SHAPE_DIAGONAL_SQUARED) {
|
if (diagonal < MIN_SHAPE_DIAGONAL_SQUARED || diagonal > MAX_SHAPE_DIAGONAL_SQUARED) {
|
||||||
// qDebug() << "ShapeManager::getShape -- not making shape due to size" << diagonal;
|
// qDebug() << "ShapeManager::getShape -- not making shape due to size" << diagonal;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -38,6 +38,15 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, vhacd::LoadFBXResults *re
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "-------------------\n";
|
||||||
|
foreach (const FBXMesh& mesh, geometry.meshes) {
|
||||||
|
foreach (const FBXMeshPart &meshPart, mesh.parts) {
|
||||||
|
std::cout << meshPart.triangleIndices.size() << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
|
|
||||||
//results->meshCount = geometry.meshes.count();
|
//results->meshCount = geometry.meshes.count();
|
||||||
// qDebug() << "read in" << geometry.meshes.count() << "meshes";
|
// qDebug() << "read in" << geometry.meshes.count() << "meshes";
|
||||||
|
|
||||||
|
@ -52,14 +61,29 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, vhacd::LoadFBXResults *re
|
||||||
vertices.append(glm::vec3(mesh.modelTransform * glm::vec4(vertex, 1.0f)));
|
vertices.append(glm::vec3(mesh.modelTransform * glm::vec4(vertex, 1.0f)));
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the triangle indices for each mesh
|
// get the triangle indices for each mesh
|
||||||
QVector<int> triangles;
|
QVector<int> triangles;
|
||||||
foreach(FBXMeshPart part, mesh.parts){
|
foreach(FBXMeshPart meshPart, mesh.parts){
|
||||||
QVector<int> indices = part.triangleIndices;
|
QVector<int> indices = meshPart.triangleIndices;
|
||||||
triangles += indices;
|
triangles += indices;
|
||||||
|
|
||||||
|
unsigned int quadCount = meshPart.quadIndices.size() / 4;
|
||||||
|
for (unsigned int i = 0; i < quadCount; i++) {
|
||||||
|
unsigned int p0Index = meshPart.quadIndices[i * 4];
|
||||||
|
unsigned int p1Index = meshPart.quadIndices[i * 4 + 1];
|
||||||
|
unsigned int p2Index = meshPart.quadIndices[i * 4 + 2];
|
||||||
|
unsigned int p3Index = meshPart.quadIndices[i * 4 + 3];
|
||||||
|
// split each quad into two triangles
|
||||||
|
triangles.append(p0Index);
|
||||||
|
triangles.append(p1Index);
|
||||||
|
triangles.append(p2Index);
|
||||||
|
triangles.append(p0Index);
|
||||||
|
triangles.append(p2Index);
|
||||||
|
triangles.append(p3Index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//only read meshes with triangles
|
// only read meshes with triangles
|
||||||
if (triangles.count() <= 0){
|
if (triangles.count() <= 0){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -131,15 +155,16 @@ void vhacd::VHACDUtil::fattenMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFB
|
||||||
auto d1 = p2 - p0;
|
auto d1 = p2 - p0;
|
||||||
|
|
||||||
auto cp = glm::cross(d0, d1);
|
auto cp = glm::cross(d0, d1);
|
||||||
cp = 5.0f * glm::normalize(cp);
|
cp = -2.0f * glm::normalize(cp);
|
||||||
|
|
||||||
auto p3 = p0 + cp;
|
auto p3 = p0 + cp;
|
||||||
auto p4 = p1 + cp;
|
|
||||||
auto p5 = p2 + cp;
|
|
||||||
|
|
||||||
auto n = results->perMeshVertices.size();
|
auto n = results->perMeshVertices.size();
|
||||||
results->perMeshVertices[i] << p3 << p4 << p5;
|
results->perMeshVertices[i] << p3;
|
||||||
results->perMeshTriangleIndices[i] << n << n+1 << n+2;
|
|
||||||
|
results->perMeshTriangleIndices[i] << triangles[j] << n << triangles[j + 1];
|
||||||
|
results->perMeshTriangleIndices[i] << triangles[j + 1] << n << triangles[j + 2];
|
||||||
|
results->perMeshTriangleIndices[i] << triangles[j + 2] << n << triangles[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
results->meshCount++;
|
results->meshCount++;
|
||||||
|
@ -148,21 +173,26 @@ void vhacd::VHACDUtil::fattenMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFB
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD::Parameters params,
|
bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *inMeshes, VHACD::IVHACD::Parameters params,
|
||||||
vhacd::ComputeResults *results,
|
vhacd::ComputeResults *results,
|
||||||
int startMeshIndex, int endMeshIndex, float minimumMeshSize) const {
|
int startMeshIndex, int endMeshIndex, float minimumMeshSize,
|
||||||
|
bool fattenFaces) const {
|
||||||
|
|
||||||
// vhacd::LoadFBXResults *meshes = new vhacd::LoadFBXResults;
|
vhacd::LoadFBXResults *meshes = new vhacd::LoadFBXResults;
|
||||||
// combineMeshes(inMeshes, meshes);
|
// combineMeshes(inMeshes, meshes);
|
||||||
|
|
||||||
// vhacd::LoadFBXResults *meshes = new vhacd::LoadFBXResults;
|
// vhacd::LoadFBXResults *meshes = new vhacd::LoadFBXResults;
|
||||||
// fattenMeshes(inMeshes, meshes);
|
|
||||||
|
if (fattenFaces) {
|
||||||
|
fattenMeshes(inMeshes, meshes);
|
||||||
|
} else {
|
||||||
|
meshes = inMeshes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VHACD::IVHACD * interfaceVHACD = VHACD::CreateVHACD();
|
VHACD::IVHACD * interfaceVHACD = VHACD::CreateVHACD();
|
||||||
int meshCount = meshes->meshCount;
|
int meshCount = meshes->meshCount;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
std::cout << "Performing V-HACD computation on " << meshCount << " meshes ..... " << std::endl;
|
|
||||||
|
|
||||||
if (startMeshIndex < 0) {
|
if (startMeshIndex < 0) {
|
||||||
startMeshIndex = 0;
|
startMeshIndex = 0;
|
||||||
|
@ -171,6 +201,14 @@ bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD
|
||||||
endMeshIndex = meshCount;
|
endMeshIndex = meshCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < meshCount; i++) {
|
||||||
|
std::cout << meshes->perMeshTriangleIndices.at(i).size() << " ";
|
||||||
|
}
|
||||||
|
std::cout << "\n";
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "Performing V-HACD computation on " << endMeshIndex - startMeshIndex << " meshes ..... " << std::endl;
|
||||||
|
|
||||||
for (int i = startMeshIndex; i < endMeshIndex; i++){
|
for (int i = startMeshIndex; i < endMeshIndex; i++){
|
||||||
qDebug() << "--------------------";
|
qDebug() << "--------------------";
|
||||||
std::vector<glm::vec3> vertices = meshes->perMeshVertices.at(i).toStdVector();
|
std::vector<glm::vec3> vertices = meshes->perMeshVertices.at(i).toStdVector();
|
||||||
|
@ -211,7 +249,6 @@ bool vhacd::VHACDUtil::computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD
|
||||||
}
|
}
|
||||||
hull.m_points = m_points_copy;
|
hull.m_points = m_points_copy;
|
||||||
|
|
||||||
|
|
||||||
int *m_triangles_copy = new int[hull.m_nTriangles * 3];
|
int *m_triangles_copy = new int[hull.m_nTriangles * 3];
|
||||||
// std::copy(std::begin(hull.m_triangles), std::end(hull.m_triangles), std::begin(m_triangles_copy));
|
// std::copy(std::begin(hull.m_triangles), std::end(hull.m_triangles), std::begin(m_triangles_copy));
|
||||||
for (unsigned int i=0; i<hull.m_nTriangles * 3; i++) {
|
for (unsigned int i=0; i<hull.m_nTriangles * 3; i++) {
|
||||||
|
|
|
@ -43,7 +43,8 @@ namespace vhacd {
|
||||||
void combineMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const;
|
void combineMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const;
|
||||||
void fattenMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const;
|
void fattenMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const;
|
||||||
bool computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD::Parameters params,
|
bool computeVHACD(vhacd::LoadFBXResults *meshes, VHACD::IVHACD::Parameters params,
|
||||||
vhacd::ComputeResults *results, int startMeshIndex, int endMeshIndex, float minimumMeshSize) const;
|
vhacd::ComputeResults *results, int startMeshIndex, int endMeshIndex, float minimumMeshSize,
|
||||||
|
bool fattenFaces) const;
|
||||||
~VHACDUtil();
|
~VHACDUtil();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -92,6 +92,9 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
|
||||||
const QCommandLineOption outputOneMeshOption("1", "output hulls as single mesh");
|
const QCommandLineOption outputOneMeshOption("1", "output hulls as single mesh");
|
||||||
parser.addOption(outputOneMeshOption);
|
parser.addOption(outputOneMeshOption);
|
||||||
|
|
||||||
|
const QCommandLineOption fattenFacesOption("f", "fatten faces");
|
||||||
|
parser.addOption(fattenFacesOption);
|
||||||
|
|
||||||
const QCommandLineOption inputFilenameOption("i", "input file", "filename.fbx");
|
const QCommandLineOption inputFilenameOption("i", "input file", "filename.fbx");
|
||||||
parser.addOption(inputFilenameOption);
|
parser.addOption(inputFilenameOption);
|
||||||
|
|
||||||
|
@ -107,6 +110,15 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
|
||||||
const QCommandLineOption minimumMeshSizeOption("m", "minimum mesh size to consider", "0");
|
const QCommandLineOption minimumMeshSizeOption("m", "minimum mesh size to consider", "0");
|
||||||
parser.addOption(minimumMeshSizeOption);
|
parser.addOption(minimumMeshSizeOption);
|
||||||
|
|
||||||
|
const QCommandLineOption vHacdResolutionOption("resolution", "v-hacd resolution", "100000");
|
||||||
|
parser.addOption(vHacdResolutionOption);
|
||||||
|
|
||||||
|
const QCommandLineOption vHacdDepthOption("depth", "v-hacd depth", "20");
|
||||||
|
parser.addOption(vHacdDepthOption);
|
||||||
|
|
||||||
|
const QCommandLineOption vHacdDeltaOption("delta", "v-hacd delta", "0.05");
|
||||||
|
parser.addOption(vHacdDeltaOption);
|
||||||
|
|
||||||
|
|
||||||
if (!parser.parse(QCoreApplication::arguments())) {
|
if (!parser.parse(QCoreApplication::arguments())) {
|
||||||
qCritical() << parser.errorText() << endl;
|
qCritical() << parser.errorText() << endl;
|
||||||
|
@ -119,17 +131,15 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool fattenFaces = parser.isSet(fattenFacesOption);
|
||||||
bool outputOneMesh = parser.isSet(outputOneMeshOption);
|
bool outputOneMesh = parser.isSet(outputOneMeshOption);
|
||||||
|
|
||||||
QString inputFilename;
|
QString inputFilename;
|
||||||
// check for an assignment pool passed on the command line or in the config
|
|
||||||
if (parser.isSet(inputFilenameOption)) {
|
if (parser.isSet(inputFilenameOption)) {
|
||||||
inputFilename = parser.value(inputFilenameOption);
|
inputFilename = parser.value(inputFilenameOption);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString outputFilename;
|
QString outputFilename;
|
||||||
// check for an assignment pool passed on the command line or in the config
|
|
||||||
if (parser.isSet(outputFilenameOption)) {
|
if (parser.isSet(outputFilenameOption)) {
|
||||||
outputFilename = parser.value(outputFilenameOption);
|
outputFilename = parser.value(outputFilenameOption);
|
||||||
}
|
}
|
||||||
|
@ -148,30 +158,43 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
|
||||||
}
|
}
|
||||||
|
|
||||||
int startMeshIndex = -1;
|
int startMeshIndex = -1;
|
||||||
// check for an assignment pool passed on the command line or in the config
|
|
||||||
if (parser.isSet(startMeshIndexOption)) {
|
if (parser.isSet(startMeshIndexOption)) {
|
||||||
startMeshIndex = parser.value(startMeshIndexOption).toInt();
|
startMeshIndex = parser.value(startMeshIndexOption).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
int endMeshIndex = -1;
|
int endMeshIndex = -1;
|
||||||
// check for an assignment pool passed on the command line or in the config
|
|
||||||
if (parser.isSet(endMeshIndexOption)) {
|
if (parser.isSet(endMeshIndexOption)) {
|
||||||
endMeshIndex = parser.value(endMeshIndexOption).toInt();
|
endMeshIndex = parser.value(endMeshIndexOption).toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
float minimumMeshSize = 0.0f;
|
float minimumMeshSize = 0.0f;
|
||||||
// check for an assignment pool passed on the command line or in the config
|
|
||||||
if (parser.isSet(minimumMeshSizeOption)) {
|
if (parser.isSet(minimumMeshSizeOption)) {
|
||||||
minimumMeshSize = parser.value(minimumMeshSizeOption).toFloat();
|
minimumMeshSize = parser.value(minimumMeshSizeOption).toFloat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vHacdResolution = 100000;
|
||||||
|
if (parser.isSet(vHacdResolutionOption)) {
|
||||||
|
vHacdResolution = parser.value(vHacdResolutionOption).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
int vHacdDepth = 20;
|
||||||
|
if (parser.isSet(vHacdDepthOption)) {
|
||||||
|
vHacdDepth = parser.value(vHacdDepthOption).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
float vHacdDelta = 0.05;
|
||||||
|
if (parser.isSet(vHacdDeltaOption)) {
|
||||||
|
vHacdDelta = parser.value(vHacdDeltaOption).toFloat();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//set parameters for V-HACD
|
//set parameters for V-HACD
|
||||||
params.m_callback = &pCallBack; //progress callback
|
params.m_callback = &pCallBack; //progress callback
|
||||||
params.m_resolution = 100000; // 100000
|
params.m_resolution = vHacdResolution; // 100000
|
||||||
params.m_depth = 20; // 20
|
params.m_depth = vHacdDepth; // 20
|
||||||
params.m_concavity = 0.001; // 0.001
|
params.m_concavity = 0.001; // 0.001
|
||||||
params.m_delta = 0.05; // 0.05
|
params.m_delta = vHacdDelta; // 0.05
|
||||||
params.m_planeDownsampling = 4; // 4
|
params.m_planeDownsampling = 4; // 4
|
||||||
params.m_convexhullDownsampling = 4; // 4
|
params.m_convexhullDownsampling = 4; // 4
|
||||||
params.m_alpha = 0.05; // 0.05 // controls the bias toward clipping along symmetry planes
|
params.m_alpha = 0.05; // 0.05 // controls the bias toward clipping along symmetry planes
|
||||||
|
@ -198,8 +221,7 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
|
||||||
//perform vhacd computation
|
//perform vhacd computation
|
||||||
begin = std::chrono::high_resolution_clock::now();
|
begin = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
|
if (!vUtil.computeVHACD(&fbx, params, &results, startMeshIndex, endMeshIndex, minimumMeshSize, fattenFaces)) {
|
||||||
if (!vUtil.computeVHACD(&fbx, params, &results, startMeshIndex, endMeshIndex, minimumMeshSize)) {
|
|
||||||
cout << "Compute Failed...";
|
cout << "Compute Failed...";
|
||||||
}
|
}
|
||||||
end = std::chrono::high_resolution_clock::now();
|
end = std::chrono::high_resolution_clock::now();
|
||||||
|
|
Loading…
Reference in a new issue