Merge branch 'master' of https://github.com/highfidelity/hifi into fix_quick_turn

This commit is contained in:
Atlante45 2015-04-10 17:51:32 +02:00
commit 910e13edeb
14 changed files with 311 additions and 100 deletions

View file

@ -41,6 +41,10 @@ if (WIN32)
message (WINDOW_SDK_PATH= ${WINDOW_SDK_PATH})
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${WINDOW_SDK_PATH})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
# /LARGEADDRESSAWARE enables 32-bit apps to use more than 2GB of memory.
# Caveats: http://stackoverflow.com/questions/2288728/drawbacks-of-using-largeaddressaware-for-32-bit-windows-executables
# TODO: Remove when building 64-bit.
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE")
elseif (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)
#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-long-long -pedantic")
#SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-unknown-pragmas")

View file

@ -0,0 +1,100 @@
(function() {
this.preload = function(entityId) {
var soundURLs = ["https://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/lamp_switch_1.wav",
"https://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/lamp_switch_2.wav",
"https://hifi-public.s3.amazonaws.com/sounds/Switches%20and%20sliders/lamp_switch_3.wav"];
this.entityId = entityId;
this.properties = Entities.getEntityProperties(this.entityId);
this.previousPosition = this.properties.position;
this.previousRotation = this.properties.rotation;
this.getUserData()
if (!this.userData) {
this.userData = {};
this.userData.lightOn = false;
this.userData.soundIndex = Math.floor(Math.random() * soundURLs.length);
this.updateUserData();
}
this.sound = SoundCache.getSound(soundURLs[this.userData.soundIndex]);
}
this.getUserData = function() {
if (this.properties.userData) {
this.userData = JSON.parse(this.properties.userData);
}
return false;
}
this.updateUserData = function() {
Entities.editEntity(this.entityId, {
userData: JSON.stringify(this.userData)
});
}
this.clickReleaseOnEntity = function(entityId, mouseEvent) {
if (!mouseEvent.isLeftButton) {
return;
}
//first find closest light
this.entityId = entityId
this.playSound();
this.properties = Entities.getEntityProperties(this.entityId)
this.light = this.findClosestLight();
if (this.light) {
this.lightProperties = Entities.getEntityProperties(this.light);
this.getUserData();
Entities.editEntity(this.light, {
visible: !this.userData.lightOn
});
this.userData.lightOn = !this.userData.lightOn;
this.updateUserData();
this.tryMoveLight();
}
}
this.playSound = function() {
if (this.sound && this.sound.downloaded) {
Audio.playSound(this.sound, {
position: this.properties.position,
volume: 0.3
});
} else {
print("Warning: Couldn't play sound.");
}
}
this.tryMoveLight = function() {
if (this.light) {
//compute offset position
var offsetPosition = Quat.multiply(Quat.inverse(this.previousRotation), Vec3.subtract(this.lightProperties.position, this.previousPosition));
var newPosition = Vec3.sum(this.properties.position, Vec3.multiplyQbyV(this.properties.rotation, offsetPosition));
if (!Vec3.equal(newPosition, this.lightProperties.position)) {
Entities.editEntity(this.light, {position: newPosition});
}
this.previousPosition = this.properties.position;
this.previousRotation = this.properties.rotation;
}
}
this.findClosestLight = function() {
var entities = Entities.findEntities(this.properties.position, 10);
var lightEntities = [];
var closestLight = null;
var nearestDistance = 20
for (var i = 0; i < entities.length; i++) {
var props = Entities.getEntityProperties(entities[i]);
if (props.type === "Light") {
var distance = Vec3.distance(props.position, this.properties.position)
if (distance < nearestDistance) {
closestLight = entities[i];
nearestDistance = distance
}
}
}
return closestLight;
}
});

View file

