From 8fa72396efeb8d617fdbe220b9c60d915b042f3c Mon Sep 17 00:00:00 2001 From: sabrina-shanman Date: Tue, 6 Nov 2018 11:44:31 -0800 Subject: [PATCH] Consolidate HFM class implementations into source file and move model logging. --- libraries/fbx/CMakeLists.txt | 3 +- libraries/fbx/src/FBXReader.cpp | 200 +------------- libraries/fbx/src/FBXReader_Material.cpp | 56 +--- libraries/fbx/src/FBXReader_Mesh.cpp | 2 +- libraries/fbx/src/FBXReader_Node.cpp | 2 +- libraries/fbx/src/GLTFReader.h | 2 +- libraries/fbx/src/OBJReader.cpp | 2 +- libraries/fbx/src/OBJWriter.cpp | 2 +- libraries/hfm/CMakeLists.txt | 1 + libraries/hfm/src/hfm/HFM.cpp | 259 ++++++++++++++++++ libraries/hfm/src/hfm/HFM.h | 1 - .../src/hfm}/ModelFormatLogging.cpp | 2 +- .../src => hfm/src/hfm}/ModelFormatLogging.h | 2 +- 13 files changed, 270 insertions(+), 264 deletions(-) create mode 100644 libraries/hfm/src/hfm/HFM.cpp rename libraries/{fbx/src => hfm/src/hfm}/ModelFormatLogging.cpp (94%) rename libraries/{fbx/src => hfm/src/hfm}/ModelFormatLogging.h (95%) diff --git a/libraries/fbx/CMakeLists.txt b/libraries/fbx/CMakeLists.txt index 81e5115ba7..2006d23c60 100644 --- a/libraries/fbx/CMakeLists.txt +++ b/libraries/fbx/CMakeLists.txt @@ -1,8 +1,7 @@ set(TARGET_NAME fbx) setup_hifi_library() -link_hifi_libraries(shared graphics networking image) +link_hifi_libraries(shared graphics networking image hfm) include_hifi_library_headers(gpu image) -include_hifi_library_headers(hfm) target_draco() diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 2cf57e54b4..cea3d079bc 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -33,109 +33,13 @@ #include #include -#include "ModelFormatLogging.h" +#include // TOOL: Uncomment the following line to enable the filtering of all the unkwnon fields of a node so we can break point easily while loading a model with problems... //#define DEBUG_FBXREADER using namespace std; -int HFMModelPointerMetaTypeId = qRegisterMetaType(); - -QStringList HFMModel::getJointNames() const { - QStringList names; - foreach (const HFMJoint& joint, joints) { - names.append(joint.name); - } - return names; -} - -bool HFMModel::hasBlendedMeshes() const { - if (!meshes.isEmpty()) { - foreach (const HFMMesh& mesh, meshes) { - if (!mesh.blendshapes.isEmpty()) { - return true; - } - } - } - return false; -} - -Extents HFMModel::getUnscaledMeshExtents() const { - const Extents& extents = meshExtents; - - // even though our caller asked for "unscaled" we need to include any fst scaling, translation, and rotation, which - // is captured in the offset matrix - glm::vec3 minimum = glm::vec3(offset * glm::vec4(extents.minimum, 1.0f)); - glm::vec3 maximum = glm::vec3(offset * glm::vec4(extents.maximum, 1.0f)); - Extents scaledExtents = { minimum, maximum }; - - return scaledExtents; -} - -// TODO: Move to graphics::Mesh when Sam's ready -bool HFMModel::convexHullContains(const glm::vec3& point) const { - if (!getUnscaledMeshExtents().containsPoint(point)) { - return false; - } - - auto checkEachPrimitive = [=](HFMMesh& mesh, QVector indices, int primitiveSize) -> bool { - // Check whether the point is "behind" all the primitives. - int verticesSize = mesh.vertices.size(); - for (int j = 0; - j < indices.size() - 2; // -2 in case the vertices aren't the right size -- we access j + 2 below - j += primitiveSize) { - if (indices[j] < verticesSize && - indices[j + 1] < verticesSize && - indices[j + 2] < verticesSize && - !isPointBehindTrianglesPlane(point, - mesh.vertices[indices[j]], - mesh.vertices[indices[j + 1]], - mesh.vertices[indices[j + 2]])) { - // it's not behind at least one so we bail - return false; - } - } - return true; - }; - - // Check that the point is contained in at least one convex mesh. - for (auto mesh : meshes) { - bool insideMesh = true; - - // To be considered inside a convex mesh, - // the point needs to be "behind" all the primitives respective planes. - for (auto part : mesh.parts) { - // run through all the triangles and quads - if (!checkEachPrimitive(mesh, part.triangleIndices, 3) || - !checkEachPrimitive(mesh, part.quadIndices, 4)) { - // If not, the point is outside, bail for this mesh - insideMesh = false; - continue; - } - } - if (insideMesh) { - // It's inside this mesh, return true. - return true; - } - } - - // It wasn't in any mesh, return false. - return false; -} - -QString HFMModel::getModelNameOfMesh(int meshIndex) const { - if (meshIndicesToModelNames.contains(meshIndex)) { - return meshIndicesToModelNames.value(meshIndex); - } - return QString(); -} - -int hfmModelMetaTypeId = qRegisterMetaType(); -int hfmAnimationFrameMetaTypeId = qRegisterMetaType(); -int hfmAnimationFrameVectorMetaTypeId = qRegisterMetaType>(); - - glm::vec3 parseVec3(const QString& string) { QStringList elements = string.split(','); if (elements.isEmpty()) { @@ -362,108 +266,6 @@ HFMBlendshape extractBlendshape(const FBXNode& object) { return blendshape; } -using IndexAccessor = std::function; - -static void setTangents(const HFMMesh& mesh, const IndexAccessor& vertexAccessor, int firstIndex, int secondIndex, - const QVector& vertices, const QVector& normals, QVector& tangents) { - glm::vec3 vertex[2]; - glm::vec3 normal; - glm::vec3* tangent = vertexAccessor(mesh, firstIndex, secondIndex, vertex, normal); - if (tangent) { - glm::vec3 bitangent = glm::cross(normal, vertex[1] - vertex[0]); - if (glm::length(bitangent) < EPSILON) { - return; - } - glm::vec2 texCoordDelta = mesh.texCoords.at(secondIndex) - mesh.texCoords.at(firstIndex); - glm::vec3 normalizedNormal = glm::normalize(normal); - *tangent += glm::cross(glm::angleAxis(-atan2f(-texCoordDelta.t, texCoordDelta.s), normalizedNormal) * - glm::normalize(bitangent), normalizedNormal); - } -} - -static void createTangents(const HFMMesh& mesh, bool generateFromTexCoords, - const QVector& vertices, const QVector& normals, QVector& tangents, - IndexAccessor accessor) { - // if we have a normal map (and texture coordinates), we must compute tangents - if (generateFromTexCoords && !mesh.texCoords.isEmpty()) { - tangents.resize(vertices.size()); - - foreach(const HFMMeshPart& part, mesh.parts) { - for (int i = 0; i < part.quadIndices.size(); i += 4) { - setTangents(mesh, accessor, part.quadIndices.at(i), part.quadIndices.at(i + 1), vertices, normals, tangents); - setTangents(mesh, accessor, part.quadIndices.at(i + 1), part.quadIndices.at(i + 2), vertices, normals, tangents); - setTangents(mesh, accessor, part.quadIndices.at(i + 2), part.quadIndices.at(i + 3), vertices, normals, tangents); - setTangents(mesh, accessor, part.quadIndices.at(i + 3), part.quadIndices.at(i), vertices, normals, tangents); - } - // <= size - 3 in order to prevent overflowing triangleIndices when (i % 3) != 0 - // This is most likely evidence of a further problem in extractMesh() - for (int i = 0; i <= part.triangleIndices.size() - 3; i += 3) { - setTangents(mesh, accessor, part.triangleIndices.at(i), part.triangleIndices.at(i + 1), vertices, normals, tangents); - setTangents(mesh, accessor, part.triangleIndices.at(i + 1), part.triangleIndices.at(i + 2), vertices, normals, tangents); - setTangents(mesh, accessor, part.triangleIndices.at(i + 2), part.triangleIndices.at(i), vertices, normals, tangents); - } - if ((part.triangleIndices.size() % 3) != 0) { - qCDebug(modelformat) << "Error in extractHFMModel part.triangleIndices.size() is not divisible by three "; - } - } - } -} - -static void _createBlendShapeTangents(HFMMesh& mesh, bool generateFromTexCoords, HFMBlendshape& blendShape); - -void HFMMesh::createBlendShapeTangents(bool generateTangents) { - for (auto& blendShape : blendshapes) { - _createBlendShapeTangents(*this, generateTangents, blendShape); - } -} - -void HFMMesh::createMeshTangents(bool generateFromTexCoords) { - HFMMesh& mesh = *this; - // This is the only workaround I've found to trick the compiler into understanding that mesh.tangents isn't - // const in the lambda function. - auto& tangents = mesh.tangents; - createTangents(mesh, generateFromTexCoords, mesh.vertices, mesh.normals, mesh.tangents, - [&](const HFMMesh& mesh, int firstIndex, int secondIndex, glm::vec3* outVertices, glm::vec3& outNormal) { - outVertices[0] = mesh.vertices[firstIndex]; - outVertices[1] = mesh.vertices[secondIndex]; - outNormal = mesh.normals[firstIndex]; - return &(tangents[firstIndex]); - }); -} - -static void _createBlendShapeTangents(HFMMesh& mesh, bool generateFromTexCoords, HFMBlendshape& blendShape) { - // Create lookup to get index in blend shape from vertex index in mesh - std::vector reverseIndices; - reverseIndices.resize(mesh.vertices.size()); - std::iota(reverseIndices.begin(), reverseIndices.end(), 0); - - for (int indexInBlendShape = 0; indexInBlendShape < blendShape.indices.size(); ++indexInBlendShape) { - auto indexInMesh = blendShape.indices[indexInBlendShape]; - reverseIndices[indexInMesh] = indexInBlendShape; - } - - createTangents(mesh, generateFromTexCoords, blendShape.vertices, blendShape.normals, blendShape.tangents, - [&](const HFMMesh& mesh, int firstIndex, int secondIndex, glm::vec3* outVertices, glm::vec3& outNormal) { - const auto index1 = reverseIndices[firstIndex]; - const auto index2 = reverseIndices[secondIndex]; - - if (index1 < blendShape.vertices.size()) { - outVertices[0] = blendShape.vertices[index1]; - if (index2 < blendShape.vertices.size()) { - outVertices[1] = blendShape.vertices[index2]; - } else { - // Index isn't in the blend shape so return vertex from mesh - outVertices[1] = mesh.vertices[secondIndex]; - } - outNormal = blendShape.normals[index1]; - return &blendShape.tangents[index1]; - } else { - // Index isn't in blend shape so return nullptr - return (glm::vec3*)nullptr; - } - }); -} - QVector getIndices(const QVector ids, QVector modelIDs) { QVector indices; foreach (const QString& id, ids) { diff --git a/libraries/fbx/src/FBXReader_Material.cpp b/libraries/fbx/src/FBXReader_Material.cpp index ff1de30b97..2ec8cfde75 100644 --- a/libraries/fbx/src/FBXReader_Material.cpp +++ b/libraries/fbx/src/FBXReader_Material.cpp @@ -25,61 +25,7 @@ #include #include -#include "ModelFormatLogging.h" - -void HFMMaterial::getTextureNames(QSet& textureList) const { - if (!normalTexture.isNull()) { - textureList.insert(normalTexture.name); - } - if (!albedoTexture.isNull()) { - textureList.insert(albedoTexture.name); - } - if (!opacityTexture.isNull()) { - textureList.insert(opacityTexture.name); - } - if (!glossTexture.isNull()) { - textureList.insert(glossTexture.name); - } - if (!roughnessTexture.isNull()) { - textureList.insert(roughnessTexture.name); - } - if (!specularTexture.isNull()) { - textureList.insert(specularTexture.name); - } - if (!metallicTexture.isNull()) { - textureList.insert(metallicTexture.name); - } - if (!emissiveTexture.isNull()) { - textureList.insert(emissiveTexture.name); - } - if (!occlusionTexture.isNull()) { - textureList.insert(occlusionTexture.name); - } - if (!scatteringTexture.isNull()) { - textureList.insert(scatteringTexture.name); - } - if (!lightmapTexture.isNull()) { - textureList.insert(lightmapTexture.name); - } -} - -void HFMMaterial::setMaxNumPixelsPerTexture(int maxNumPixels) { - normalTexture.maxNumPixels = maxNumPixels; - albedoTexture.maxNumPixels = maxNumPixels; - opacityTexture.maxNumPixels = maxNumPixels; - glossTexture.maxNumPixels = maxNumPixels; - roughnessTexture.maxNumPixels = maxNumPixels; - specularTexture.maxNumPixels = maxNumPixels; - metallicTexture.maxNumPixels = maxNumPixels; - emissiveTexture.maxNumPixels = maxNumPixels; - occlusionTexture.maxNumPixels = maxNumPixels; - scatteringTexture.maxNumPixels = maxNumPixels; - lightmapTexture.maxNumPixels = maxNumPixels; -} - -bool HFMMaterial::needTangentSpace() const { - return !normalTexture.isNull(); -} +#include HFMTexture FBXReader::getTexture(const QString& textureID) { HFMTexture texture; diff --git a/libraries/fbx/src/FBXReader_Mesh.cpp b/libraries/fbx/src/FBXReader_Mesh.cpp index e098aff99a..07c4c2a25a 100644 --- a/libraries/fbx/src/FBXReader_Mesh.cpp +++ b/libraries/fbx/src/FBXReader_Mesh.cpp @@ -31,7 +31,7 @@ #include #include #include -#include "ModelFormatLogging.h" +#include #include "FBXReader.h" diff --git a/libraries/fbx/src/FBXReader_Node.cpp b/libraries/fbx/src/FBXReader_Node.cpp index 9375dc7b56..cd717998dd 100644 --- a/libraries/fbx/src/FBXReader_Node.cpp +++ b/libraries/fbx/src/FBXReader_Node.cpp @@ -22,7 +22,7 @@ #include #include -#include "ModelFormatLogging.h" +#include template int streamSize() { diff --git a/libraries/fbx/src/GLTFReader.h b/libraries/fbx/src/GLTFReader.h index 44186504f0..cf01aa0c6b 100644 --- a/libraries/fbx/src/GLTFReader.h +++ b/libraries/fbx/src/GLTFReader.h @@ -14,7 +14,7 @@ #include #include -#include "ModelFormatLogging.h" +#include #include "FBXReader.h" diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 87fae0e965..dd8acec9a2 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -28,7 +28,7 @@ #include #include "FBXReader.h" -#include "ModelFormatLogging.h" +#include #include QHash COMMENT_SCALE_HINTS = {{"This file uses centimeters as units", 1.0f / 100.0f}, diff --git a/libraries/fbx/src/OBJWriter.cpp b/libraries/fbx/src/OBJWriter.cpp index 630ac95b9e..b2e191bcbf 100644 --- a/libraries/fbx/src/OBJWriter.cpp +++ b/libraries/fbx/src/OBJWriter.cpp @@ -15,7 +15,7 @@ #include #include #include -#include "ModelFormatLogging.h" +#include static QString formatFloat(double n) { // limit precision to 6, but don't output trailing zeros. diff --git a/libraries/hfm/CMakeLists.txt b/libraries/hfm/CMakeLists.txt index d569688a26..a042e51fb8 100644 --- a/libraries/hfm/CMakeLists.txt +++ b/libraries/hfm/CMakeLists.txt @@ -1,6 +1,7 @@ set(TARGET_NAME hfm) setup_hifi_library() +include_hifi_library_headers(gpu) include_hifi_library_headers(graphics) include_hifi_library_headers(shared) diff --git a/libraries/hfm/src/hfm/HFM.cpp b/libraries/hfm/src/hfm/HFM.cpp new file mode 100644 index 0000000000..8f01956f17 --- /dev/null +++ b/libraries/hfm/src/hfm/HFM.cpp @@ -0,0 +1,259 @@ +// +// HFM.cpp +// libraries/hfm/src +// +// Created by Sabrina Shanman on 2018/11/06. +// Copyright 2018 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 "HFM.h" + +#include "ModelFormatLogging.h" + +void HFMMaterial::getTextureNames(QSet& textureList) const { + if (!normalTexture.isNull()) { + textureList.insert(normalTexture.name); + } + if (!albedoTexture.isNull()) { + textureList.insert(albedoTexture.name); + } + if (!opacityTexture.isNull()) { + textureList.insert(opacityTexture.name); + } + if (!glossTexture.isNull()) { + textureList.insert(glossTexture.name); + } + if (!roughnessTexture.isNull()) { + textureList.insert(roughnessTexture.name); + } + if (!specularTexture.isNull()) { + textureList.insert(specularTexture.name); + } + if (!metallicTexture.isNull()) { + textureList.insert(metallicTexture.name); + } + if (!emissiveTexture.isNull()) { + textureList.insert(emissiveTexture.name); + } + if (!occlusionTexture.isNull()) { + textureList.insert(occlusionTexture.name); + } + if (!scatteringTexture.isNull()) { + textureList.insert(scatteringTexture.name); + } + if (!lightmapTexture.isNull()) { + textureList.insert(lightmapTexture.name); + } +} + +void HFMMaterial::setMaxNumPixelsPerTexture(int maxNumPixels) { + normalTexture.maxNumPixels = maxNumPixels; + albedoTexture.maxNumPixels = maxNumPixels; + opacityTexture.maxNumPixels = maxNumPixels; + glossTexture.maxNumPixels = maxNumPixels; + roughnessTexture.maxNumPixels = maxNumPixels; + specularTexture.maxNumPixels = maxNumPixels; + metallicTexture.maxNumPixels = maxNumPixels; + emissiveTexture.maxNumPixels = maxNumPixels; + occlusionTexture.maxNumPixels = maxNumPixels; + scatteringTexture.maxNumPixels = maxNumPixels; + lightmapTexture.maxNumPixels = maxNumPixels; +} + +bool HFMMaterial::needTangentSpace() const { + return !normalTexture.isNull(); +} + +static void _createBlendShapeTangents(HFMMesh& mesh, bool generateFromTexCoords, HFMBlendshape& blendShape); + +void HFMMesh::createBlendShapeTangents(bool generateTangents) { + for (auto& blendShape : blendshapes) { + _createBlendShapeTangents(*this, generateTangents, blendShape); + } +} + +using IndexAccessor = std::function; + +static void setTangents(const HFMMesh& mesh, const IndexAccessor& vertexAccessor, int firstIndex, int secondIndex, + const QVector& vertices, const QVector& normals, QVector& tangents) { + glm::vec3 vertex[2]; + glm::vec3 normal; + glm::vec3* tangent = vertexAccessor(mesh, firstIndex, secondIndex, vertex, normal); + if (tangent) { + glm::vec3 bitangent = glm::cross(normal, vertex[1] - vertex[0]); + if (glm::length(bitangent) < EPSILON) { + return; + } + glm::vec2 texCoordDelta = mesh.texCoords.at(secondIndex) - mesh.texCoords.at(firstIndex); + glm::vec3 normalizedNormal = glm::normalize(normal); + *tangent += glm::cross(glm::angleAxis(-atan2f(-texCoordDelta.t, texCoordDelta.s), normalizedNormal) * + glm::normalize(bitangent), normalizedNormal); + } +} + +static void createTangents(const HFMMesh& mesh, bool generateFromTexCoords, + const QVector& vertices, const QVector& normals, QVector& tangents, + IndexAccessor accessor) { + // if we have a normal map (and texture coordinates), we must compute tangents + if (generateFromTexCoords && !mesh.texCoords.isEmpty()) { + tangents.resize(vertices.size()); + + foreach(const HFMMeshPart& part, mesh.parts) { + for (int i = 0; i < part.quadIndices.size(); i += 4) { + setTangents(mesh, accessor, part.quadIndices.at(i), part.quadIndices.at(i + 1), vertices, normals, tangents); + setTangents(mesh, accessor, part.quadIndices.at(i + 1), part.quadIndices.at(i + 2), vertices, normals, tangents); + setTangents(mesh, accessor, part.quadIndices.at(i + 2), part.quadIndices.at(i + 3), vertices, normals, tangents); + setTangents(mesh, accessor, part.quadIndices.at(i + 3), part.quadIndices.at(i), vertices, normals, tangents); + } + // <= size - 3 in order to prevent overflowing triangleIndices when (i % 3) != 0 + // This is most likely evidence of a further problem in extractMesh() + for (int i = 0; i <= part.triangleIndices.size() - 3; i += 3) { + setTangents(mesh, accessor, part.triangleIndices.at(i), part.triangleIndices.at(i + 1), vertices, normals, tangents); + setTangents(mesh, accessor, part.triangleIndices.at(i + 1), part.triangleIndices.at(i + 2), vertices, normals, tangents); + setTangents(mesh, accessor, part.triangleIndices.at(i + 2), part.triangleIndices.at(i), vertices, normals, tangents); + } + if ((part.triangleIndices.size() % 3) != 0) { + qCDebug(modelformat) << "Error in extractHFMModel part.triangleIndices.size() is not divisible by three "; + } + } + } +} + +void HFMMesh::createMeshTangents(bool generateFromTexCoords) { + HFMMesh& mesh = *this; + // This is the only workaround I've found to trick the compiler into understanding that mesh.tangents isn't + // const in the lambda function. + auto& tangents = mesh.tangents; + createTangents(mesh, generateFromTexCoords, mesh.vertices, mesh.normals, mesh.tangents, + [&](const HFMMesh& mesh, int firstIndex, int secondIndex, glm::vec3* outVertices, glm::vec3& outNormal) { + outVertices[0] = mesh.vertices[firstIndex]; + outVertices[1] = mesh.vertices[secondIndex]; + outNormal = mesh.normals[firstIndex]; + return &(tangents[firstIndex]); + }); +} + +static void _createBlendShapeTangents(HFMMesh& mesh, bool generateFromTexCoords, HFMBlendshape& blendShape) { + // Create lookup to get index in blend shape from vertex index in mesh + std::vector reverseIndices; + reverseIndices.resize(mesh.vertices.size()); + std::iota(reverseIndices.begin(), reverseIndices.end(), 0); + + for (int indexInBlendShape = 0; indexInBlendShape < blendShape.indices.size(); ++indexInBlendShape) { + auto indexInMesh = blendShape.indices[indexInBlendShape]; + reverseIndices[indexInMesh] = indexInBlendShape; + } + + createTangents(mesh, generateFromTexCoords, blendShape.vertices, blendShape.normals, blendShape.tangents, + [&](const HFMMesh& mesh, int firstIndex, int secondIndex, glm::vec3* outVertices, glm::vec3& outNormal) { + const auto index1 = reverseIndices[firstIndex]; + const auto index2 = reverseIndices[secondIndex]; + + if (index1 < blendShape.vertices.size()) { + outVertices[0] = blendShape.vertices[index1]; + if (index2 < blendShape.vertices.size()) { + outVertices[1] = blendShape.vertices[index2]; + } else { + // Index isn't in the blend shape so return vertex from mesh + outVertices[1] = mesh.vertices[secondIndex]; + } + outNormal = blendShape.normals[index1]; + return &blendShape.tangents[index1]; + } else { + // Index isn't in blend shape so return nullptr + return (glm::vec3*)nullptr; + } + }); +} + +QStringList HFMModel::getJointNames() const { + QStringList names; + foreach (const HFMJoint& joint, joints) { + names.append(joint.name); + } + return names; +} + +bool HFMModel::hasBlendedMeshes() const { + if (!meshes.isEmpty()) { + foreach (const HFMMesh& mesh, meshes) { + if (!mesh.blendshapes.isEmpty()) { + return true; + } + } + } + return false; +} + +Extents HFMModel::getUnscaledMeshExtents() const { + const Extents& extents = meshExtents; + + // even though our caller asked for "unscaled" we need to include any fst scaling, translation, and rotation, which + // is captured in the offset matrix + glm::vec3 minimum = glm::vec3(offset * glm::vec4(extents.minimum, 1.0f)); + glm::vec3 maximum = glm::vec3(offset * glm::vec4(extents.maximum, 1.0f)); + Extents scaledExtents = { minimum, maximum }; + + return scaledExtents; +} + +// TODO: Move to graphics::Mesh when Sam's ready +bool HFMModel::convexHullContains(const glm::vec3& point) const { + if (!getUnscaledMeshExtents().containsPoint(point)) { + return false; + } + + auto checkEachPrimitive = [=](HFMMesh& mesh, QVector indices, int primitiveSize) -> bool { + // Check whether the point is "behind" all the primitives. + int verticesSize = mesh.vertices.size(); + for (int j = 0; + j < indices.size() - 2; // -2 in case the vertices aren't the right size -- we access j + 2 below + j += primitiveSize) { + if (indices[j] < verticesSize && + indices[j + 1] < verticesSize && + indices[j + 2] < verticesSize && + !isPointBehindTrianglesPlane(point, + mesh.vertices[indices[j]], + mesh.vertices[indices[j + 1]], + mesh.vertices[indices[j + 2]])) { + // it's not behind at least one so we bail + return false; + } + } + return true; + }; + + // Check that the point is contained in at least one convex mesh. + for (auto mesh : meshes) { + bool insideMesh = true; + + // To be considered inside a convex mesh, + // the point needs to be "behind" all the primitives respective planes. + for (auto part : mesh.parts) { + // run through all the triangles and quads + if (!checkEachPrimitive(mesh, part.triangleIndices, 3) || + !checkEachPrimitive(mesh, part.quadIndices, 4)) { + // If not, the point is outside, bail for this mesh + insideMesh = false; + continue; + } + } + if (insideMesh) { + // It's inside this mesh, return true. + return true; + } + } + + // It wasn't in any mesh, return false. + return false; +} + +QString HFMModel::getModelNameOfMesh(int meshIndex) const { + if (meshIndicesToModelNames.contains(meshIndex)) { + return meshIndicesToModelNames.value(meshIndex); + } + return QString(); +} diff --git a/libraries/hfm/src/hfm/HFM.h b/libraries/hfm/src/hfm/HFM.h index dd5250ca83..1766d519cc 100644 --- a/libraries/hfm/src/hfm/HFM.h +++ b/libraries/hfm/src/hfm/HFM.h @@ -352,7 +352,6 @@ public: Q_DECLARE_METATYPE(HFMAnimationFrame) Q_DECLARE_METATYPE(QVector) - Q_DECLARE_METATYPE(HFMModel) Q_DECLARE_METATYPE(HFMModel::Pointer) diff --git a/libraries/fbx/src/ModelFormatLogging.cpp b/libraries/hfm/src/hfm/ModelFormatLogging.cpp similarity index 94% rename from libraries/fbx/src/ModelFormatLogging.cpp rename to libraries/hfm/src/hfm/ModelFormatLogging.cpp index e720b3c054..7748b8496d 100644 --- a/libraries/fbx/src/ModelFormatLogging.cpp +++ b/libraries/hfm/src/hfm/ModelFormatLogging.cpp @@ -1,6 +1,6 @@ // // ModelFormatLogging.cpp -// libraries/fbx/src +// libraries/hfm/src // // Created by Seth Alves on 4/6/15. // Copyright 2014 High Fidelity, Inc. diff --git a/libraries/fbx/src/ModelFormatLogging.h b/libraries/hfm/src/hfm/ModelFormatLogging.h similarity index 95% rename from libraries/fbx/src/ModelFormatLogging.h rename to libraries/hfm/src/hfm/ModelFormatLogging.h index 19c7c27322..745f22d7ff 100644 --- a/libraries/fbx/src/ModelFormatLogging.h +++ b/libraries/hfm/src/hfm/ModelFormatLogging.h @@ -1,6 +1,6 @@ // // ModelFormatLogging.h -// libraries/fbx/src +// libraries/hfm/src // // Created by Seth Alves on 4/6/15. // Copyright 2014 High Fidelity, Inc.