From a73cad91bcf1d74bc7f8dfe4277e0d43b58b04e9 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 29 Oct 2014 08:09:10 -0700 Subject: [PATCH 1/7] first cut at reading and mapping submeshes to named models --- libraries/fbx/src/FBXReader.cpp | 101 +++++++++++++++++++++++++++++--- libraries/fbx/src/FBXReader.h | 9 +++ 2 files changed, 103 insertions(+), 7 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 2a51a83ab8..655498f4d5 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -71,6 +71,14 @@ Extents FBXGeometry::getUnscaledMeshExtents() const { return scaledExtents; } +QString FBXGeometry::getModelNameOfMesh(int meshIndex) const { + if (meshIndicesToModelNames.contains(meshIndex)) { + return meshIndicesToModelNames.value(meshIndex); + } + return QString(); +} + + static int fbxGeometryMetaTypeId = qRegisterMetaType(); static int fbxAnimationFrameMetaTypeId = qRegisterMetaType(); @@ -513,6 +521,17 @@ QString processID(const QString& id) { return id.mid(id.lastIndexOf(':') + 1); } +QString getName(const QVariantList& properties) { + QString name; + if (properties.size() == 3) { + name = properties.at(1).toString(); + name = processID(name.left(name.indexOf(QChar('\0')))); + } else { + name = processID(properties.at(0).toString()); + } + return name; +} + QString getID(const QVariantList& properties, int index = 0) { return processID(properties.at(index).toString()); } @@ -870,6 +889,10 @@ ExtractedMesh extractMesh(const FBXNode& object) { beginIndex = endIndex; } } + + //data.extracted.mesh.name = getID(object.properties); // remember the name + + //qDebug() << "extractMesh() extracted mesh of name:" << getID(object.properties); return data.extracted; } @@ -1008,7 +1031,13 @@ bool checkMaterialsHaveTextures(const QHash& materials, } FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) { +qDebug() << "extractFBXGeometry() --------------"; + QHash meshes; + QHash modelIDsToNames; + QHash meshIDsToMeshIndices; + QHash ooChildToParent; + QVector blendshapes; QMultiHash parentMap; QMultiHash childMap; @@ -1079,6 +1108,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) FBXGeometry geometry; float unitScaleFactor = 1.0f; foreach (const FBXNode& child, node.children) { + if (child.name == "FBXHeaderExtension") { foreach (const FBXNode& object, child.children) { if (object.name == "SceneInfo") { @@ -1113,8 +1143,19 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } } else if (child.name == "Objects") { foreach (const FBXNode& object, child.children) { + +qDebug() << "object type:" << object.name + << " name:" << getName(object.properties) + << " ID:" << getID(object.properties); + if (object.name == "Geometry") { + + //qDebug() << "geometry of name:" << getID(object.properties); + if (object.properties.at(2) == "Mesh") { + +qDebug() << "EXTRACTING MESH!!!"; + meshes.insert(getID(object.properties), extractMesh(object)); } else { // object.properties.at(2) == "Shape" @@ -1122,14 +1163,15 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) blendshapes.append(extracted); } } else if (object.name == "Model") { - QString name; - if (object.properties.size() == 3) { - name = object.properties.at(1).toString(); - name = processID(name.left(name.indexOf(QChar('\0')))); - } else { - name = getID(object.properties); - } + //qDebug() << "model of name:" << getID(object.properties); + + QString name = getName(object.properties); + QString id = getID(object.properties); + +qDebug() << "model of name:" << name << "id:" << id; + modelIDsToNames.insert(id, name); + if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye") { jointEyeLeftID = getID(object.properties); @@ -1393,6 +1435,17 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) } else if (child.name == "Connections") { foreach (const FBXNode& connection, child.children) { if (connection.name == "C" || connection.name == "Connect") { + if (connection.properties.at(0) == "OO") { + QString childID = getID(connection.properties, 1); + QString parentID = getID(connection.properties, 2); + +qDebug() << "OO Connection child: " << childID << " - parentID: " << parentID; + + ooChildToParent.insert(childID, parentID); + } else { + qDebug() << connection.properties.at(0) << " Connection 1: " << getID(connection.properties, 1) + << " - 2: " << getID(connection.properties, 2); + } if (connection.properties.at(0) == "OP") { QByteArray type = connection.properties.at(3).toByteArray().toLower(); if (type.contains("diffuse")) { @@ -1883,6 +1936,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) extracted.mesh.isEye = (maxJointIndex == geometry.leftEyeJointIndex || maxJointIndex == geometry.rightEyeJointIndex); geometry.meshes.append(extracted.mesh); + int meshIndex = geometry.meshes.size() - 1; + qDebug() << "*********************** meshID: " << it.key() << "index:" << meshIndex; + meshIDsToMeshIndices.insert(it.key(), meshIndex); + } // now that all joints have been scanned, compute a collision shape for each joint @@ -1982,6 +2039,36 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) geometry.sittingPoints.append(sittingPoint); } + //qDebug() << "parentMap:" << parentMap; + + // attempt to map any meshes to a named model + // geometry.meshIndicesToModelNames; // QHash + + qDebug() << "meshIDsToMeshIndices: " << meshIDsToMeshIndices; + qDebug() << "ooChildToParent: " << ooChildToParent; + qDebug() << "modelIDsToNames: " << modelIDsToNames; + + for (QHash::const_iterator m = meshIDsToMeshIndices.constBegin(); + m != meshIDsToMeshIndices.constEnd(); m++) { + const QString& meshID = m.key(); + int meshIndex = m.value(); + + if (ooChildToParent.contains(meshID)) { + const QString& modelID = ooChildToParent.value(meshID); + qDebug() << "modelID: " << modelID << "... from meshID:" << meshID; + const QString& modelName = modelIDsToNames.value(modelID); + qDebug() << "modelName: " << modelName << "... from modelID:" << modelID; + geometry.meshIndicesToModelNames.insert(meshIndex, modelName); + } else { + qDebug() << "ooChildToParent. DOES NOT CONTAIN meshID:" << meshID; + } + } + qDebug() << "meshIndicesToModelNames: " << geometry.meshIndicesToModelNames; + + + +qDebug() << "------- DONE --------- extractFBXGeometry() --------------"; + return geometry; } diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 49b0534438..173c9336c4 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -143,6 +143,9 @@ public: QVector blendshapes; bool hasSpecularTexture() const; + + //QString name; + //int foo; }; /// A single animation frame extracted from an FBX document. @@ -220,6 +223,12 @@ public: /// Returns the unscaled extents of the model's mesh Extents getUnscaledMeshExtents() const; + + + QHash meshIndicesToModelNames; + + /// given a meshIndex this will return the name of the model that mesh belongs to if known + QString getModelNameOfMesh(int meshIndex) const; }; Q_DECLARE_METATYPE(FBXGeometry) From 6b1dc6788388e0ca3e57ea7f82f6bd3f18cd2975 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 29 Oct 2014 08:17:30 -0700 Subject: [PATCH 2/7] some cleanup --- libraries/fbx/src/FBXReader.cpp | 56 ++++----------------------------- 1 file changed, 6 insertions(+), 50 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 655498f4d5..014d694768 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -890,10 +890,6 @@ ExtractedMesh extractMesh(const FBXNode& object) { } } - //data.extracted.mesh.name = getID(object.properties); // remember the name - - //qDebug() << "extractMesh() extracted mesh of name:" << getID(object.properties); - return data.extracted; } @@ -1031,8 +1027,6 @@ bool checkMaterialsHaveTextures(const QHash& materials, } FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) { -qDebug() << "extractFBXGeometry() --------------"; - QHash meshes; QHash modelIDsToNames; QHash meshIDsToMeshIndices; @@ -1143,33 +1137,16 @@ qDebug() << "extractFBXGeometry() --------------"; } } else if (child.name == "Objects") { foreach (const FBXNode& object, child.children) { - -qDebug() << "object type:" << object.name - << " name:" << getName(object.properties) - << " ID:" << getID(object.properties); - if (object.name == "Geometry") { - - //qDebug() << "geometry of name:" << getID(object.properties); - if (object.properties.at(2) == "Mesh") { - -qDebug() << "EXTRACTING MESH!!!"; - meshes.insert(getID(object.properties), extractMesh(object)); - } else { // object.properties.at(2) == "Shape" ExtractedBlendshape extracted = { getID(object.properties), extractBlendshape(object) }; blendshapes.append(extracted); } } else if (object.name == "Model") { - - //qDebug() << "model of name:" << getID(object.properties); - QString name = getName(object.properties); QString id = getID(object.properties); - -qDebug() << "model of name:" << name << "id:" << id; modelIDsToNames.insert(id, name); if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye") { @@ -1438,13 +1415,7 @@ qDebug() << "model of name:" << name << "id:" << id; if (connection.properties.at(0) == "OO") { QString childID = getID(connection.properties, 1); QString parentID = getID(connection.properties, 2); - -qDebug() << "OO Connection child: " << childID << " - parentID: " << parentID; - ooChildToParent.insert(childID, parentID); - } else { - qDebug() << connection.properties.at(0) << " Connection 1: " << getID(connection.properties, 1) - << " - 2: " << getID(connection.properties, 2); } if (connection.properties.at(0) == "OP") { QByteArray type = connection.properties.at(3).toByteArray().toLower(); @@ -1937,7 +1908,6 @@ qDebug() << "OO Connection child: " << childID << " - parentID: " << parentID; geometry.meshes.append(extracted.mesh); int meshIndex = geometry.meshes.size() - 1; - qDebug() << "*********************** meshID: " << it.key() << "index:" << meshIndex; meshIDsToMeshIndices.insert(it.key(), meshIndex); } @@ -2039,35 +2009,21 @@ qDebug() << "OO Connection child: " << childID << " - parentID: " << parentID; geometry.sittingPoints.append(sittingPoint); } - //qDebug() << "parentMap:" << parentMap; - // attempt to map any meshes to a named model - // geometry.meshIndicesToModelNames; // QHash - - qDebug() << "meshIDsToMeshIndices: " << meshIDsToMeshIndices; - qDebug() << "ooChildToParent: " << ooChildToParent; - qDebug() << "modelIDsToNames: " << modelIDsToNames; - for (QHash::const_iterator m = meshIDsToMeshIndices.constBegin(); - m != meshIDsToMeshIndices.constEnd(); m++) { + m != meshIDsToMeshIndices.constEnd(); m++) { + const QString& meshID = m.key(); int meshIndex = m.value(); if (ooChildToParent.contains(meshID)) { const QString& modelID = ooChildToParent.value(meshID); - qDebug() << "modelID: " << modelID << "... from meshID:" << meshID; - const QString& modelName = modelIDsToNames.value(modelID); - qDebug() << "modelName: " << modelName << "... from modelID:" << modelID; - geometry.meshIndicesToModelNames.insert(meshIndex, modelName); - } else { - qDebug() << "ooChildToParent. DOES NOT CONTAIN meshID:" << meshID; + if (modelIDsToNames.contains(modelID)) { + const QString& modelName = modelIDsToNames.value(modelID); + geometry.meshIndicesToModelNames.insert(meshIndex, modelName); + } } } - qDebug() << "meshIndicesToModelNames: " << geometry.meshIndicesToModelNames; - - - -qDebug() << "------- DONE --------- extractFBXGeometry() --------------"; return geometry; } From 3e9bc23c2f1746225dfe1863a116de2683f95a5d Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 29 Oct 2014 10:19:04 -0700 Subject: [PATCH 3/7] moving RenderArgs into shared so it can be used by overlays, first cut at ray picking against submeshes --- interface/src/Application.cpp | 2 +- interface/src/entities/EntityTreeRenderer.cpp | 7 +- interface/src/entities/EntityTreeRenderer.h | 3 +- interface/src/renderer/Model.cpp | 124 ++++++++++++++++-- interface/src/renderer/Model.h | 9 +- .../src/ui/overlays/BillboardOverlay.cpp | 2 +- interface/src/ui/overlays/BillboardOverlay.h | 2 +- interface/src/ui/overlays/Circle3DOverlay.cpp | 2 +- interface/src/ui/overlays/Circle3DOverlay.h | 2 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 2 +- interface/src/ui/overlays/Cube3DOverlay.h | 2 +- interface/src/ui/overlays/ImageOverlay.cpp | 2 +- interface/src/ui/overlays/ImageOverlay.h | 2 +- interface/src/ui/overlays/Line3DOverlay.cpp | 2 +- interface/src/ui/overlays/Line3DOverlay.h | 2 +- .../src/ui/overlays/LocalModelsOverlay.cpp | 2 +- .../src/ui/overlays/LocalModelsOverlay.h | 2 +- .../src/ui/overlays/LocalVoxelsOverlay.cpp | 2 +- .../src/ui/overlays/LocalVoxelsOverlay.h | 2 +- interface/src/ui/overlays/ModelOverlay.cpp | 10 +- interface/src/ui/overlays/ModelOverlay.h | 2 +- interface/src/ui/overlays/Overlay.h | 3 +- interface/src/ui/overlays/Overlays.cpp | 15 ++- .../src/ui/overlays/Rectangle3DOverlay.cpp | 2 +- .../src/ui/overlays/Rectangle3DOverlay.h | 2 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- interface/src/ui/overlays/Sphere3DOverlay.h | 2 +- interface/src/ui/overlays/Text3DOverlay.cpp | 2 +- interface/src/ui/overlays/Text3DOverlay.h | 4 +- interface/src/ui/overlays/TextOverlay.cpp | 2 +- interface/src/ui/overlays/TextOverlay.h | 2 +- libraries/octree/src/OctreeHeadlessViewer.h | 2 +- libraries/octree/src/OctreeRenderer.cpp | 3 +- libraries/octree/src/OctreeRenderer.h | 33 +---- libraries/shared/src/RenderArgs.h | 46 +++++++ 35 files changed, 228 insertions(+), 77 deletions(-) create mode 100644 libraries/shared/src/RenderArgs.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 438713e03d..17d49e35f2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2791,7 +2791,7 @@ void Application::updateShadowMap() { { PerformanceTimer perfTimer("entities"); - _entities.render(OctreeRenderer::SHADOW_RENDER_MODE); + _entities.render(RenderArgs::SHADOW_RENDER_MODE); } glDisable(GL_POLYGON_OFFSET_FILL); diff --git a/interface/src/entities/EntityTreeRenderer.cpp b/interface/src/entities/EntityTreeRenderer.cpp index 2c7c970376..876547e389 100644 --- a/interface/src/entities/EntityTreeRenderer.cpp +++ b/interface/src/entities/EntityTreeRenderer.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "Menu.h" @@ -65,7 +66,7 @@ void EntityTreeRenderer::update() { } } -void EntityTreeRenderer::render(RenderMode renderMode) { +void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode) { OctreeRenderer::render(renderMode); deleteReleasedModels(); // seems like as good as any other place to do some memory cleanup } @@ -163,7 +164,7 @@ void renderElementProxy(EntityTreeElement* entityTreeElement) { } void EntityTreeRenderer::renderProxies(const EntityItem* entity, RenderArgs* args) { - bool isShadowMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE; + bool isShadowMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE; bool displayModelBounds = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelBounds); if (!isShadowMode && displayModelBounds) { PerformanceTimer perfTimer("renderProxies"); @@ -237,7 +238,7 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) uint16_t numberOfEntities = entityItems.size(); - bool isShadowMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE; + bool isShadowMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE; bool displayElementProxy = Menu::getInstance()->isOptionChecked(MenuOption::DisplayModelElementProxy); diff --git a/interface/src/entities/EntityTreeRenderer.h b/interface/src/entities/EntityTreeRenderer.h index 7ce984a97d..09d931541d 100644 --- a/interface/src/entities/EntityTreeRenderer.h +++ b/interface/src/entities/EntityTreeRenderer.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -48,7 +49,7 @@ public: void processEraseMessage(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode); virtual void init(); - virtual void render(RenderMode renderMode = DEFAULT_RENDER_MODE); + virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE); virtual const FBXGeometry* getGeometryForEntity(const EntityItem* entityItem); virtual const Model* getModelForEntityItem(const EntityItem* entityItem); diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index e949e9a811..823ac0cc7e 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -394,6 +394,99 @@ void Model::setJointStates(QVector states) { _boundingRadius = radius; } +bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, + float& distance, BoxFace& face) const { + + //return false; + qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; + + bool intersectedSomething = false; + + // if we aren't active, we can't ray pick yet... + if (!isActive()) { + qDebug() << " line:" << __LINE__ << " returning intersectedSomething:" << intersectedSomething; + return intersectedSomething; + } + + // if we don't have valid mesh boxes, calculate them now. We cache the results of these calculations + // so long as the model hasn't been simulated and the mesh hasn't changed. + /* + if (!_calculatedMeshBoxesValid) { + recalcuateMeshBoxes(); + } + */ + + // extents is the entity relative, scaled, centered extents of the entity + glm::vec3 position = _translation; + glm::mat4 rotation = glm::mat4_cast(_rotation); + glm::mat4 translation = glm::translate(position); + glm::mat4 modelToWorldMatrix = translation * rotation; + glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); + + Extents modelExtents = getMeshExtents(); // NOTE: unrotated + + glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; + glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the model frame of reference + AABox overlayFrameBox(corner, dimensions); + + glm::vec3 modelFrameOrigin = glm::vec3(worldToModelMatrix * glm::vec4(origin, 1.0f)); + glm::vec3 modelFrameDirection = glm::vec3(worldToModelMatrix * glm::vec4(direction, 0.0f)); + + // we can use the AABox's ray intersection by mapping our origin and direction into the model frame + // and testing intersection there. + if (overlayFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { + + qDebug() << " line:" << __LINE__ << " overlayFrameBox.findRayIntersection() TRUE consider sub meshes!"; + + float bestDistance = std::numeric_limits::max(); + float distanceToSubMesh; + BoxFace subMeshFace; + BoxFace bestSubMeshFace; + int subMeshIndex = 0; + int bestSubMeshIndex = -1; + + // If we hit the models box, then consider the submeshes... + foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + //qDebug() << " consider sub mesh[" << subMeshIndex <<"] " + // << subMeshBox << "name:" << geometry.getModelNameOfMesh(subMeshIndex); + + if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { + if (distanceToSubMesh < bestDistance) { + bestSubMeshIndex = subMeshIndex; + bestDistance = distanceToSubMesh; + bestSubMeshFace = subMeshFace; + intersectedSomething = true; + qDebug() << " INTERSECTS sub mesh[" << subMeshIndex <<"] " + << subMeshBox + << "distance:" << distanceToSubMesh + << "name:" << geometry.getModelNameOfMesh(subMeshIndex); + } + } + subMeshIndex++; + } + + return intersectedSomething; + } + + return intersectedSomething; +} + +void Model::recalcuateMeshBoxes() { + if (!_calculatedMeshBoxesValid) { + PerformanceTimer perfTimer("calculatedMeshBoxes"); + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + int numberOfMeshes = geometry.meshes.size(); + _calculatedMeshBoxes.resize(numberOfMeshes); + for (int i = 0; i < numberOfMeshes; i++) { + const FBXMesh& mesh = geometry.meshes.at(i); + Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents); + _calculatedMeshBoxes[i] = AABox(scaledMeshExtents); + } + _calculatedMeshBoxesValid = true; + } +} + bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); // render the attachments @@ -408,17 +501,8 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { // where our caller has passed RenderArgs which will include a view frustum we can cull // against. We cache the results of these calculations so long as the model hasn't been // simulated and the mesh hasn't changed. - if (args && !_calculatedMeshBoxesValid) { - PerformanceTimer perfTimer("calculatedMeshBoxes"); - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - int numberOfMeshes = geometry.meshes.size(); - _calculatedMeshBoxes.resize(numberOfMeshes); - for (int i = 0; i < numberOfMeshes; i++) { - const FBXMesh& mesh = geometry.meshes.at(i); - Extents scaledMeshExtents = calculateScaledOffsetExtents(mesh.meshExtents); - _calculatedMeshBoxes[i] = AABox(scaledMeshExtents); - } - _calculatedMeshBoxesValid = true; + if (/*args &&*/ !_calculatedMeshBoxesValid) { + recalcuateMeshBoxes(); } // set up dilated textures on first render after load/simulate @@ -858,7 +942,15 @@ void Model::setScaleToFit(bool scaleToFit, const glm::vec3& dimensions) { } void Model::setScaleToFit(bool scaleToFit, float largestDimension) { + // NOTE: if the model is not active, then it means we don't actually know the true/natural dimensions of the + // mesh, and so we can't do the needed calculations for scaling to fit to a single largest dimension. In this + // case we will record that we do want to do this, but we will stick our desired single dimension into the + // first element of the vec3 for the non-fixed aspect ration dimensions if (!isActive()) { + _scaleToFit = scaleToFit; + if (scaleToFit) { + _scaleToFitDimensions = glm::vec3(largestDimension, FAKE_DIMENSION_PLACEHOLDER, FAKE_DIMENSION_PLACEHOLDER); + } return; } @@ -880,6 +972,15 @@ void Model::setScaleToFit(bool scaleToFit, float largestDimension) { } void Model::scaleToFit() { + // If our _scaleToFitDimensions.y/z are FAKE_DIMENSION_PLACEHOLDER then it means our + // user asked to scale us in a fixed aspect ratio to a single largest dimension, but + // we didn't yet have an active mesh. We can only enter this scaleToFit() in this state + // if we now do have an active mesh, so we take this opportunity to actually determine + // the correct scale. + if (_scaleToFit && _scaleToFitDimensions.y == FAKE_DIMENSION_PLACEHOLDER + && _scaleToFitDimensions.z == FAKE_DIMENSION_PLACEHOLDER) { + setScaleToFit(_scaleToFit, _scaleToFitDimensions.x); + } Extents modelMeshExtents = getUnscaledMeshExtents(); // size is our "target size in world space" @@ -912,6 +1013,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) { || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); if (isActive() && fullUpdate) { + //qDebug() << "simulated _calculatedMeshBoxesValid = false"; _calculatedMeshBoxesValid = false; // if we have to simulate, we need to assume our mesh boxes are all invalid // check for scale to fit diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 7df8f27605..75a4e4776a 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -189,13 +189,18 @@ public: Q_INVOKABLE void setTextureWithNameToURL(const QString& name, const QUrl& url) { _geometry->setTextureWithNameToURL(name, url); } - + + bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, + float& distance, BoxFace& face) const; + protected: QSharedPointer _geometry; glm::vec3 _scale; glm::vec3 _offset; + const float FAKE_DIMENSION_PLACEHOLDER = -1.0f; + bool _scaleToFit; /// If you set scaleToFit, we will calculate scale based on MeshExtents glm::vec3 _scaleToFitDimensions; /// this is the dimensions that scale to fit will use bool _scaledToFit; /// have we scaled to fit @@ -341,6 +346,8 @@ private: QVector _calculatedMeshBoxes; bool _calculatedMeshBoxesValid; + void recalcuateMeshBoxes(); + void segregateMeshGroups(); // used to calculate our list of translucent vs opaque meshes bool _meshGroupsKnown; diff --git a/interface/src/ui/overlays/BillboardOverlay.cpp b/interface/src/ui/overlays/BillboardOverlay.cpp index c52b07bcfa..c8d4877bb5 100644 --- a/interface/src/ui/overlays/BillboardOverlay.cpp +++ b/interface/src/ui/overlays/BillboardOverlay.cpp @@ -24,7 +24,7 @@ BillboardOverlay::BillboardOverlay() : _isLoaded = false; } -void BillboardOverlay::render() { +void BillboardOverlay::render(RenderArgs* args) { if (!_visible || !_isLoaded) { return; } diff --git a/interface/src/ui/overlays/BillboardOverlay.h b/interface/src/ui/overlays/BillboardOverlay.h index c0c2b05364..018ca5f5cf 100644 --- a/interface/src/ui/overlays/BillboardOverlay.h +++ b/interface/src/ui/overlays/BillboardOverlay.h @@ -23,7 +23,7 @@ class BillboardOverlay : public Base3DOverlay { public: BillboardOverlay(); - virtual void render(); + virtual void render(RenderArgs* args); // setters void setURL(const QString& url); diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index d7120a5ff8..144119c450 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -36,7 +36,7 @@ Circle3DOverlay::Circle3DOverlay() : Circle3DOverlay::~Circle3DOverlay() { } -void Circle3DOverlay::render() { +void Circle3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/Circle3DOverlay.h b/interface/src/ui/overlays/Circle3DOverlay.h index 289781cdd7..191a0d3100 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.h +++ b/interface/src/ui/overlays/Circle3DOverlay.h @@ -19,7 +19,7 @@ class Circle3DOverlay : public Planar3DOverlay { public: Circle3DOverlay(); ~Circle3DOverlay(); - virtual void render(); + virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); float getStartAt() const { return _startAt; } diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 8395fafcaa..81a2dfd498 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -25,7 +25,7 @@ Cube3DOverlay::Cube3DOverlay() { Cube3DOverlay::~Cube3DOverlay() { } -void Cube3DOverlay::render() { +void Cube3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/Cube3DOverlay.h b/interface/src/ui/overlays/Cube3DOverlay.h index 828048e697..272d68bb5e 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.h +++ b/interface/src/ui/overlays/Cube3DOverlay.h @@ -19,7 +19,7 @@ class Cube3DOverlay : public Volume3DOverlay { public: Cube3DOverlay(); ~Cube3DOverlay(); - virtual void render(); + virtual void render(RenderArgs* args); }; diff --git a/interface/src/ui/overlays/ImageOverlay.cpp b/interface/src/ui/overlays/ImageOverlay.cpp index 2b4e1e2f56..b0bcd6d5ae 100644 --- a/interface/src/ui/overlays/ImageOverlay.cpp +++ b/interface/src/ui/overlays/ImageOverlay.cpp @@ -52,7 +52,7 @@ void ImageOverlay::replyFinished() { _isLoaded = true; } -void ImageOverlay::render() { +void ImageOverlay::render(RenderArgs* args) { if (!_visible || !_isLoaded) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/ImageOverlay.h b/interface/src/ui/overlays/ImageOverlay.h index 633567287d..ef1ead8c02 100644 --- a/interface/src/ui/overlays/ImageOverlay.h +++ b/interface/src/ui/overlays/ImageOverlay.h @@ -34,7 +34,7 @@ class ImageOverlay : public Overlay2D { public: ImageOverlay(); ~ImageOverlay(); - virtual void render(); + virtual void render(RenderArgs* args); // getters const QRect& getClipFromSource() const { return _fromImage; } diff --git a/interface/src/ui/overlays/Line3DOverlay.cpp b/interface/src/ui/overlays/Line3DOverlay.cpp index d386ae41bf..18671ea074 100644 --- a/interface/src/ui/overlays/Line3DOverlay.cpp +++ b/interface/src/ui/overlays/Line3DOverlay.cpp @@ -21,7 +21,7 @@ Line3DOverlay::Line3DOverlay() { Line3DOverlay::~Line3DOverlay() { } -void Line3DOverlay::render() { +void Line3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/Line3DOverlay.h b/interface/src/ui/overlays/Line3DOverlay.h index 5b802f49c8..f9c4e0d6d6 100644 --- a/interface/src/ui/overlays/Line3DOverlay.h +++ b/interface/src/ui/overlays/Line3DOverlay.h @@ -19,7 +19,7 @@ class Line3DOverlay : public Base3DOverlay { public: Line3DOverlay(); ~Line3DOverlay(); - virtual void render(); + virtual void render(RenderArgs* args); // getters const glm::vec3& getEnd() const { return _end; } diff --git a/interface/src/ui/overlays/LocalModelsOverlay.cpp b/interface/src/ui/overlays/LocalModelsOverlay.cpp index efecd74009..c1f16bf13e 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalModelsOverlay.cpp @@ -25,7 +25,7 @@ void LocalModelsOverlay::update(float deltatime) { _entityTreeRenderer->update(); } -void LocalModelsOverlay::render() { +void LocalModelsOverlay::render(RenderArgs* args) { if (_visible) { float glowLevel = getGlowLevel(); diff --git a/interface/src/ui/overlays/LocalModelsOverlay.h b/interface/src/ui/overlays/LocalModelsOverlay.h index b6265e6244..60f09b8666 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.h +++ b/interface/src/ui/overlays/LocalModelsOverlay.h @@ -23,7 +23,7 @@ public: ~LocalModelsOverlay(); virtual void update(float deltatime); - virtual void render(); + virtual void render(RenderArgs* args); private: EntityTreeRenderer* _entityTreeRenderer; diff --git a/interface/src/ui/overlays/LocalVoxelsOverlay.cpp b/interface/src/ui/overlays/LocalVoxelsOverlay.cpp index 6a474fb33e..dcfc79f3b4 100644 --- a/interface/src/ui/overlays/LocalVoxelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalVoxelsOverlay.cpp @@ -51,7 +51,7 @@ void LocalVoxelsOverlay::update(float deltatime) { _tree->unlock(); } -void LocalVoxelsOverlay::render() { +void LocalVoxelsOverlay::render(RenderArgs* args) { glm::vec3 dimensions = getDimensions(); float size = glm::length(dimensions); if (_visible && size > 0 && _voxelSystem && _voxelSystem->isInitialized()) { diff --git a/interface/src/ui/overlays/LocalVoxelsOverlay.h b/interface/src/ui/overlays/LocalVoxelsOverlay.h index cc23b05ff6..46a88407af 100644 --- a/interface/src/ui/overlays/LocalVoxelsOverlay.h +++ b/interface/src/ui/overlays/LocalVoxelsOverlay.h @@ -35,7 +35,7 @@ public: ~LocalVoxelsOverlay(); virtual void update(float deltatime); - virtual void render(); + virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 0169bf40cd..94ed11c9cb 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -26,6 +26,8 @@ void ModelOverlay::update(float deltatime) { _updateModel = false; _model.setScaleToFit(true, _scale); +qDebug() << "setScaleToFit() scale: " << _scale; + _model.setSnapModelToCenter(true); _model.setRotation(_rotation); _model.setTranslation(_position); @@ -37,7 +39,7 @@ void ModelOverlay::update(float deltatime) { _isLoaded = _model.isActive(); } -void ModelOverlay::render() { +void ModelOverlay::render(RenderArgs* args) { if (!_visible) { return; } @@ -70,6 +72,7 @@ void ModelOverlay::setProperties(const QScriptValue &properties) { QScriptValue scaleValue = properties.property("scale"); if (scaleValue.isValid()) { _scale = scaleValue.toVariant().toFloat(); +qDebug() << "scale: " << _scale; _updateModel = true; } @@ -125,6 +128,10 @@ void ModelOverlay::setProperties(const QScriptValue &properties) { bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const { + qDebug() << "ModelOverlay::findRayIntersection() calling _model.findRayIntersectionAgainstSubMeshes()..."; + return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face); + + /* // if our model isn't active, we can't ray pick yet... if (!_model.isActive()) { return false; @@ -153,4 +160,5 @@ bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& } return false; + */ } diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index a116958b7e..71ac4c8b19 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -22,7 +22,7 @@ public: ModelOverlay(); virtual void update(float deltatime); - virtual void render(); + virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index d4d0c40135..81ddaf1a91 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -20,6 +20,7 @@ #include #include // for xColor +#include const xColor DEFAULT_OVERLAY_COLOR = { 255, 255, 255 }; const float DEFAULT_ALPHA = 0.7f; @@ -37,7 +38,7 @@ public: ~Overlay(); void init(QGLWidget* parent); virtual void update(float deltatime) {} - virtual void render() = 0; + virtual void render(RenderArgs* args) = 0; // getters virtual bool is3D() const = 0; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index b079acb0a8..67be69c9ed 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -10,6 +10,7 @@ #include #include +#include #include "BillboardOverlay.h" #include "Circle3DOverlay.h" @@ -78,8 +79,13 @@ void Overlays::update(float deltatime) { void Overlays::render2D() { QReadLocker lock(&_lock); + + RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(), + Menu::getInstance()->getVoxelSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(), + RenderArgs::DEFAULT_RENDER_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + foreach(Overlay* thisOverlay, _overlays2D) { - thisOverlay->render(); + thisOverlay->render(&args); } } @@ -95,6 +101,11 @@ void Overlays::render3D() { float angle = 0.0f; glm::vec3 axis(0.0f, 1.0f, 0.0f); float myAvatarScale = 1.0f; + + RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(), + Menu::getInstance()->getVoxelSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(), + RenderArgs::DEFAULT_RENDER_MODE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + foreach(Overlay* thisOverlay, _overlays3D) { glPushMatrix(); @@ -118,7 +129,7 @@ void Overlays::render3D() { default: break; } - thisOverlay->render(); + thisOverlay->render(&args); glPopMatrix(); } } diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.cpp b/interface/src/ui/overlays/Rectangle3DOverlay.cpp index 383deb2239..c131a139ac 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.cpp +++ b/interface/src/ui/overlays/Rectangle3DOverlay.cpp @@ -23,7 +23,7 @@ Rectangle3DOverlay::Rectangle3DOverlay() { Rectangle3DOverlay::~Rectangle3DOverlay() { } -void Rectangle3DOverlay::render() { +void Rectangle3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/Rectangle3DOverlay.h b/interface/src/ui/overlays/Rectangle3DOverlay.h index 367db8c4b7..9cec6da7e7 100644 --- a/interface/src/ui/overlays/Rectangle3DOverlay.h +++ b/interface/src/ui/overlays/Rectangle3DOverlay.h @@ -19,7 +19,7 @@ class Rectangle3DOverlay : public Planar3DOverlay { public: Rectangle3DOverlay(); ~Rectangle3DOverlay(); - virtual void render(); + virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); }; diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 7c162c7957..63ed3e8d7e 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -24,7 +24,7 @@ Sphere3DOverlay::Sphere3DOverlay() { Sphere3DOverlay::~Sphere3DOverlay() { } -void Sphere3DOverlay::render() { +void Sphere3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.h b/interface/src/ui/overlays/Sphere3DOverlay.h index 9a2816611b..98776a3f57 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.h +++ b/interface/src/ui/overlays/Sphere3DOverlay.h @@ -19,7 +19,7 @@ class Sphere3DOverlay : public Volume3DOverlay { public: Sphere3DOverlay(); ~Sphere3DOverlay(); - virtual void render(); + virtual void render(RenderArgs* args); }; diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index feb36943c3..d8febbf0eb 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -52,7 +52,7 @@ xColor Text3DOverlay::getBackgroundColor() { } -void Text3DOverlay::render() { +void Text3DOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/Text3DOverlay.h b/interface/src/ui/overlays/Text3DOverlay.h index c49116ee0c..45e311c554 100644 --- a/interface/src/ui/overlays/Text3DOverlay.h +++ b/interface/src/ui/overlays/Text3DOverlay.h @@ -15,6 +15,8 @@ #include "InterfaceConfig.h" #include + +#include #include "Planar3DOverlay.h" class Text3DOverlay : public Planar3DOverlay { @@ -23,7 +25,7 @@ class Text3DOverlay : public Planar3DOverlay { public: Text3DOverlay(); ~Text3DOverlay(); - virtual void render(); + virtual void render(RenderArgs* args); // getters const QString& getText() const { return _text; } diff --git a/interface/src/ui/overlays/TextOverlay.cpp b/interface/src/ui/overlays/TextOverlay.cpp index 89c6b1fe4f..530b30a856 100644 --- a/interface/src/ui/overlays/TextOverlay.cpp +++ b/interface/src/ui/overlays/TextOverlay.cpp @@ -48,7 +48,7 @@ xColor TextOverlay::getBackgroundColor() { } -void TextOverlay::render() { +void TextOverlay::render(RenderArgs* args) { if (!_visible) { return; // do nothing if we're not visible } diff --git a/interface/src/ui/overlays/TextOverlay.h b/interface/src/ui/overlays/TextOverlay.h index 0ef7d6b772..f7ff83e542 100644 --- a/interface/src/ui/overlays/TextOverlay.h +++ b/interface/src/ui/overlays/TextOverlay.h @@ -37,7 +37,7 @@ class TextOverlay : public Overlay2D { public: TextOverlay(); ~TextOverlay(); - virtual void render(); + virtual void render(RenderArgs* args); // getters const QString& getText() const { return _text; } diff --git a/libraries/octree/src/OctreeHeadlessViewer.h b/libraries/octree/src/OctreeHeadlessViewer.h index 8c08f6d214..03b8a204e0 100644 --- a/libraries/octree/src/OctreeHeadlessViewer.h +++ b/libraries/octree/src/OctreeHeadlessViewer.h @@ -33,7 +33,7 @@ public: virtual void renderElement(OctreeElement* element, RenderArgs* args) { /* swallow these */ } virtual void init(); - virtual void render(RenderMode renderMode = DEFAULT_RENDER_MODE) { /* swallow these */ } + virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE) { /* swallow these */ } void setJurisdictionListener(JurisdictionListener* jurisdictionListener) { _jurisdictionListener = jurisdictionListener; } diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index d6f3caef6c..a8aafbe34d 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -14,6 +14,7 @@ #include #include +#include #include "OctreeRenderer.h" OctreeRenderer::OctreeRenderer() : @@ -161,7 +162,7 @@ bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) { return false; } -void OctreeRenderer::render(RenderMode renderMode) { +void OctreeRenderer::render(RenderArgs::RenderMode renderMode) { RenderArgs args = { this, _viewFrustum, getSizeScale(), getBoundaryLevelAdjust(), renderMode, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; if (_tree) { diff --git a/libraries/octree/src/OctreeRenderer.h b/libraries/octree/src/OctreeRenderer.h index e37f20529f..d418467012 100644 --- a/libraries/octree/src/OctreeRenderer.h +++ b/libraries/octree/src/OctreeRenderer.h @@ -18,6 +18,7 @@ #include #include +#include #include #include "Octree.h" @@ -25,7 +26,6 @@ #include "ViewFrustum.h" class OctreeRenderer; -class RenderArgs; // Generic client side Octree renderer class. @@ -51,10 +51,8 @@ public: /// initialize and GPU/rendering related resources virtual void init(); - enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; - /// render the content of the octree - virtual void render(RenderMode renderMode = DEFAULT_RENDER_MODE); + virtual void render(RenderArgs::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE); ViewFrustum* getViewFrustum() const { return _viewFrustum; } void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; } @@ -104,31 +102,4 @@ protected: int _opaqueMeshPartsRendered; }; -class RenderArgs { -public: - OctreeRenderer* _renderer; - ViewFrustum* _viewFrustum; - float _sizeScale; - int _boundaryLevelAdjust; - OctreeRenderer::RenderMode _renderMode; - - int _elementsTouched; - int _itemsRendered; - int _itemsOutOfView; - int _itemsTooSmall; - - int _meshesConsidered; - int _meshesRendered; - int _meshesOutOfView; - int _meshesTooSmall; - - int _materialSwitches; - int _trianglesRendered; - int _quadsRendered; - - int _translucentMeshPartsRendered; - int _opaqueMeshPartsRendered; -}; - - #endif // hifi_OctreeRenderer_h diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h new file mode 100644 index 0000000000..1ed43f94ad --- /dev/null +++ b/libraries/shared/src/RenderArgs.h @@ -0,0 +1,46 @@ +// +// RenderArgs.h +// libraries/shared +// +// Created by Brad Hefta-Gaub on 10/29/14. +// Copyright 2013-2014 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 +// + +#ifndef hifi_RenderArgs_h +#define hifi_RenderArgs_h + +class ViewFrustum; +class OctreeRenderer; + +class RenderArgs { +public: + enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; + + OctreeRenderer* _renderer; + ViewFrustum* _viewFrustum; + float _sizeScale; + int _boundaryLevelAdjust; + RenderMode _renderMode; + + int _elementsTouched; + int _itemsRendered; + int _itemsOutOfView; + int _itemsTooSmall; + + int _meshesConsidered; + int _meshesRendered; + int _meshesOutOfView; + int _meshesTooSmall; + + int _materialSwitches; + int _trianglesRendered; + int _quadsRendered; + + int _translucentMeshPartsRendered; + int _opaqueMeshPartsRendered; +}; + +#endif // hifi_RenderArgs_h From 17a20ceb1685c868733dd50acde1286350ede7e7 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 29 Oct 2014 10:49:24 -0700 Subject: [PATCH 4/7] pass the submesh name as extraInfo in the ray pick result --- .../entities/RenderableModelEntityItem.cpp | 2 +- interface/src/renderer/Model.cpp | 26 ++-------- interface/src/renderer/Model.h | 2 +- interface/src/ui/overlays/Base3DOverlay.h | 5 ++ interface/src/ui/overlays/ModelOverlay.cpp | 48 +++++-------------- interface/src/ui/overlays/ModelOverlay.h | 2 + interface/src/ui/overlays/Overlays.cpp | 9 +++- interface/src/ui/overlays/Overlays.h | 2 + libraries/fbx/src/FBXReader.h | 3 -- 9 files changed, 32 insertions(+), 67 deletions(-) diff --git a/interface/src/entities/RenderableModelEntityItem.cpp b/interface/src/entities/RenderableModelEntityItem.cpp index ec4c5b4008..50bf947955 100644 --- a/interface/src/entities/RenderableModelEntityItem.cpp +++ b/interface/src/entities/RenderableModelEntityItem.cpp @@ -112,7 +112,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { } // TODO: should we allow entityItems to have alpha on their models? - Model::RenderMode modelRenderMode = args->_renderMode == OctreeRenderer::SHADOW_RENDER_MODE + Model::RenderMode modelRenderMode = args->_renderMode == RenderArgs::SHADOW_RENDER_MODE ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; if (_model->isActive()) { diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 823ac0cc7e..ffa8261c3c 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -395,27 +395,15 @@ void Model::setJointStates(QVector states) { } bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) const { + float& distance, BoxFace& face, QString& extraInfo) const { - //return false; - qDebug() << "Model::findRayIntersectionAgainstSubMeshes()..."; - bool intersectedSomething = false; // if we aren't active, we can't ray pick yet... if (!isActive()) { - qDebug() << " line:" << __LINE__ << " returning intersectedSomething:" << intersectedSomething; return intersectedSomething; } - // if we don't have valid mesh boxes, calculate them now. We cache the results of these calculations - // so long as the model hasn't been simulated and the mesh hasn't changed. - /* - if (!_calculatedMeshBoxesValid) { - recalcuateMeshBoxes(); - } - */ - // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = _translation; glm::mat4 rotation = glm::mat4_cast(_rotation); @@ -436,8 +424,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // and testing intersection there. if (overlayFrameBox.findRayIntersection(modelFrameOrigin, modelFrameDirection, distance, face)) { - qDebug() << " line:" << __LINE__ << " overlayFrameBox.findRayIntersection() TRUE consider sub meshes!"; - float bestDistance = std::numeric_limits::max(); float distanceToSubMesh; BoxFace subMeshFace; @@ -448,8 +434,6 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g // If we hit the models box, then consider the submeshes... foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { const FBXGeometry& geometry = _geometry->getFBXGeometry(); - //qDebug() << " consider sub mesh[" << subMeshIndex <<"] " - // << subMeshBox << "name:" << geometry.getModelNameOfMesh(subMeshIndex); if (subMeshBox.findRayIntersection(origin, direction, distanceToSubMesh, subMeshFace)) { if (distanceToSubMesh < bestDistance) { @@ -457,10 +441,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g bestDistance = distanceToSubMesh; bestSubMeshFace = subMeshFace; intersectedSomething = true; - qDebug() << " INTERSECTS sub mesh[" << subMeshIndex <<"] " - << subMeshBox - << "distance:" << distanceToSubMesh - << "name:" << geometry.getModelNameOfMesh(subMeshIndex); + extraInfo = geometry.getModelNameOfMesh(subMeshIndex); } } subMeshIndex++; @@ -501,7 +482,7 @@ bool Model::render(float alpha, RenderMode mode, RenderArgs* args) { // where our caller has passed RenderArgs which will include a view frustum we can cull // against. We cache the results of these calculations so long as the model hasn't been // simulated and the mesh hasn't changed. - if (/*args &&*/ !_calculatedMeshBoxesValid) { + if (args && !_calculatedMeshBoxesValid) { recalcuateMeshBoxes(); } @@ -1013,7 +994,6 @@ void Model::simulate(float deltaTime, bool fullUpdate) { || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); if (isActive() && fullUpdate) { - //qDebug() << "simulated _calculatedMeshBoxesValid = false"; _calculatedMeshBoxesValid = false; // if we have to simulate, we need to assume our mesh boxes are all invalid // check for scale to fit diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 75a4e4776a..d25273cfe7 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -191,7 +191,7 @@ public: { _geometry->setTextureWithNameToURL(name, url); } bool findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, - float& distance, BoxFace& face) const; + float& distance, BoxFace& face, QString& extraInfo) const; protected: QSharedPointer _geometry; diff --git a/interface/src/ui/overlays/Base3DOverlay.h b/interface/src/ui/overlays/Base3DOverlay.h index fa750e4fe7..75ce6b303d 100644 --- a/interface/src/ui/overlays/Base3DOverlay.h +++ b/interface/src/ui/overlays/Base3DOverlay.h @@ -48,6 +48,11 @@ public: virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, + float& distance, BoxFace& face, QString& extraInfo) const { + return findRayIntersection(origin, direction, distance, face); + } + protected: void drawDashedLine(const glm::vec3& start, const glm::vec3& end); diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 94ed11c9cb..1d28de8646 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -26,8 +26,6 @@ void ModelOverlay::update(float deltatime) { _updateModel = false; _model.setScaleToFit(true, _scale); -qDebug() << "setScaleToFit() scale: " << _scale; - _model.setSnapModelToCenter(true); _model.setRotation(_rotation); _model.setTranslation(_position); @@ -51,7 +49,7 @@ void ModelOverlay::render(RenderArgs* args) { if (glowLevel > 0.0f) { glower = new Glower(glowLevel); } - _model.render(getAlpha()); + _model.render(getAlpha(), Model::DEFAULT_RENDER_MODE, args); if (glower) { delete glower; } @@ -72,7 +70,6 @@ void ModelOverlay::setProperties(const QScriptValue &properties) { QScriptValue scaleValue = properties.property("scale"); if (scaleValue.isValid()) { _scale = scaleValue.toVariant().toFloat(); -qDebug() << "scale: " << _scale; _updateModel = true; } @@ -127,38 +124,15 @@ qDebug() << "scale: " << _scale; bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const { - - qDebug() << "ModelOverlay::findRayIntersection() calling _model.findRayIntersectionAgainstSubMeshes()..."; - return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face); - /* - // if our model isn't active, we can't ray pick yet... - if (!_model.isActive()) { - return false; - } - - // extents is the entity relative, scaled, centered extents of the entity - glm::vec3 position = getPosition(); - glm::mat4 rotation = glm::mat4_cast(getRotation()); - glm::mat4 translation = glm::translate(position); - glm::mat4 entityToWorldMatrix = translation * rotation; - glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix); - - Extents modelExtents = _model.getMeshExtents(); // NOTE: unrotated - - glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; - glm::vec3 corner = dimensions * -0.5f; // since we're going to do the ray picking in the overlay frame of reference - AABox overlayFrameBox(corner, dimensions); - - glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f)); - glm::vec3 overlayFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)); - - // we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame - // and testing intersection there. - if (overlayFrameBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, distance, face)) { - return true; - } - - return false; - */ + QString subMeshNameTemp; + return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, subMeshNameTemp); } + +bool ModelOverlay::findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, + float& distance, BoxFace& face, QString& extraInfo) const { + + return _model.findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo); +} + + diff --git a/interface/src/ui/overlays/ModelOverlay.h b/interface/src/ui/overlays/ModelOverlay.h index 71ac4c8b19..26471a79e1 100644 --- a/interface/src/ui/overlays/ModelOverlay.h +++ b/interface/src/ui/overlays/ModelOverlay.h @@ -25,6 +25,8 @@ public: virtual void render(RenderArgs* args); virtual void setProperties(const QScriptValue& properties); virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face) const; + virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction, + float& distance, BoxFace& face, QString& extraInfo) const; private: diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 67be69c9ed..8ad8a561e5 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -250,7 +250,8 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) if (thisOverlay->getVisible() && !thisOverlay->getIgnoreRayIntersection() && thisOverlay->isLoaded()) { float thisDistance; BoxFace thisFace; - if (thisOverlay->findRayIntersection(ray.origin, ray.direction, thisDistance, thisFace)) { + QString thisExtraInfo; + if (thisOverlay->findRayIntersectionExtraInfo(ray.origin, ray.direction, thisDistance, thisFace, thisExtraInfo)) { if (thisDistance < bestDistance) { bestDistance = thisDistance; result.intersects = true; @@ -258,6 +259,7 @@ RayToOverlayIntersectionResult Overlays::findRayIntersection(const PickRay& ray) result.face = thisFace; result.overlayID = thisID; result.intersection = ray.origin + (ray.direction * thisDistance); + result.extraInfo = thisExtraInfo; } } } @@ -270,7 +272,8 @@ RayToOverlayIntersectionResult::RayToOverlayIntersectionResult() : overlayID(-1), distance(0), face(), - intersection() + intersection(), + extraInfo() { } @@ -309,6 +312,7 @@ QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, obj.setProperty("face", faceName); QScriptValue intersection = vec3toScriptValue(engine, value.intersection); obj.setProperty("intersection", intersection); + obj.setProperty("extraInfo", value.extraInfo); return obj; } @@ -337,6 +341,7 @@ void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, R if (intersection.isValid()) { vec3FromScriptValue(intersection, value.intersection); } + value.extraInfo = object.property("extraInfo").toVariant().toString(); } bool Overlays::isLoaded(unsigned int id) { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 4851b1f9dc..64bccc2e5a 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -11,6 +11,7 @@ #ifndef hifi_Overlays_h #define hifi_Overlays_h +#include #include #include "Overlay.h" @@ -23,6 +24,7 @@ public: float distance; BoxFace face; glm::vec3 intersection; + QString extraInfo; }; Q_DECLARE_METATYPE(RayToOverlayIntersectionResult); diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 173c9336c4..797f0e9558 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -143,9 +143,6 @@ public: QVector blendshapes; bool hasSpecularTexture() const; - - //QString name; - //int foo; }; /// A single animation frame extracted from an FBX document. From f1326e91b9893a04063686aa8823b7dddf72ffdc Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 29 Oct 2014 11:10:52 -0700 Subject: [PATCH 5/7] move the _model.setScaleToFit( largest dimension) to the setProperties not update --- interface/src/ui/overlays/ModelOverlay.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 1d28de8646..150d40f15a 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -25,7 +25,6 @@ void ModelOverlay::update(float deltatime) { if (_updateModel) { _updateModel = false; - _model.setScaleToFit(true, _scale); _model.setSnapModelToCenter(true); _model.setRotation(_rotation); _model.setTranslation(_position); @@ -70,6 +69,7 @@ void ModelOverlay::setProperties(const QScriptValue &properties) { QScriptValue scaleValue = properties.property("scale"); if (scaleValue.isValid()) { _scale = scaleValue.toVariant().toFloat(); + _model.setScaleToFit(true, _scale); _updateModel = true; } From 0696bd39f5aa91542fb5d9a00dbf29b5bda4c1ad Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 29 Oct 2014 11:39:23 -0700 Subject: [PATCH 6/7] added example script for lobby model overlays --- examples/testModelOverlaySubMeshes.js | 87 +++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 examples/testModelOverlaySubMeshes.js diff --git a/examples/testModelOverlaySubMeshes.js b/examples/testModelOverlaySubMeshes.js new file mode 100644 index 0000000000..5195b76e60 --- /dev/null +++ b/examples/testModelOverlaySubMeshes.js @@ -0,0 +1,87 @@ +var position = Vec3.sum(MyAvatar.position, { x: 0, y: -1, z: 0}); + +var scalingFactor = 0.01; + +var sphereNaturalExtentsMin = { x: -1230, y: -1223, z: -1210 }; +var sphereNaturalExtentsMax = { x: 1230, y: 1229, z: 1223 }; +var panelsNaturalExtentsMin = { x: -1181, y: -326, z: 56 }; +var panelsNaturalExtentsMax = { x: 1181, y: 576, z: 1183 }; + +var sphereNaturalDimensions = Vec3.subtract(sphereNaturalExtentsMax, sphereNaturalExtentsMin); +var panelsNaturalDimensions = Vec3.subtract(panelsNaturalExtentsMax, panelsNaturalExtentsMin); +Vec3.print("sphereNaturalDimensions:", sphereNaturalDimensions); +Vec3.print("panelsNaturalDimensions:", panelsNaturalDimensions); + +var sphereNaturalCenter = Vec3.sum(sphereNaturalExtentsMin, Vec3.multiply(sphereNaturalDimensions, 0.5)); +var panelsNaturalCenter = Vec3.sum(panelsNaturalExtentsMin, Vec3.multiply(panelsNaturalDimensions, 0.5)); +Vec3.print("sphereNaturalCenter:", sphereNaturalCenter); +Vec3.print("panelsNaturalCenter:", panelsNaturalCenter); + +var sphereDimensions = Vec3.multiply(sphereNaturalDimensions, scalingFactor); +var panelsDimensions = Vec3.multiply(panelsNaturalDimensions, scalingFactor); +Vec3.print("sphereDimensions:", sphereDimensions); +Vec3.print("panelsDimensions:", panelsDimensions); + +var sphereCenter = Vec3.multiply(sphereNaturalCenter, scalingFactor); +var panelsCenter = Vec3.multiply(panelsNaturalCenter, scalingFactor); +Vec3.print("sphereCenter:", sphereCenter); +Vec3.print("panelsCenter:", panelsCenter); + +var centerShift = Vec3.subtract(panelsCenter, sphereCenter); +Vec3.print("centerShift:", centerShift); + +var spherePosition = position; +Vec3.print("spherePosition:", spherePosition); +var panelsPosition = Vec3.sum(spherePosition, centerShift); +Vec3.print("panelsPosition:", panelsPosition); + + +var screensOverlay = Overlays.addOverlay("model", { + position: panelsPosition, + dimensions: panelsDimensions, + url: "https://s3.amazonaws.com/hifi-public/models/sets/Lobby/LobbyConcepts/Lobby5_IsolatedPanelsFreezeTransforms.fbx" + }); + + +var structureOverlay = Overlays.addOverlay("model", { + position: spherePosition, + dimensions: sphereDimensions, + url: "https://s3.amazonaws.com/hifi-public/models/sets/Lobby/LobbyConcepts/Lobby5_OrbShellOnly.fbx", + ignoreRayIntersection: true, // we don't want to ray pick against any of this + }); + +var statusText = Overlays.addOverlay("text", { + x: 200, + y: 100, + width: 200, + height: 20, + backgroundColor: { red: 0, green: 0, blue: 0}, + alpha: 1.0, + color: { red: 255, green: 255, blue: 255}, + topMargin: 4, + leftMargin: 4, + text: "", + }); + + +Controller.mouseMoveEvent.connect(function(event){ + var pickRay = Camera.computePickRay(event.x, event.y); + var result = Overlays.findRayIntersection(pickRay); + + if (result.intersects) { + if (result.overlayID == screensOverlay) { + Overlays.editOverlay(statusText, { text: "You are pointing at: " + result.extraInfo }); + } else { + Overlays.editOverlay(statusText, { text: "You are not pointing at a panel..." }); + } + } else { + Overlays.editOverlay(statusText, { text: "You are not pointing at a panel..." }); + } +}); + + +Script.scriptEnding.connect(function(){ + Overlays.deleteOverlay(screensOverlay); + Overlays.deleteOverlay(structureOverlay); + Overlays.deleteOverlay(statusText); +}); From ac3a963eca78f064c472b6fa5b0f74d6ff58e490 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 29 Oct 2014 12:01:43 -0700 Subject: [PATCH 7/7] fix build buster --- interface/src/renderer/Model.cpp | 88 +++++++++++++++++++++----------- interface/src/renderer/Model.h | 2 +- 2 files changed, 60 insertions(+), 30 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index a934a2a79f..fc99970fea 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -35,6 +35,7 @@ using namespace std; static int modelPointerTypeId = qRegisterMetaType >(); static int weakNetworkGeometryPointerTypeId = qRegisterMetaType >(); static int vec3VectorTypeId = qRegisterMetaType >(); +float Model::FAKE_DIMENSION_PLACEHOLDER = -1.0f; Model::Model(QObject* parent) : QObject(parent), @@ -123,35 +124,64 @@ void Model::setOffset(const glm::vec3& offset) { void Model::initProgram(ProgramObject& program, Model::Locations& locations, int specularTextureUnit) { program.bind(); -#ifdef Q_OS_MAC - // HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite - glBindAttribLocation(program.programId(), 4, "tangent"); - glLinkProgram(program.programId()); -#endif - - locations.tangent = program.attributeLocation("tangent"); - locations.alphaThreshold = program.uniformLocation("alphaThreshold"); - program.setUniformValue("diffuseMap", 0); - program.setUniformValue("normalMap", 1); - program.setUniformValue("specularMap", specularTextureUnit); - program.release(); -} - -void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations, int specularTextureUnit) { - initProgram(program, locations, specularTextureUnit); - -#ifdef Q_OS_MAC - // HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite - glBindAttribLocation(program.programId(), 5, "clusterIndices"); - glBindAttribLocation(program.programId(), 6, "clusterWeights"); - glLinkProgram(program.programId()); -#endif - - program.bind(); - locations.clusterMatrices = program.uniformLocation("clusterMatrices"); - - locations.clusterIndices = program.attributeLocation("clusterIndices"); - locations.clusterWeights = program.attributeLocation("clusterWeights"); +#ifdef Q_OS_MAC + + // HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite + + glBindAttribLocation(program.programId(), 4, "tangent"); + + glLinkProgram(program.programId()); + +#endif + + + + locations.tangent = program.attributeLocation("tangent"); + + locations.alphaThreshold = program.uniformLocation("alphaThreshold"); + + program.setUniformValue("diffuseMap", 0); + + program.setUniformValue("normalMap", 1); + + program.setUniformValue("specularMap", specularTextureUnit); + + program.release(); + +} + + + +void Model::initSkinProgram(ProgramObject& program, Model::SkinLocations& locations, int specularTextureUnit) { + + initProgram(program, locations, specularTextureUnit); + + + +#ifdef Q_OS_MAC + + // HACK: Assign explicitely the attribute channel to avoid a bug on Yosemite + + glBindAttribLocation(program.programId(), 5, "clusterIndices"); + + glBindAttribLocation(program.programId(), 6, "clusterWeights"); + + glLinkProgram(program.programId()); + +#endif + + + + program.bind(); + + locations.clusterMatrices = program.uniformLocation("clusterMatrices"); + + + + locations.clusterIndices = program.attributeLocation("clusterIndices"); + + locations.clusterWeights = program.attributeLocation("clusterWeights"); + program.release(); } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index d25273cfe7..9892a12c9d 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -199,7 +199,7 @@ protected: glm::vec3 _scale; glm::vec3 _offset; - const float FAKE_DIMENSION_PLACEHOLDER = -1.0f; + static float FAKE_DIMENSION_PLACEHOLDER; bool _scaleToFit; /// If you set scaleToFit, we will calculate scale based on MeshExtents glm::vec3 _scaleToFitDimensions; /// this is the dimensions that scale to fit will use