@ -211,7 +211,14 @@
disableChildren(document.getElementById("properties-list"), 'input');
} else {
var activeElement = document.activeElement;
var selected = activeElement.selectionStart == 0 && activeElement.selectionEnd == activeElement.value.length;
try {
var selected = (activeElement
&& activeElement.selectionStart == 0
&& activeElement.selectionEnd == activeElement.value.length);
} catch (e) {
var selected = false;
}
var properties = data.selections[0].properties;

View file

@ -201,11 +201,11 @@ var usersWindow = (function () {
WINDOW_BASE_MARGIN = 6, // A little less is needed in order look correct
WINDOW_FONT = { size: 12 },
WINDOW_FOREGROUND_COLOR = { red: 240, green: 240, blue: 240 },
WINDOW_FOREGROUND_ALPHA = 0.9,
WINDOW_FOREGROUND_ALPHA = 0.95,
WINDOW_HEADING_COLOR = { red: 180, green: 180, blue: 180 },
WINDOW_HEADING_ALPHA = 0.9,
WINDOW_HEADING_ALPHA = 0.95,
WINDOW_BACKGROUND_COLOR = { red: 80, green: 80, blue: 80 },
WINDOW_BACKGROUND_ALPHA = 0.7,
WINDOW_BACKGROUND_ALPHA = 0.8,
windowPane,
windowHeading,
MIN_MAX_BUTTON_SVG = HIFI_PUBLIC_BUCKET + "images/tools/min-max-toggle.svg",
@ -223,7 +223,7 @@ var usersWindow = (function () {
SCROLLBAR_BAR_MIN_HEIGHT = 5,
SCROLLBAR_BAR_COLOR = { red: 170, green: 170, blue: 170 },
SCROLLBAR_BAR_ALPHA = 0.8,
SCROLLBAR_BAR_SELECTED_ALPHA = 0.9,
SCROLLBAR_BAR_SELECTED_ALPHA = 0.95,
scrollbarBar,
scrollbarBackgroundHeight,
scrollbarBarHeight,
@ -233,12 +233,12 @@ var usersWindow = (function () {
FRIENDS_BUTTON_SVG_HEIGHT = 27,
FRIENDS_BUTTON_WIDTH = FRIENDS_BUTTON_SVG_WIDTH,
FRIENDS_BUTTON_HEIGHT = FRIENDS_BUTTON_SVG_HEIGHT,
FRIENDS_BUTTON_COLOR = { red: 255, green: 255, blue: 255 },
FRIENDS_BUTTON_ALPHA = 0.9,
FRIENDS_BUTTON_COLOR = { red: 225, green: 225, blue: 225 },
FRIENDS_BUTTON_ALPHA = 0.95,
friendsButton,
OPTION_BACKGROUND_COLOR = { red: 60, green: 60, blue: 60 },
OPTION_BACKGROUND_ALPHA = 0.8,
OPTION_BACKGROUND_ALPHA = 0.1,
DISPLAY_SPACER = 12, // Space before display control
DISPLAY_PROMPT = "Show me:",
@ -247,8 +247,8 @@ var usersWindow = (function () {
DISPLAY_FRIENDS = "friends",
DISPLAY_VALUES = [DISPLAY_EVERYONE, DISPLAY_FRIENDS],
DISPLAY_DISPLAY_VALUES = DISPLAY_VALUES,
DISPLAY_OPTIONS_BACKGROUND_COLOR = { red: 40, green: 40, blue: 40 },
DISPLAY_OPTIONS_BACKGROUND_ALPHA = 0.95,
DISPLAY_OPTIONS_BACKGROUND_COLOR = { red: 120, green: 120, blue: 120 },
DISPLAY_OPTIONS_BACKGROUND_ALPHA = 0.9,
displayControl,
VISIBILITY_SPACER = 6, // Space before visibility control

View file

@ -212,6 +212,7 @@ void Renderer::glUpload(GLsizei numStars) {
void Renderer::glBatch(GLfloat const* matrix, GLsizei n_ranges, float alpha) {
glDisable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glEnable(GL_BLEND);
// setup modelview matrix
glPushMatrix();

View file

@ -201,7 +201,7 @@
#define COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(P, S)\
QScriptValue P = object.property(#P); \
if (P.isValid()) { \
QString newValue = P.toVariant().toString();\
QString newValue = P.toVariant().toString().trimmed();\
if (_defaultSettings || newValue != _##P) { \
S(newValue); \
} \

View file

@ -116,6 +116,24 @@ bool OBJTokenizer::isNextTokenFloat() {
return ok;
}
void setMeshPartDefaults(FBXMeshPart &meshPart, QString materialID) {
meshPart.diffuseColor = glm::vec3(1, 1, 1);
meshPart.specularColor = glm::vec3(1, 1, 1);
meshPart.emissiveColor = glm::vec3(0, 0, 0);
meshPart.emissiveParams = glm::vec2(0, 1);
meshPart.shininess = 40;
meshPart.opacity = 1;
meshPart.materialID = materialID;
meshPart.opacity = 1.0;
meshPart._material = model::MaterialPointer(new model::Material());
meshPart._material->setDiffuse(glm::vec3(1.0, 1.0, 1.0));
meshPart._material->setOpacity(1.0);
meshPart._material->setSpecular(glm::vec3(1.0, 1.0, 1.0));
meshPart._material->setShininess(96.0);
meshPart._material->setEmissive(glm::vec3(0.0, 0.0, 0.0));
}
bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
FBXGeometry &geometry, QVector<glm::vec3>& faceNormals, QVector<int>& faceNormalIndexes,
float& scaleGuess) {
@ -125,21 +143,7 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping,
bool sawG = false;
bool result = true;
meshPart.diffuseColor = glm::vec3(1, 1, 1);
meshPart.specularColor = glm::vec3(1, 1, 1);
meshPart.emissiveColor = glm::vec3(0, 0, 0);
meshPart.emissiveParams = glm::vec2(0, 1);
meshPart.shininess = 40;
meshPart.opacity = 1;
meshPart.materialID = QString("dontknow") + QString::number(mesh.parts.count());
meshPart.opacity = 1.0;
meshPart._material = model::MaterialPointer(new model::Material());
meshPart._material->setDiffuse(glm::vec3(1.0, 1.0, 1.0));
meshPart._material->setOpacity(1.0);
meshPart._material->setSpecular(glm::vec3(1.0, 1.0, 1.0));
meshPart._material->setShininess(96.0);
meshPart._material->setEmissive(glm::vec3(0.0, 0.0, 0.0));
setMeshPartDefaults(meshPart, QString("dontknow") + QString::number(mesh.parts.count()));
while (true) {
int tokenType = tokenizer.nextToken();

View file

@ -5,3 +5,4 @@
FBXGeometry readOBJ(const QByteArray& model, const QVariantHash& mapping);
FBXGeometry readOBJ(QIODevice* device, const QVariantHash& mapping);
void fbxDebugDump(const FBXGeometry& fbxgeo);
void setMeshPartDefaults(FBXMeshPart &meshPart, QString materialID);

View file

@ -27,7 +27,7 @@ Resource::Size Resource::Sysmem::allocateMemory(Byte** dataAllocated, Size size)
if (size > 0) {
// Try allocating as much as the required size + one block of memory
newSize = size;
(*dataAllocated) = new Byte[newSize];
(*dataAllocated) = new (std::nothrow) Byte[newSize];
// Failed?
if (!(*dataAllocated)) {
qWarning() << "Buffer::Sysmem::allocate() : Can't allocate a system memory buffer of " << newSize << "bytes. Fails to create the buffer Sysmem.";

View file

@ -1024,7 +1024,7 @@ int Octree::encodeTreeBitstream(OctreeElement* element,
roomForOctalCode = packetData->startSubTree(newCode);
if (newCode) {
delete newCode;
delete[] newCode;
codeLength = numberOfThreeBitSectionsInCode(newCode);
} else {
codeLength = 1;
@ -2064,7 +2064,7 @@ bool Octree::readJSONFromStream(unsigned long streamLength, QDataStream& inputSt
QVariant asVariant = asDocument.toVariant();
QVariantMap asMap = asVariant.toMap();
readFromMap(asMap);
delete rawData;
delete[] rawData;
return true;
}

View file

@ -36,7 +36,7 @@ btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) {
float diagonal = 4.0f * glm::length2(info.getHalfExtents());
const float MIN_SHAPE_DIAGONAL_SQUARED = 3.0e-4f; // 1 cm 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*/ ) {
// qCDebug(physics) << "ShapeManager::getShape -- not making shape due to size" << diagonal;
return NULL;
}

View file

@ -50,42 +50,92 @@ bool vhacd::VHACDUtil::loadFBX(const QString filename, FBXGeometry& result) {
}
unsigned int getTrianglesInMeshPart(const FBXMeshPart &meshPart, std::vector<int>& triangles) {
// append all the triangles (and converted quads) from this mesh-part to triangles
std::vector<int> meshPartTriangles = meshPart.triangleIndices.toStdVector();
triangles.insert(triangles.end(), meshPartTriangles.begin(), meshPartTriangles.end());
// void vhacd::VHACDUtil::fattenMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const {
// convert quads to triangles
unsigned int triangleCount = meshPart.triangleIndices.size() / 3;
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.push_back(p0Index);
triangles.push_back(p1Index);
triangles.push_back(p2Index);
triangles.push_back(p0Index);
triangles.push_back(p2Index);
triangles.push_back(p3Index);
triangleCount += 2;
}
// for (int i = 0; i < meshes->meshCount; i++) {
// QVector<glm::vec3> vertices = meshes->perMeshVertices.at(i);
// QVector<int> triangles = meshes->perMeshTriangleIndices.at(i);
// const float largestDimension = meshes->perMeshLargestDimension.at(i);
return triangleCount;
}
// results->perMeshVertices.append(vertices);
// results->perMeshTriangleIndices.append(triangles);
// results->perMeshLargestDimension.append(largestDimension);
// for (int j = 0; j < triangles.size(); j += 3) {
// auto p0 = vertices[triangles[j]];
// auto p1 = vertices[triangles[j+1]];
// auto p2 = vertices[triangles[j+2]];
void vhacd::VHACDUtil::fattenMeshes(const FBXMesh& mesh, FBXMesh& result,
unsigned int& meshPartCount,
unsigned int startMeshIndex, unsigned int endMeshIndex) const {
// this is used to make meshes generated from a highfield collidable. each triangle
// is converted into a tetrahedron and made into its own mesh-part.
// auto d0 = p1 - p0;
// auto d1 = p2 - p0;
std::vector<int> triangles;
foreach (const FBXMeshPart &meshPart, mesh.parts) {
if (meshPartCount < startMeshIndex || meshPartCount >= endMeshIndex) {
meshPartCount++;
continue;
}
getTrianglesInMeshPart(meshPart, triangles);
}
// auto cp = glm::cross(d0, d1);
// cp = -2.0f * glm::normalize(cp);
unsigned int triangleCount = triangles.size() / 3;
if (triangleCount == 0) {
return;
}
// auto p3 = p0 + cp;
// auto n = results->perMeshVertices.size();
// results->perMeshVertices[i] << p3;
int indexStartOffset = result.vertices.size();
// 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];
// }
// new mesh gets the transformed points from the original
for (int i = 0; i < mesh.vertices.size(); i++) {
// apply the source mesh's transform to the points
glm::vec4 v = mesh.modelTransform * glm::vec4(mesh.vertices[i], 1.0f);
result.vertices += glm::vec3(v);
}
// results->meshCount++;
// }
// }
// turn each triangle into a tetrahedron
for (unsigned int i = 0; i < triangleCount; i++) {
int index0 = triangles[i * 3] + indexStartOffset;
int index1 = triangles[i * 3 + 1] + indexStartOffset;
int index2 = triangles[i * 3 + 2] + indexStartOffset;
glm::vec3 p0 = result.vertices[index0];
glm::vec3 p1 = result.vertices[index1];
glm::vec3 p2 = result.vertices[index2];
glm::vec3 av = (p0 + p1 + p2) / 3.0f; // center of the triangular face
float dropAmount = 0;
dropAmount = glm::max(glm::length(p1 - p0), dropAmount);
dropAmount = glm::max(glm::length(p2 - p1), dropAmount);
dropAmount = glm::max(glm::length(p0 - p2), dropAmount);
glm::vec3 p3 = av - glm::vec3(0, dropAmount, 0); // a point 1 meter below the average of this triangle's points
int index3 = result.vertices.size();
result.vertices << p3; // add the new point to the result mesh
FBXMeshPart newMeshPart;
setMeshPartDefaults(newMeshPart, "unknown");
newMeshPart.triangleIndices << index0 << index1 << index2;
newMeshPart.triangleIndices << index0 << index3 << index1;
newMeshPart.triangleIndices << index1 << index3 << index2;
newMeshPart.triangleIndices << index2 << index3 << index0;
result.parts.append(newMeshPart);
}
}
@ -127,8 +177,7 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry,
FBXGeometry& result,
int startMeshIndex,
int endMeshIndex,
float minimumMeshSize, float maximumMeshSize,
bool fattenFaces) {
float minimumMeshSize, float maximumMeshSize) {
// count the mesh-parts
int meshCount = 0;
foreach (const FBXMesh& mesh, geometry.meshes) {
@ -168,27 +217,8 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry,
qDebug() << "--------------------";
std::vector<int> triangles = meshPart.triangleIndices.toStdVector();
AABox aaBox = getAABoxForMeshPart(mesh, meshPart);
// convert quads to triangles
unsigned int triangleCount = meshPart.triangleIndices.size() / 3;
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.push_back(p0Index);
triangles.push_back(p1Index);
triangles.push_back(p2Index);
triangles.push_back(p0Index);
triangles.push_back(p2Index);
triangles.push_back(p3Index);
triangleCount += 2;
}
std::vector<int> triangles;
unsigned int triangleCount = getTrianglesInMeshPart(meshPart, triangles);
// only process meshes with triangles
if (triangles.size() <= 0) {
@ -198,6 +228,7 @@ bool vhacd::VHACDUtil::computeVHACD(FBXGeometry& geometry,
}
int nPoints = vertices.size();
AABox aaBox = getAABoxForMeshPart(mesh, meshPart);
const float largestDimension = aaBox.getLargestDimension();
qDebug() << "Mesh " << count << " -- " << nPoints << " points, " << triangleCount << " triangles, "

View file

@ -26,14 +26,16 @@ namespace vhacd {
class VHACDUtil {
public:
bool loadFBX(const QString filename, FBXGeometry& result);
// void combineMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const;
// void fattenMeshes(vhacd::LoadFBXResults *meshes, vhacd::LoadFBXResults *results) const;
void fattenMeshes(const FBXMesh& mesh, FBXMesh& result,
unsigned int& meshPartCount,
unsigned int startMeshIndex, unsigned int endMeshIndex) const;
bool computeVHACD(FBXGeometry& geometry,
VHACD::IVHACD::Parameters params,
FBXGeometry& result,
int startMeshIndex, int endMeshIndex,
float minimumMeshSize, float maximumMeshSize,
bool fattenFaces);
float minimumMeshSize, float maximumMeshSize);
~VHACDUtil();
};

View file

@ -33,7 +33,7 @@ QString formatFloat(double n) {
}
bool writeOBJ(QString outFileName, FBXGeometry& geometry, int whichMeshPart = -1) {
bool writeOBJ(QString outFileName, FBXGeometry& geometry, bool outputCentimeters, int whichMeshPart = -1) {
QFile file(outFileName);
if (!file.open(QIODevice::WriteOnly)) {
qDebug() << "Unable to write to " << outFileName;
@ -41,6 +41,10 @@ bool writeOBJ(QString outFileName, FBXGeometry& geometry, int whichMeshPart = -1
}
QTextStream out(&file);
if (outputCentimeters) {
out << "# This file uses centimeters as units\n\n";
}
unsigned int nth = 0;
// vertex indexes in obj files span the entire file
@ -116,6 +120,9 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
const QCommandLineOption outputFilenameOption("o", "output file", "filename.obj");
parser.addOption(outputFilenameOption);
const QCommandLineOption outputCentimetersOption("c", "output units are centimeters");
parser.addOption(outputCentimetersOption);
const QCommandLineOption startMeshIndexOption("s", "start-mesh index", "0");
parser.addOption(startMeshIndexOption);
@ -137,7 +144,21 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
"according the \"best\" clipping plane (range=1-32)", "20");
parser.addOption(vHacdDepthOption);
const QCommandLineOption vHacdDeltaOption("delta", "Controls the bias toward maximaxing local concavity (range=0.0-1.0)", "0.05");
const QCommandLineOption vHacdAlphaOption("alpha", "Controls the bias toward clipping along symmetry "
"planes (range=0.0-1.0)", "0.05");
parser.addOption(vHacdAlphaOption);
const QCommandLineOption vHacdBetaOption("beta", "Controls the bias toward clipping along revolution "
"axes (range=0.0-1.0)", "0.05");
parser.addOption(vHacdBetaOption);
const QCommandLineOption vHacdGammaOption("gamma", "Controls the maximum allowed concavity during the "
"merge stage (range=0.0-1.0)", "0.00125");
parser.addOption(vHacdGammaOption);
const QCommandLineOption vHacdDeltaOption("delta", "Controls the bias toward maximaxing local "
"concavity (range=0.0-1.0)", "0.05");
parser.addOption(vHacdDeltaOption);
const QCommandLineOption vHacdConcavityOption("concavity", "Maximum allowed concavity (range=0.0-1.0)", "0.0025");
@ -152,10 +173,6 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
"plane selection stage (range=1-16)", "4");
parser.addOption(vHacdConvexhulldownsamplingOption);
// alpha
// beta
// gamma
// delta
// pca
// mode
@ -178,9 +195,11 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
Q_UNREACHABLE();
}
bool fattenFaces = parser.isSet(fattenFacesOption);
bool outputCentimeters = parser.isSet(outputCentimetersOption);
bool fattenFaces = parser.isSet(fattenFacesOption);
bool generateHulls = parser.isSet(generateHullsOption);
bool splitModel = parser.isSet(splitOption);
QString inputFilename;
@ -236,6 +255,21 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
vHacdDepth = parser.value(vHacdDepthOption).toInt();
}
float vHacdAlpha = 0.05;
if (parser.isSet(vHacdAlphaOption)) {
vHacdAlpha = parser.value(vHacdAlphaOption).toFloat();
}
float vHacdBeta = 0.05;
if (parser.isSet(vHacdBetaOption)) {
vHacdBeta = parser.value(vHacdBetaOption).toFloat();
}
float vHacdGamma = 0.00125;
if (parser.isSet(vHacdGammaOption)) {
vHacdGamma = parser.value(vHacdGammaOption).toFloat();
}
float vHacdDelta = 0.05;
if (parser.isSet(vHacdDeltaOption)) {
vHacdDelta = parser.value(vHacdDeltaOption).toFloat();
@ -261,8 +295,8 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
vHacdMaxVerticesPerCH = parser.value(vHacdMaxVerticesPerCHOption).toInt();
}
if (!parser.isSet(splitOption) && !generateHulls) {
cerr << "\nNothing to do! Use -g or --split\n\n";
if (!splitModel && !generateHulls && !fattenFaces) {
cerr << "\nNothing to do! Use -g or -f or --split\n\n";
parser.showHelp();
Q_UNREACHABLE();
}
@ -279,14 +313,14 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
auto loadDuration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin).count();
if (parser.isSet(splitOption)) {
if (splitModel) {
QVector<QString> infileExtensions = {"fbx", "obj"};
QString baseFileName = fileNameWithoutExtension(inputFilename, infileExtensions);
int count = 0;
foreach (const FBXMesh& mesh, fbx.meshes) {
foreach (const FBXMeshPart &meshPart, mesh.parts) {
QString outputFileName = baseFileName + "-" + QString::number(count) + ".obj";
writeOBJ(outputFileName, fbx, count);
writeOBJ(outputFileName, fbx, outputCentimeters, count);
count++;
}
}
@ -304,9 +338,9 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
params.m_delta = vHacdDelta;
params.m_planeDownsampling = vHacdPlanedownsampling;
params.m_convexhullDownsampling = vHacdConvexhulldownsampling;
params.m_alpha = 0.05; // 0.05 // controls the bias toward clipping along symmetry planes
params.m_beta = 0.05; // 0.05
params.m_gamma = 0.0005; // 0.0005
params.m_alpha = vHacdAlpha;
params.m_beta = vHacdBeta;
params.m_gamma = vHacdGamma;
params.m_pca = 0; // 0 enable/disable normalizing the mesh before applying the convex decomposition
params.m_mode = 0; // 0: voxel-based (recommended), 1: tetrahedron-based
params.m_maxNumVerticesPerCH = vHacdMaxVerticesPerCH;
@ -321,7 +355,7 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
FBXGeometry result;
if (!vUtil.computeVHACD(fbx, params, result, startMeshIndex, endMeshIndex,
minimumMeshSize, maximumMeshSize, fattenFaces)) {
minimumMeshSize, maximumMeshSize)) {
cout << "Compute Failed...";
}
end = std::chrono::high_resolution_clock::now();
@ -350,7 +384,34 @@ VHACDUtilApp::VHACDUtilApp(int argc, char* argv[]) :
cout << "Total FBX load time: " << (double)loadDuration / 1000000000.00 << " seconds" << endl;
cout << "V-HACD Compute time: " << (double)computeDuration / 1000000000.00 << " seconds" << endl;
writeOBJ(outputFilename, result);
writeOBJ(outputFilename, result, outputCentimeters);
}
if (fattenFaces) {
FBXGeometry newFbx;
FBXMesh result;
// count the mesh-parts
unsigned int meshCount = 0;
foreach (const FBXMesh& mesh, fbx.meshes) {
meshCount += mesh.parts.size();
}
if (startMeshIndex < 0) {
startMeshIndex = 0;
}
if (endMeshIndex < 0) {
endMeshIndex = meshCount;
}
unsigned int meshPartCount = 0;
result.modelTransform = glm::mat4(); // Identity matrix
foreach (const FBXMesh& mesh, fbx.meshes) {
vUtil.fattenMeshes(mesh, result, meshPartCount, startMeshIndex, endMeshIndex);
}
newFbx.meshes.append(result);
writeOBJ(outputFilename, newFbx, outputCentimeters);
}
}