From d6322903a2c39fc9e693e866218b06027053b74b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 11 Aug 2015 10:12:46 -0700 Subject: [PATCH 01/47] quiet compiler --- libraries/entities/src/EntityItemProperties.h | 2 +- libraries/entities/src/PolyLineEntityItem.cpp | 5 +- libraries/fbx/src/FBXReader.cpp | 22 +- libraries/render-utils/src/Model.cpp | 202 ++++++++---------- 4 files changed, 107 insertions(+), 124 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 8085c24d90..e7c280686a 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -154,9 +154,9 @@ public: DEFINE_PROPERTY_REF(PROP_HREF, Href, href, QString); DEFINE_PROPERTY_REF(PROP_DESCRIPTION, Description, description, QString); DEFINE_PROPERTY(PROP_FACE_CAMERA, FaceCamera, faceCamera, bool); + DEFINE_PROPERTY_REF(PROP_ACTION_DATA, ActionData, actionData, QByteArray); DEFINE_PROPERTY(PROP_NORMALS, Normals, normals, QVector); DEFINE_PROPERTY(PROP_STROKE_WIDTHS, StrokeWidths, strokeWidths, QVector); - DEFINE_PROPERTY_REF(PROP_ACTION_DATA, ActionData, actionData, QByteArray); DEFINE_PROPERTY_REF(PROP_X_TEXTURE_URL, XTextureURL, xTextureURL, QString); DEFINE_PROPERTY_REF(PROP_Y_TEXTURE_URL, YTextureURL, yTextureURL, QString); DEFINE_PROPERTY_REF(PROP_Z_TEXTURE_URL, ZTextureURL, zTextureURL, QString); diff --git a/libraries/entities/src/PolyLineEntityItem.cpp b/libraries/entities/src/PolyLineEntityItem.cpp index 9ade80f3be..196fde47fb 100644 --- a/libraries/entities/src/PolyLineEntityItem.cpp +++ b/libraries/entities/src/PolyLineEntityItem.cpp @@ -170,9 +170,10 @@ bool PolyLineEntityItem::setLinePoints(const QVector& points) { for (int i = 0; i < points.size(); i++) { glm::vec3 point = points.at(i); - glm::vec3 pos = getPosition(); glm::vec3 halfBox = getDimensions() * 0.5f; - if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) { + if ((point.x < - halfBox.x || point.x > halfBox.x) || + (point.y < -halfBox.y || point.y > halfBox.y) || + (point.z < - halfBox.z || point.z > halfBox.z)) { qDebug() << "Point is outside entity's bounding box"; return false; } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 5e7647263a..ebffa4410a 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -976,7 +976,7 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) { data.extracted.mesh.meshIndex = meshIndex++; QVector materials; QVector textures; - bool isMaterialPerPolygon = false; + // bool isMaterialPerPolygon = false; foreach (const FBXNode& child, object.children) { if (child.name == "Vertices") { @@ -1107,13 +1107,13 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) { foreach (const FBXNode& subdata, child.children) { if (subdata.name == "Materials") { materials = getIntVector(subdata); - } else if (subdata.name == "MappingInformationType") { - if (subdata.properties.at(0) == "ByPolygon") { - isMaterialPerPolygon = true; - } else { - isMaterialPerPolygon = false; - } - } + } // else if (subdata.name == "MappingInformationType") { + // if (subdata.properties.at(0) == "ByPolygon") + // isMaterialPerPolygon = true; + // } else { + // isMaterialPerPolygon = false; + // } + // } } @@ -1126,12 +1126,6 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) { } } - - bool isMultiMaterial = false; - if (isMaterialPerPolygon) { - isMultiMaterial = true; - } - // convert the polygons to quads and triangles int polygonIndex = 0; QHash, int> materialTextureParts; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 3080d965a1..8a9a3f68dc 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -112,14 +112,14 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader)); gpu::Shader::makeProgram(*program, slotBindings); - - + + auto locations = std::make_shared(); initLocations(program, *locations); - + auto state = std::make_shared(); - + // Backface on shadow if (key.isShadow()) { state->setCullMode(gpu::State::CULL_FRONT); @@ -140,36 +140,36 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, // Good to go add the brand new pipeline auto pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); insert(value_type(key.getRaw(), RenderPipeline(pipeline, locations))); - - + + if (!key.isWireFrame()) { - + RenderKey wireframeKey(key.getRaw() | RenderKey::IS_WIREFRAME); auto wireframeState = std::make_shared(state->getValues()); - + wireframeState->setFillMode(gpu::State::FILL_LINE); - + // create a new RenderPipeline with the same shader side and the mirrorState auto wireframePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, wireframeState)); insert(value_type(wireframeKey.getRaw(), RenderPipeline(wireframePipeline, locations))); } - + // If not a shadow pass, create the mirror version from the same state, just change the FrontFace if (!key.isShadow()) { - + RenderKey mirrorKey(key.getRaw() | RenderKey::IS_MIRROR); auto mirrorState = std::make_shared(state->getValues()); // create a new RenderPipeline with the same shader side and the mirrorState auto mirrorPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, mirrorState)); insert(value_type(mirrorKey.getRaw(), RenderPipeline(mirrorPipeline, locations))); - + if (!key.isWireFrame()) { RenderKey wireframeKey(key.getRaw() | RenderKey::IS_MIRROR | RenderKey::IS_WIREFRAME); auto wireframeState = std::make_shared(state->getValues()); - + wireframeState->setFillMode(gpu::State::FILL_LINE); - + // create a new RenderPipeline with the same shader side and the mirrorState auto wireframePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, wireframeState)); insert(value_type(wireframeKey.getRaw(), RenderPipeline(wireframePipeline, locations))); @@ -214,12 +214,12 @@ void Model::setScaleInternal(const glm::vec3& scale) { } } -void Model::setOffset(const glm::vec3& offset) { - _offset = offset; - +void Model::setOffset(const glm::vec3& offset) { + _offset = offset; + // if someone manually sets our offset, then we are no longer snapped to center - _snapModelToRegistrationPoint = false; - _snappedToRegistrationPoint = false; + _snapModelToRegistrationPoint = false; + _snappedToRegistrationPoint = false; } QVector Model::createJointStates(const FBXGeometry& geometry) { @@ -267,7 +267,7 @@ void Model::init() { auto modelLightmapNormalSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag))); // Fill the renderPipelineLib - + _renderPipelineLib.addRenderPipeline( RenderKey(0), modelVertex, modelPixel); @@ -284,7 +284,7 @@ void Model::init() { RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), modelNormalMapVertex, modelNormalSpecularMapPixel); - + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_TRANSLUCENT), modelVertex, modelTranslucentPixel); @@ -292,7 +292,7 @@ void Model::init() { _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_TRANSLUCENT | RenderKey::HAS_LIGHTMAP), modelVertex, modelTranslucentPixel); - + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::HAS_TANGENTS | RenderKey::IS_TRANSLUCENT), modelNormalMapVertex, modelTranslucentPixel); @@ -440,15 +440,15 @@ bool Model::updateGeometry() { } _geometry->setLoadPriority(this, -_lodDistance); _geometry->ensureLoading(); - + if (needToRebuild) { const FBXGeometry& fbxGeometry = geometry->getFBXGeometry(); foreach (const FBXMesh& mesh, fbxGeometry.meshes) { MeshState state; state.clusterMatrices.resize(mesh.clusters.size()); state.cauterizedClusterMatrices.resize(mesh.clusters.size()); - _meshStates.append(state); - + _meshStates.append(state); + auto buffer = std::make_shared(); if (!mesh.blendshapes.isEmpty()) { buffer->resize((mesh.vertices.size() + mesh.normals.size()) * sizeof(glm::vec3)); @@ -486,7 +486,7 @@ void Model::initJointStates(QVector states) { rightShoulderJointIndex); } -bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, +bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face, QString& extraInfo, bool pickAgainstTriangles) { bool intersectedSomething = false; @@ -495,7 +495,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g if (!isActive()) { return intersectedSomething; } - + // extents is the entity relative, scaled, centered extents of the entity glm::vec3 position = _translation; glm::mat4 rotation = glm::mat4_cast(_rotation); @@ -504,7 +504,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g glm::mat4 worldToModelMatrix = glm::inverse(modelToWorldMatrix); Extents modelExtents = getMeshExtents(); // NOTE: unrotated - + glm::vec3 dimensions = modelExtents.maximum - modelExtents.minimum; glm::vec3 corner = -(dimensions * _registrationPoint); // since we're going to do the ray picking in the model frame of reference AABox modelFrameBox(corner, dimensions); @@ -543,7 +543,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g int t = 0; foreach (const Triangle& triangle, meshTriangles) { t++; - + float thisTriangleDistance; if (findRayTriangleIntersection(origin, direction, triangle, thisTriangleDistance)) { if (thisTriangleDistance < bestDistance) { @@ -562,7 +562,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g extraInfo = geometry.getModelNameOfMesh(subMeshIndex); } } - } + } subMeshIndex++; } _mutex.unlock(); @@ -570,7 +570,7 @@ bool Model::findRayIntersectionAgainstSubMeshes(const glm::vec3& origin, const g if (intersectedSomething) { distance = bestDistance; } - + return intersectedSomething; } @@ -582,22 +582,22 @@ bool Model::convexHullContains(glm::vec3 point) { if (!isActive()) { return false; } - + // 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 * _registrationPoint); AABox modelFrameBox(corner, dimensions); - + glm::vec3 modelFramePoint = glm::vec3(worldToModelMatrix * glm::vec4(point, 1.0f)); - + // we can use the AABox's contains() by mapping our point into the model frame // and testing there. if (modelFrameBox.contains(modelFramePoint)){ @@ -605,7 +605,7 @@ bool Model::convexHullContains(glm::vec3 point) { if (!_calculatedMeshTrianglesValid) { recalculateMeshBoxes(true); } - + // If we are inside the models box, then consider the submeshes... int subMeshIndex = 0; foreach(const AABox& subMeshBox, _calculatedMeshBoxes) { @@ -619,7 +619,7 @@ bool Model::convexHullContains(glm::vec3 point) { insideMesh = false; break; } - + } if (insideMesh) { // It's inside this mesh, return true. @@ -658,7 +658,7 @@ void Model::recalculateMeshPartOffsets() { // Any script might trigger findRayIntersectionAgainstSubMeshes (and maybe convexHullContains), so these // can occur multiple times. In addition, rendering does it's own ray picking in order to decide which // entity-scripts to call. I think it would be best to do the picking once-per-frame (in cpu, or gpu if possible) -// and then the calls use the most recent such result. +// and then the calls use the most recent such result. void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { PROFILE_RANGE(__FUNCTION__); bool calculatedMeshTrianglesNeeded = pickAgainstTriangles && !_calculatedMeshTrianglesValid; @@ -703,7 +703,7 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { glm::vec3 mv1 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i1], 1.0f)); glm::vec3 mv2 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i2], 1.0f)); glm::vec3 mv3 = glm::vec3(mesh.modelTransform * glm::vec4(mesh.vertices[i3], 1.0f)); - + // track the mesh parts in model space if (!atLeastOnePointInBounds) { thisPartBounds.setBox(mv0, 0.0f); @@ -719,18 +719,18 @@ void Model::recalculateMeshBoxes(bool pickAgainstTriangles) { glm::vec3 v1 = calculateScaledOffsetPoint(mv1); glm::vec3 v2 = calculateScaledOffsetPoint(mv2); glm::vec3 v3 = calculateScaledOffsetPoint(mv3); - + // Sam's recommended triangle slices Triangle tri1 = { v0, v1, v3 }; Triangle tri2 = { v1, v2, v3 }; - + // NOTE: Random guy on the internet's recommended triangle slices //Triangle tri1 = { v0, v1, v2 }; //Triangle tri2 = { v2, v3, v0 }; - + thisMeshTriangles.push_back(tri1); thisMeshTriangles.push_back(tri2); - + } } @@ -792,7 +792,7 @@ void Model::renderSetup(RenderArgs* args) { _dilatedTextures.append(dilated); } } - + if (!_meshGroupsKnown && isLoaded()) { segregateMeshGroups(); } @@ -805,7 +805,7 @@ public: transparent(transparent), model(model), url(model->getURL()), meshIndex(meshIndex), partIndex(partIndex) { } typedef render::Payload Payload; typedef Payload::DataPointer Pointer; - + bool transparent; Model* model; QUrl url; @@ -814,14 +814,14 @@ public: }; namespace render { - template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload) { + template <> const ItemKey payloadGetKey(const MeshPartPayload::Pointer& payload) { if (!payload->model->isVisible()) { return ItemKey::Builder().withInvisible().build(); } return payload->transparent ? ItemKey::Builder::transparentShape() : ItemKey::Builder::opaqueShape(); } - - template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) { + + template <> const Item::Bound payloadGetBound(const MeshPartPayload::Pointer& payload) { if (payload) { return payload->model->getPartBounds(payload->meshIndex, payload->partIndex); } @@ -875,7 +875,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan _renderItems.insert(item, renderPayload); somethingAdded = true; } - + _readyWhenAdded = readyToAddToScene(); return somethingAdded; @@ -907,7 +907,7 @@ bool Model::addToScene(std::shared_ptr scene, render::PendingChan _renderItems.insert(item, renderPayload); somethingAdded = true; } - + _readyWhenAdded = readyToAddToScene(); return somethingAdded; @@ -929,7 +929,7 @@ void Model::renderDebugMeshBoxes(gpu::Batch& batch) { _debugMeshBoxesID = DependencyManager::get()->allocateID(); } QVector points; - + glm::vec3 brn = box.getCorner(); glm::vec3 bln = brn + glm::vec3(box.getDimensions().x, 0, 0); glm::vec3 brf = brn + glm::vec3(0, 0, box.getDimensions().z); @@ -963,12 +963,12 @@ void Model::renderDebugMeshBoxes(gpu::Batch& batch) { { 1.0f, 1.0f, 0.0f, 1.0f }, // yellow { 0.0f, 1.0f, 1.0f, 1.0f }, // cyan { 1.0f, 1.0f, 1.0f, 1.0f }, // white - { 0.0f, 0.5f, 0.0f, 1.0f }, - { 0.0f, 0.0f, 0.5f, 1.0f }, - { 0.5f, 0.0f, 0.5f, 1.0f }, - { 0.5f, 0.5f, 0.0f, 1.0f }, + { 0.0f, 0.5f, 0.0f, 1.0f }, + { 0.0f, 0.0f, 0.5f, 1.0f }, + { 0.5f, 0.0f, 0.5f, 1.0f }, + { 0.5f, 0.5f, 0.0f, 1.0f }, { 0.0f, 0.5f, 0.5f, 1.0f } }; - + DependencyManager::get()->updateVertices(_debugMeshBoxesID, points, color[colorNdx]); DependencyManager::get()->renderVertices(batch, gpu::LINES, _debugMeshBoxesID); colorNdx++; @@ -1003,7 +1003,7 @@ Extents Model::getUnscaledMeshExtents() const { if (!isActive()) { return Extents(); } - + const Extents& extents = _geometry->getFBXGeometry().meshExtents; // even though our caller asked for "unscaled" we need to include any fst scaling, translation, and rotation, which @@ -1011,7 +1011,7 @@ Extents Model::getUnscaledMeshExtents() const { glm::vec3 minimum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0f)); glm::vec3 maximum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0f)); Extents scaledExtents = { minimum, maximum }; - + return scaledExtents; } @@ -1020,12 +1020,12 @@ Extents Model::calculateScaledOffsetExtents(const Extents& extents) const { glm::vec3 minimum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0f)); glm::vec3 maximum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0f)); - Extents scaledOffsetExtents = { ((minimum + _offset) * _scale), + Extents scaledOffsetExtents = { ((minimum + _offset) * _scale), ((maximum + _offset) * _scale) }; Extents rotatedExtents = scaledOffsetExtents.getRotated(_rotation); - Extents translatedExtents = { rotatedExtents.minimum + _translation, + Extents translatedExtents = { rotatedExtents.minimum + _translation, rotatedExtents.maximum + _translation }; return translatedExtents; @@ -1084,7 +1084,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo onInvalidate(); - // if so instructed, keep the current geometry until the new one is loaded + // if so instructed, keep the current geometry until the new one is loaded _nextGeometry = DependencyManager::get()->getGeometry(url, fallback, delayLoad); _nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS; if (!retainCurrent || !isActive() || (_nextGeometry && _nextGeometry->isLoaded())) { @@ -1094,14 +1094,14 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo void Model::geometryRefreshed() { QObject* sender = QObject::sender(); - + if (sender == _geometry) { _readyWhenAdded = false; // reset out render items. _needsReload = true; invalidCalculatedMeshBoxes(); - + onInvalidate(); - + // if so instructed, keep the current geometry until the new one is loaded _nextGeometry = DependencyManager::get()->getGeometry(_url); _nextLODHysteresis = NetworkGeometry::NO_HYSTERESIS; @@ -1121,7 +1121,7 @@ const QSharedPointer Model::getCollisionGeometry(bool delayLoad if (_collisionGeometry && _collisionGeometry->isLoaded()) { return _collisionGeometry; } - + return QSharedPointer(); } @@ -1176,11 +1176,11 @@ public: Blender(Model* model, int blendNumber, const QWeakPointer& geometry, const QVector& meshes, const QVector& blendshapeCoefficients); - + virtual void run(); private: - + QPointer _model; int _blendNumber; QWeakPointer _geometry; @@ -1254,10 +1254,10 @@ void Model::setScaleToFit(bool scaleToFit, float largestDimension, bool forceRes } return; } - + if (forceRescale || _scaleToFit != scaleToFit || glm::length(_scaleToFitDimensions) != largestDimension) { _scaleToFit = scaleToFit; - + // we only need to do this work if we're "turning on" scale to fit. if (scaleToFit) { Extents modelMeshExtents = getUnscaledMeshExtents(); @@ -1278,7 +1278,7 @@ void Model::scaleToFit() { // 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 + if (_scaleToFit && _scaleToFitDimensions.y == FAKE_DIMENSION_PLACEHOLDER && _scaleToFitDimensions.z == FAKE_DIMENSION_PLACEHOLDER) { setScaleToFit(_scaleToFit, _scaleToFitDimensions.x); } @@ -1313,7 +1313,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) { PROFILE_RANGE(__FUNCTION__); fullUpdate = updateGeometry() || fullUpdate || (_scaleToFit && !_scaledToFit) || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); - + if (isActive() && fullUpdate) { // NOTE: This is overly aggressive and we are invalidating the MeshBoxes when in fact they may not be invalid // they really only become invalid if something about the transform to world space has changed. This is @@ -1440,7 +1440,7 @@ void Model::setBlendedVertices(int blendNumber, const QWeakPointergetFBXGeometry(); + const FBXGeometry& fbxGeometry = _geometry->getFBXGeometry(); int index = 0; for (int i = 0; i < fbxGeometry.meshes.size(); i++) { const FBXMesh& mesh = fbxGeometry.meshes.at(i); @@ -1461,7 +1461,7 @@ void Model::setGeometry(const QSharedPointer& newGeometry) { if (_geometry == newGeometry) { return; } - + if (_geometry) { _geometry->disconnect(_geometry.data(), &Resource::onRefresh, this, &Model::geometryRefreshed); } @@ -1474,10 +1474,10 @@ void Model::applyNextGeometry() { deleteGeometry(); _dilatedTextures.clear(); _lodHysteresis = _nextLODHysteresis; - + // we retain a reference to the base geometry so that its reference count doesn't fall to zero setGeometry(_nextGeometry); - + _meshGroupsKnown = false; _readyWhenAdded = false; // in case any of our users are using scenes _needsReload = false; // we are loaded now! @@ -1509,9 +1509,9 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) { return calculateScaledOffsetAABox(_geometry->getFBXGeometry().meshExtents); } } - + if (_geometry->getFBXGeometry().meshes.size() > meshIndex) { - + // FIX ME! - This is currently a hack because for some mesh parts our efforts to calculate the bounding // box of the mesh part fails. It seems to create boxes that are not consistent with where the // geometry actually renders. If instead we make all the parts share the bounds of the entire subMesh @@ -1536,7 +1536,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran if (!_readyWhenAdded) { return; // bail asap } - + // We need to make sure we have valid offsets calculated before we can render if (!_calculatedMeshPartOffsetValid) { _mutex.lock(); @@ -1561,13 +1561,13 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran // guard against partially loaded meshes if (meshIndex >= networkMeshes.size() || meshIndex >= geometry.meshes.size() || meshIndex >= _meshStates.size() ) { - return; + return; } const NetworkMesh& networkMesh = networkMeshes.at(meshIndex); const FBXMesh& mesh = geometry.meshes.at(meshIndex); const MeshState& state = _meshStates.at(meshIndex); - + bool translucentMesh = translucent; // networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); bool hasTangents = !mesh.tangents.isEmpty(); bool hasSpecular = mesh.hasSpecularTexture(); @@ -1597,7 +1597,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran DependencyManager::get()->renderWireCube(batch, 1.0f, cubeColor); } #endif //def DEBUG_BOUNDING_PARTS - + if (wireframe) { translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; } @@ -1614,14 +1614,14 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown // to false to rebuild out mesh groups. - + if (meshIndex < 0 || meshIndex >= networkMeshes.size() || meshIndex > geometry.meshes.size()) { _meshGroupsKnown = false; // regenerate these lists next time around. _readyWhenAdded = false; // in case any of our users are using scenes invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid return; // FIXME! } - + batch.setIndexBuffer(gpu::UINT32, (networkMesh._indexBuffer), 0); int vertexCount = mesh.vertices.size(); if (vertexCount == 0) { @@ -1633,7 +1633,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran if (_transforms.empty()) { _transforms.push_back(Transform()); } - + if (isSkinned) { const float* bones; if (_cauterizeBones) { @@ -1682,7 +1682,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran qCDebug(renderutils) << "WARNING: material == nullptr!!!"; } #endif - + if (material != nullptr) { // apply material properties @@ -1724,12 +1724,12 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran batch._glUniformMatrix4fv(locations->texcoordMatrices, 2, false, (const float*) &texcoordTransform); } - if (!mesh.tangents.isEmpty()) { + if (!mesh.tangents.isEmpty()) { NetworkTexture* normalMap = networkPart.normalTexture.data(); batch.setResourceTexture(1, (!normalMap || !normalMap->isLoaded()) ? textureCache->getBlueTexture() : normalMap->getGPUTexture()); } - + if (locations->specularTextureUnit >= 0) { NetworkTexture* specularMap = networkPart.specularTexture.data(); batch.setResourceTexture(locations->specularTextureUnit, (!specularMap || !specularMap->isLoaded()) ? @@ -1747,18 +1747,18 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran float emissiveOffset = part.emissiveParams.x; float emissiveScale = part.emissiveParams.y; batch._glUniform2f(locations->emissiveParams, emissiveOffset, emissiveScale); - + NetworkTexture* emissiveMap = networkPart.emissiveTexture.data(); batch.setResourceTexture(locations->emissiveTextureUnit, (!emissiveMap || !emissiveMap->isLoaded()) ? textureCache->getGrayTexture() : emissiveMap->getGPUTexture()); } - + if (translucent && locations->lightBufferUnit >= 0) { DependencyManager::get()->setupTransparent(args, locations->lightBufferUnit); } } } - + qint64 offset; { // FIXME_STUTTER: We should n't have any lock here @@ -1798,7 +1798,7 @@ void Model::segregateMeshGroups() { qDebug() << "WARNING!!!! Mesh Sizes don't match! We will not segregate mesh groups yet."; return; } - + _transparentRenderItems.clear(); _opaqueRenderItems.clear(); @@ -1807,18 +1807,6 @@ void Model::segregateMeshGroups() { const NetworkMesh& networkMesh = networkMeshes.at(i); const FBXMesh& mesh = geometry.meshes.at(i); const MeshState& state = _meshStates.at(i); - - - bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); - bool hasTangents = !mesh.tangents.isEmpty(); - bool hasSpecular = mesh.hasSpecularTexture(); - bool hasLightmap = mesh.hasEmissiveTexture(); - bool isSkinned = state.clusterMatrices.size() > 1; - bool wireframe = isWireframe(); - - if (wireframe) { - translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; - } // Create the render payloads int totalParts = mesh.parts.size(); @@ -1831,7 +1819,7 @@ void Model::segregateMeshGroups() { } } _meshGroupsKnown = true; -} +} void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, bool isWireframe, RenderArgs* args, @@ -1851,7 +1839,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f gpu::ShaderPointer program = (*pipeline).second._pipeline->getProgram(); locations = (*pipeline).second._locations.get(); - + // Setup the One pipeline batch.setPipeline((*pipeline).second._pipeline); @@ -1865,7 +1853,7 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f } if ((locations->normalFittingMapUnit > -1)) { - batch.setResourceTexture(locations->normalFittingMapUnit, + batch.setResourceTexture(locations->normalFittingMapUnit, DependencyManager::get()->getNormalFittingTexture()); } } From dab584833059bb529b3aa5179417bbbac4f691e6 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 11 Aug 2015 10:21:30 -0700 Subject: [PATCH 02/47] quiet compiler --- libraries/gpu/src/gpu/State.h | 816 +++++++++++++++++----------------- 1 file changed, 408 insertions(+), 408 deletions(-) diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 5e53284f36..42177e74dc 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -1,408 +1,408 @@ -// -// State -// libraries/gpu/src/gpu -// -// Created by Sam Gateau on 3/8/2015. -// Copyright 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_gpu_State_h -#define hifi_gpu_State_h - -#include "Format.h" - -#include -#include -#include -#include - -// Why a macro and not a fancy template you will ask me ? -// Because some of the fields are bool packed tightly in the State::Cache class -// and it s just not good anymore for template T& variable manipulation... -#define SET_FIELD(field, defaultValue, value, dest) {\ - dest = value;\ - if (value == defaultValue) {\ - _signature.reset(field);\ - } else {\ - _signature.set(field);\ - }\ - _stamp++;\ -}\ - - -namespace gpu { - -class GPUObject; - -class State { -public: - State(); - virtual ~State(); - - Stamp getStamp() const { return _stamp; } - - typedef ::gpu::ComparisonFunction ComparisonFunction; - - enum FillMode { - FILL_POINT = 0, - FILL_LINE, - FILL_FACE, - - NUM_FILL_MODES, - }; - - enum CullMode { - CULL_NONE = 0, - CULL_FRONT, - CULL_BACK, - - NUM_CULL_MODES, - }; - - enum StencilOp { - STENCIL_OP_KEEP = 0, - STENCIL_OP_ZERO, - STENCIL_OP_REPLACE, - STENCIL_OP_INCR_SAT, - STENCIL_OP_DECR_SAT, - STENCIL_OP_INVERT, - STENCIL_OP_INCR, - STENCIL_OP_DECR, - - NUM_STENCIL_OPS, - }; - - enum BlendArg { - ZERO = 0, - ONE, - SRC_COLOR, - INV_SRC_COLOR, - SRC_ALPHA, - INV_SRC_ALPHA, - DEST_ALPHA, - INV_DEST_ALPHA, - DEST_COLOR, - INV_DEST_COLOR, - SRC_ALPHA_SAT, - FACTOR_COLOR, - INV_FACTOR_COLOR, - FACTOR_ALPHA, - INV_FACTOR_ALPHA, - - NUM_BLEND_ARGS, - }; - - enum BlendOp { - BLEND_OP_ADD = 0, - BLEND_OP_SUBTRACT, - BLEND_OP_REV_SUBTRACT, - BLEND_OP_MIN, - BLEND_OP_MAX, - - NUM_BLEND_OPS, - }; - - enum ColorMask - { - WRITE_NONE = 0, - WRITE_RED = 1, - WRITE_GREEN = 2, - WRITE_BLUE = 4, - WRITE_ALPHA = 8, - WRITE_ALL = (WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA ), - }; - - class DepthTest { - uint8 _function = LESS; - uint8 _writeMask = true; - uint8 _enabled = false; - uint8 _spare = 0; - public: - DepthTest(bool enabled = false, bool writeMask = true, ComparisonFunction func = LESS) : - _function(func), _writeMask(writeMask), _enabled(enabled) {} - - bool isEnabled() const { return _enabled; } - ComparisonFunction getFunction() const { return ComparisonFunction(_function); } - bool getWriteMask() const { return _writeMask; } - - int32 getRaw() const { return *(reinterpret_cast(this)); } - DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } - bool operator== (const DepthTest& right) const { return getRaw() == right.getRaw(); } - bool operator!= (const DepthTest& right) const { return getRaw() != right.getRaw(); } - }; - - class StencilTest { - static const int FUNC_MASK = 0x000f; - static const int FAIL_OP_MASK = 0x00f0; - static const int DEPTH_FAIL_OP_MASK = 0x0f00; - static const int PASS_OP_MASK = 0xf000; - static const int FAIL_OP_OFFSET = 4; - static const int DEPTH_FAIL_OP_OFFSET = 8; - static const int PASS_OP_OFFSET = 12; - - uint16 _functionAndOperations; - uint8 _reference = 0; - uint8 _readMask = 0xff; - public: - - StencilTest(uint8 reference = 0, uint8 readMask =0xFF, ComparisonFunction func = ALWAYS, StencilOp failOp = STENCIL_OP_KEEP, StencilOp depthFailOp = STENCIL_OP_KEEP, StencilOp passOp = STENCIL_OP_KEEP) : - _functionAndOperations(func | (failOp << FAIL_OP_OFFSET) | (depthFailOp << DEPTH_FAIL_OP_OFFSET) | (passOp << PASS_OP_OFFSET)), - _reference(reference), _readMask(readMask) - {} - - ComparisonFunction getFunction() const { return ComparisonFunction(_functionAndOperations & FUNC_MASK); } - StencilOp getFailOp() const { return StencilOp((_functionAndOperations & FAIL_OP_MASK) >> FAIL_OP_OFFSET); } - StencilOp getDepthFailOp() const { return StencilOp((_functionAndOperations & DEPTH_FAIL_OP_MASK) >> DEPTH_FAIL_OP_OFFSET); } - StencilOp getPassOp() const { return StencilOp((_functionAndOperations & PASS_OP_MASK) >> PASS_OP_OFFSET); } - - uint8 getReference() const { return _reference; } - uint8 getReadMask() const { return _readMask; } - - int32 getRaw() const { return *(reinterpret_cast(this)); } - StencilTest(int32 raw) { *(reinterpret_cast(this)) = raw; } - bool operator== (const StencilTest& right) const { return getRaw() == right.getRaw(); } - bool operator!= (const StencilTest& right) const { return getRaw() != right.getRaw(); } - }; - - class StencilActivation { - uint8 _frontWriteMask = 0xFF; - uint8 _backWriteMask = 0xFF; - uint16 _enabled = 0; - public: - - StencilActivation(bool enabled, uint8 frontWriteMask = 0xFF, uint8 backWriteMask = 0xFF) : - _frontWriteMask(frontWriteMask), _backWriteMask(backWriteMask), _enabled(enabled) {} - - bool isEnabled() const { return (_enabled != 0); } - uint8 getWriteMaskFront() const { return _frontWriteMask; } - uint8 getWriteMaskBack() const { return _backWriteMask; } - - int32 getRaw() const { return *(reinterpret_cast(this)); } - StencilActivation(int32 raw) { *(reinterpret_cast(this)) = raw; } - bool operator== (const StencilActivation& right) const { return getRaw() == right.getRaw(); } - bool operator!= (const StencilActivation& right) const { return getRaw() != right.getRaw(); } - }; - - class BlendFunction { - static const int COLOR_MASK = 0x0f; - static const int ALPHA_MASK = 0xf0; - static const int ALPHA_OFFSET = 4; - - uint8 _enabled; - uint8 _source; - uint8 _destination; - uint8 _operation; - public: - - BlendFunction(bool enabled, - BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, - BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) : - _enabled(enabled), - _source(sourceColor | (sourceAlpha << ALPHA_OFFSET)), - _destination(destinationColor | (destinationAlpha << ALPHA_OFFSET)), - _operation(operationColor | (operationAlpha << ALPHA_OFFSET)) {} - - BlendFunction(bool enabled, BlendArg source = ONE, BlendOp operation = BLEND_OP_ADD, BlendArg destination = ZERO) : - _enabled(enabled), - _source(source | (source << ALPHA_OFFSET)), - _destination(destination | (destination << ALPHA_OFFSET)), - _operation(operation | (operation << ALPHA_OFFSET)) {} - - bool isEnabled() const { return (_enabled != 0); } - - BlendArg getSourceColor() const { return BlendArg(_source & COLOR_MASK); } - BlendArg getDestinationColor() const { return BlendArg(_destination & COLOR_MASK); } - BlendOp getOperationColor() const { return BlendOp(_operation & COLOR_MASK); } - - BlendArg getSourceAlpha() const { return BlendArg((_source & ALPHA_MASK) >> ALPHA_OFFSET); } - BlendArg getDestinationAlpha() const { return BlendArg((_destination & ALPHA_MASK) >> ALPHA_OFFSET); } - BlendOp getOperationAlpha() const { return BlendOp((_operation & ALPHA_MASK) >> ALPHA_OFFSET); } - - int32 getRaw() const { return *(reinterpret_cast(this)); } - BlendFunction(int32 raw) { *(reinterpret_cast(this)) = raw; } - bool operator== (const BlendFunction& right) const { return getRaw() == right.getRaw(); } - bool operator!= (const BlendFunction& right) const { return getRaw() != right.getRaw(); } - }; - - // The Data class is the full explicit description of the State class fields value. - // Useful for having one const static called Default for reference or for the gpu::Backend to keep track of the current value - class Data { - public: - float depthBias = 0.0f; - float depthBiasSlopeScale = 0.0f; - - DepthTest depthTest = DepthTest(false, true, LESS); - - StencilActivation stencilActivation = StencilActivation(false); - StencilTest stencilTestFront = StencilTest(0, 0xff, ALWAYS, STENCIL_OP_KEEP, STENCIL_OP_KEEP, STENCIL_OP_KEEP); - StencilTest stencilTestBack = StencilTest(0, 0xff, ALWAYS, STENCIL_OP_KEEP, STENCIL_OP_KEEP, STENCIL_OP_KEEP); - - uint32 sampleMask = 0xFFFFFFFF; - - BlendFunction blendFunction = BlendFunction(false); - - uint8 fillMode = FILL_FACE; - uint8 cullMode = CULL_NONE; - - uint8 colorWriteMask = WRITE_ALL; - - bool frontFaceClockwise : 1; - bool depthClampEnable : 1; - bool scissorEnable : 1; - bool multisampleEnable : 1; - bool antialisedLineEnable : 1; - bool alphaToCoverageEnable : 1; - - Data() : - frontFaceClockwise(false), - depthClampEnable(false), - scissorEnable(false), - multisampleEnable(false), - antialisedLineEnable(true), - alphaToCoverageEnable(false) - {} - }; - - // The unique default values for all the fields - static const Data DEFAULT; - void setFillMode(FillMode fill) { SET_FIELD(FILL_MODE, DEFAULT.fillMode, fill, _values.fillMode); } - FillMode getFillMode() const { return FillMode(_values.fillMode); } - - void setCullMode(CullMode cull) { SET_FIELD(CULL_MODE, DEFAULT.cullMode, cull, _values.cullMode); } - CullMode getCullMode() const { return CullMode(_values.cullMode); } - - void setFrontFaceClockwise(bool isClockwise) { SET_FIELD(FRONT_FACE_CLOCKWISE, DEFAULT.frontFaceClockwise, isClockwise, _values.frontFaceClockwise); } - bool isFrontFaceClockwise() const { return _values.frontFaceClockwise; } - - void setDepthClampEnable(bool enable) { SET_FIELD(DEPTH_CLAMP_ENABLE, DEFAULT.depthClampEnable, enable, _values.depthClampEnable); } - bool isDepthClampEnable() const { return _values.depthClampEnable; } - - void setScissorEnable(bool enable) { SET_FIELD(SCISSOR_ENABLE, DEFAULT.scissorEnable, enable, _values.scissorEnable); } - bool isScissorEnable() const { return _values.scissorEnable; } - - void setMultisampleEnable(bool enable) { SET_FIELD(MULTISAMPLE_ENABLE, DEFAULT.multisampleEnable, enable, _values.multisampleEnable); } - bool isMultisampleEnable() const { return _values.multisampleEnable; } - - void setAntialiasedLineEnable(bool enable) { SET_FIELD(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable, enable, _values.antialisedLineEnable); } - bool isAntialiasedLineEnable() const { return _values.antialisedLineEnable; } - - // Depth Bias - void setDepthBias(float bias) { SET_FIELD(DEPTH_BIAS, DEFAULT.depthBias, bias, _values.depthBias); } - float getDepthBias() const { return _values.depthBias; } - - void setDepthBiasSlopeScale(float scale) { SET_FIELD(DEPTH_BIAS_SLOPE_SCALE, DEFAULT.depthBiasSlopeScale, scale, _values.depthBiasSlopeScale); } - float getDepthBiasSlopeScale() const { return _values.depthBiasSlopeScale; } - - // Depth Test - void setDepthTest(DepthTest depthTest) { SET_FIELD(DEPTH_TEST, DEFAULT.depthTest, depthTest, _values.depthTest); } - void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { setDepthTest(DepthTest(enable, writeMask, func)); } - DepthTest getDepthTest() const { return _values.depthTest; } - - bool isDepthTestEnabled() const { return getDepthTest().isEnabled(); } - bool getDepthTestWriteMask() const { return getDepthTest().getWriteMask(); } - ComparisonFunction getDepthTestFunc() const { return getDepthTest().getFunction(); } - - // Stencil test - void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest) { - SET_FIELD(STENCIL_ACTIVATION, DEFAULT.stencilActivation, StencilActivation(enabled, frontWriteMask, backWriteMask), _values.stencilActivation); - SET_FIELD(STENCIL_TEST_FRONT, DEFAULT.stencilTestFront, frontTest, _values.stencilTestFront); - SET_FIELD(STENCIL_TEST_BACK, DEFAULT.stencilTestBack, backTest, _values.stencilTestBack); } - void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) { - setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); } - - StencilActivation getStencilActivation() const { return _values.stencilActivation; } - StencilTest getStencilTestFront() const { return _values.stencilTestFront; } - StencilTest getStencilTestBack() const { return _values.stencilTestBack; } - - bool isStencilEnabled() const { return getStencilActivation().isEnabled(); } - uint8 getStencilWriteMaskFront() const { return getStencilActivation().getWriteMaskFront(); } - uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); } - - // Alpha to coverage - void setAlphaToCoverageEnable(bool enable) { SET_FIELD(ALPHA_TO_COVERAGE_ENABLE, DEFAULT.alphaToCoverageEnable, enable, _values.alphaToCoverageEnable); } - bool isAlphaToCoverageEnabled() const { return _values.alphaToCoverageEnable; } - - // Sample mask - void setSampleMask(uint32 mask) { SET_FIELD(SAMPLE_MASK, DEFAULT.sampleMask, mask, _values.sampleMask); } - uint32 getSampleMask() const { return _values.sampleMask; } - - // Blend Function - void setBlendFunction(BlendFunction function) { SET_FIELD(BLEND_FUNCTION, DEFAULT.blendFunction, function, _values.blendFunction); } - BlendFunction getBlendFunction() const { return _values.blendFunction; } - - void setBlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) { - setBlendFunction(BlendFunction(enabled, sourceColor, operationColor, destinationColor, sourceAlpha, operationAlpha, destinationAlpha)); } - void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) { - setBlendFunction(BlendFunction(enabled, source, operation, destination)); } - - bool isBlendEnabled() const { return getBlendFunction().isEnabled(); } - - // Color write mask - void setColorWriteMask(uint8 mask) { SET_FIELD(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, mask, _values.colorWriteMask); } - void setColorWriteMask(bool red, bool green, bool blue, bool alpha) { uint32 value = ((WRITE_RED * red) | (WRITE_GREEN * green) | (WRITE_BLUE * blue) | (WRITE_ALPHA * alpha)); SET_FIELD(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, value, _values.colorWriteMask); } - uint8 getColorWriteMask() const { return _values.colorWriteMask; } - - // All the possible fields - enum Field { - FILL_MODE, - CULL_MODE, - FRONT_FACE_CLOCKWISE, - DEPTH_CLAMP_ENABLE, - SCISSOR_ENABLE, - MULTISAMPLE_ENABLE, - ANTIALISED_LINE_ENABLE, - - DEPTH_BIAS, - DEPTH_BIAS_SLOPE_SCALE, - - DEPTH_TEST, - - STENCIL_ACTIVATION, - STENCIL_TEST_FRONT, - STENCIL_TEST_BACK, - - SAMPLE_MASK, - ALPHA_TO_COVERAGE_ENABLE, - - BLEND_FUNCTION, - - COLOR_WRITE_MASK, - - NUM_FIELDS, // not a valid field, just the count - }; - - // The signature of the state tells which fields of the state are not default - // this way during rendering the Backend can compare it's current state and try to minimize the job to do - typedef std::bitset Signature; - - Signature getSignature() const { return _signature; } - - static Signature evalSignature(const Data& state); - - // For convenience, create a State from the values directly - State(const Data& values); - const Data& getValues() const { return _values; } - -protected: - State(const State& state); - State& operator=(const State& state); - - Data _values; - Signature _signature{0}; - Stamp _stamp{0}; - - // This shouldn't be used by anything else than the Backend class with the proper casting. - mutable GPUObject* _gpuObject = nullptr; - void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } - GPUObject* getGPUObject() const { return _gpuObject; } - friend class Backend; -}; - -typedef std::shared_ptr< State > StatePointer; -typedef std::vector< StatePointer > States; - -}; - -#endif +// +// State +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 3/8/2015. +// Copyright 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_gpu_State_h +#define hifi_gpu_State_h + +#include "Format.h" + +#include +#include +#include +#include + +// Why a macro and not a fancy template you will ask me ? +// Because some of the fields are bool packed tightly in the State::Cache class +// and it s just not good anymore for template T& variable manipulation... +#define SET_FIELD(field, defaultValue, value, dest) {\ + dest = value;\ + if (value == defaultValue) {\ + _signature.reset(field);\ + } else {\ + _signature.set(field);\ + }\ + _stamp++;\ +}\ + + +namespace gpu { + +class GPUObject; + +class State { +public: + State(); + virtual ~State(); + + Stamp getStamp() const { return _stamp; } + + typedef ::gpu::ComparisonFunction ComparisonFunction; + + enum FillMode { + FILL_POINT = 0, + FILL_LINE, + FILL_FACE, + + NUM_FILL_MODES, + }; + + enum CullMode { + CULL_NONE = 0, + CULL_FRONT, + CULL_BACK, + + NUM_CULL_MODES, + }; + + enum StencilOp { + STENCIL_OP_KEEP = 0, + STENCIL_OP_ZERO, + STENCIL_OP_REPLACE, + STENCIL_OP_INCR_SAT, + STENCIL_OP_DECR_SAT, + STENCIL_OP_INVERT, + STENCIL_OP_INCR, + STENCIL_OP_DECR, + + NUM_STENCIL_OPS, + }; + + enum BlendArg { + ZERO = 0, + ONE, + SRC_COLOR, + INV_SRC_COLOR, + SRC_ALPHA, + INV_SRC_ALPHA, + DEST_ALPHA, + INV_DEST_ALPHA, + DEST_COLOR, + INV_DEST_COLOR, + SRC_ALPHA_SAT, + FACTOR_COLOR, + INV_FACTOR_COLOR, + FACTOR_ALPHA, + INV_FACTOR_ALPHA, + + NUM_BLEND_ARGS, + }; + + enum BlendOp { + BLEND_OP_ADD = 0, + BLEND_OP_SUBTRACT, + BLEND_OP_REV_SUBTRACT, + BLEND_OP_MIN, + BLEND_OP_MAX, + + NUM_BLEND_OPS, + }; + + enum ColorMask + { + WRITE_NONE = 0, + WRITE_RED = 1, + WRITE_GREEN = 2, + WRITE_BLUE = 4, + WRITE_ALPHA = 8, + WRITE_ALL = (WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA ), + }; + + class DepthTest { + uint8 _function = LESS; + uint8 _writeMask = true; + uint8 _enabled = false; + uint8 _spare = 0; + public: + DepthTest(bool enabled = false, bool writeMask = true, ComparisonFunction func = LESS) : + _function(func), _writeMask(writeMask), _enabled(enabled) {} + + bool isEnabled() const { return _enabled != 0; } + ComparisonFunction getFunction() const { return ComparisonFunction(_function); } + bool getWriteMask() const { return _writeMask; } + + int32 getRaw() const { return *(reinterpret_cast(this)); } + DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } + bool operator== (const DepthTest& right) const { return getRaw() == right.getRaw(); } + bool operator!= (const DepthTest& right) const { return getRaw() != right.getRaw(); } + }; + + class StencilTest { + static const int FUNC_MASK = 0x000f; + static const int FAIL_OP_MASK = 0x00f0; + static const int DEPTH_FAIL_OP_MASK = 0x0f00; + static const int PASS_OP_MASK = 0xf000; + static const int FAIL_OP_OFFSET = 4; + static const int DEPTH_FAIL_OP_OFFSET = 8; + static const int PASS_OP_OFFSET = 12; + + uint16 _functionAndOperations; + uint8 _reference = 0; + uint8 _readMask = 0xff; + public: + + StencilTest(uint8 reference = 0, uint8 readMask =0xFF, ComparisonFunction func = ALWAYS, StencilOp failOp = STENCIL_OP_KEEP, StencilOp depthFailOp = STENCIL_OP_KEEP, StencilOp passOp = STENCIL_OP_KEEP) : + _functionAndOperations(func | (failOp << FAIL_OP_OFFSET) | (depthFailOp << DEPTH_FAIL_OP_OFFSET) | (passOp << PASS_OP_OFFSET)), + _reference(reference), _readMask(readMask) + {} + + ComparisonFunction getFunction() const { return ComparisonFunction(_functionAndOperations & FUNC_MASK); } + StencilOp getFailOp() const { return StencilOp((_functionAndOperations & FAIL_OP_MASK) >> FAIL_OP_OFFSET); } + StencilOp getDepthFailOp() const { return StencilOp((_functionAndOperations & DEPTH_FAIL_OP_MASK) >> DEPTH_FAIL_OP_OFFSET); } + StencilOp getPassOp() const { return StencilOp((_functionAndOperations & PASS_OP_MASK) >> PASS_OP_OFFSET); } + + uint8 getReference() const { return _reference; } + uint8 getReadMask() const { return _readMask; } + + int32 getRaw() const { return *(reinterpret_cast(this)); } + StencilTest(int32 raw) { *(reinterpret_cast(this)) = raw; } + bool operator== (const StencilTest& right) const { return getRaw() == right.getRaw(); } + bool operator!= (const StencilTest& right) const { return getRaw() != right.getRaw(); } + }; + + class StencilActivation { + uint8 _frontWriteMask = 0xFF; + uint8 _backWriteMask = 0xFF; + uint16 _enabled = 0; + public: + + StencilActivation(bool enabled, uint8 frontWriteMask = 0xFF, uint8 backWriteMask = 0xFF) : + _frontWriteMask(frontWriteMask), _backWriteMask(backWriteMask), _enabled(enabled) {} + + bool isEnabled() const { return (_enabled != 0); } + uint8 getWriteMaskFront() const { return _frontWriteMask; } + uint8 getWriteMaskBack() const { return _backWriteMask; } + + int32 getRaw() const { return *(reinterpret_cast(this)); } + StencilActivation(int32 raw) { *(reinterpret_cast(this)) = raw; } + bool operator== (const StencilActivation& right) const { return getRaw() == right.getRaw(); } + bool operator!= (const StencilActivation& right) const { return getRaw() != right.getRaw(); } + }; + + class BlendFunction { + static const int COLOR_MASK = 0x0f; + static const int ALPHA_MASK = 0xf0; + static const int ALPHA_OFFSET = 4; + + uint8 _enabled; + uint8 _source; + uint8 _destination; + uint8 _operation; + public: + + BlendFunction(bool enabled, + BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, + BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) : + _enabled(enabled), + _source(sourceColor | (sourceAlpha << ALPHA_OFFSET)), + _destination(destinationColor | (destinationAlpha << ALPHA_OFFSET)), + _operation(operationColor | (operationAlpha << ALPHA_OFFSET)) {} + + BlendFunction(bool enabled, BlendArg source = ONE, BlendOp operation = BLEND_OP_ADD, BlendArg destination = ZERO) : + _enabled(enabled), + _source(source | (source << ALPHA_OFFSET)), + _destination(destination | (destination << ALPHA_OFFSET)), + _operation(operation | (operation << ALPHA_OFFSET)) {} + + bool isEnabled() const { return (_enabled != 0); } + + BlendArg getSourceColor() const { return BlendArg(_source & COLOR_MASK); } + BlendArg getDestinationColor() const { return BlendArg(_destination & COLOR_MASK); } + BlendOp getOperationColor() const { return BlendOp(_operation & COLOR_MASK); } + + BlendArg getSourceAlpha() const { return BlendArg((_source & ALPHA_MASK) >> ALPHA_OFFSET); } + BlendArg getDestinationAlpha() const { return BlendArg((_destination & ALPHA_MASK) >> ALPHA_OFFSET); } + BlendOp getOperationAlpha() const { return BlendOp((_operation & ALPHA_MASK) >> ALPHA_OFFSET); } + + int32 getRaw() const { return *(reinterpret_cast(this)); } + BlendFunction(int32 raw) { *(reinterpret_cast(this)) = raw; } + bool operator== (const BlendFunction& right) const { return getRaw() == right.getRaw(); } + bool operator!= (const BlendFunction& right) const { return getRaw() != right.getRaw(); } + }; + + // The Data class is the full explicit description of the State class fields value. + // Useful for having one const static called Default for reference or for the gpu::Backend to keep track of the current value + class Data { + public: + float depthBias = 0.0f; + float depthBiasSlopeScale = 0.0f; + + DepthTest depthTest = DepthTest(false, true, LESS); + + StencilActivation stencilActivation = StencilActivation(false); + StencilTest stencilTestFront = StencilTest(0, 0xff, ALWAYS, STENCIL_OP_KEEP, STENCIL_OP_KEEP, STENCIL_OP_KEEP); + StencilTest stencilTestBack = StencilTest(0, 0xff, ALWAYS, STENCIL_OP_KEEP, STENCIL_OP_KEEP, STENCIL_OP_KEEP); + + uint32 sampleMask = 0xFFFFFFFF; + + BlendFunction blendFunction = BlendFunction(false); + + uint8 fillMode = FILL_FACE; + uint8 cullMode = CULL_NONE; + + uint8 colorWriteMask = WRITE_ALL; + + bool frontFaceClockwise : 1; + bool depthClampEnable : 1; + bool scissorEnable : 1; + bool multisampleEnable : 1; + bool antialisedLineEnable : 1; + bool alphaToCoverageEnable : 1; + + Data() : + frontFaceClockwise(false), + depthClampEnable(false), + scissorEnable(false), + multisampleEnable(false), + antialisedLineEnable(true), + alphaToCoverageEnable(false) + {} + }; + + // The unique default values for all the fields + static const Data DEFAULT; + void setFillMode(FillMode fill) { SET_FIELD(FILL_MODE, DEFAULT.fillMode, fill, _values.fillMode); } + FillMode getFillMode() const { return FillMode(_values.fillMode); } + + void setCullMode(CullMode cull) { SET_FIELD(CULL_MODE, DEFAULT.cullMode, cull, _values.cullMode); } + CullMode getCullMode() const { return CullMode(_values.cullMode); } + + void setFrontFaceClockwise(bool isClockwise) { SET_FIELD(FRONT_FACE_CLOCKWISE, DEFAULT.frontFaceClockwise, isClockwise, _values.frontFaceClockwise); } + bool isFrontFaceClockwise() const { return _values.frontFaceClockwise; } + + void setDepthClampEnable(bool enable) { SET_FIELD(DEPTH_CLAMP_ENABLE, DEFAULT.depthClampEnable, enable, _values.depthClampEnable); } + bool isDepthClampEnable() const { return _values.depthClampEnable; } + + void setScissorEnable(bool enable) { SET_FIELD(SCISSOR_ENABLE, DEFAULT.scissorEnable, enable, _values.scissorEnable); } + bool isScissorEnable() const { return _values.scissorEnable; } + + void setMultisampleEnable(bool enable) { SET_FIELD(MULTISAMPLE_ENABLE, DEFAULT.multisampleEnable, enable, _values.multisampleEnable); } + bool isMultisampleEnable() const { return _values.multisampleEnable; } + + void setAntialiasedLineEnable(bool enable) { SET_FIELD(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable, enable, _values.antialisedLineEnable); } + bool isAntialiasedLineEnable() const { return _values.antialisedLineEnable; } + + // Depth Bias + void setDepthBias(float bias) { SET_FIELD(DEPTH_BIAS, DEFAULT.depthBias, bias, _values.depthBias); } + float getDepthBias() const { return _values.depthBias; } + + void setDepthBiasSlopeScale(float scale) { SET_FIELD(DEPTH_BIAS_SLOPE_SCALE, DEFAULT.depthBiasSlopeScale, scale, _values.depthBiasSlopeScale); } + float getDepthBiasSlopeScale() const { return _values.depthBiasSlopeScale; } + + // Depth Test + void setDepthTest(DepthTest depthTest) { SET_FIELD(DEPTH_TEST, DEFAULT.depthTest, depthTest, _values.depthTest); } + void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { setDepthTest(DepthTest(enable, writeMask, func)); } + DepthTest getDepthTest() const { return _values.depthTest; } + + bool isDepthTestEnabled() const { return getDepthTest().isEnabled(); } + bool getDepthTestWriteMask() const { return getDepthTest().getWriteMask(); } + ComparisonFunction getDepthTestFunc() const { return getDepthTest().getFunction(); } + + // Stencil test + void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest) { + SET_FIELD(STENCIL_ACTIVATION, DEFAULT.stencilActivation, StencilActivation(enabled, frontWriteMask, backWriteMask), _values.stencilActivation); + SET_FIELD(STENCIL_TEST_FRONT, DEFAULT.stencilTestFront, frontTest, _values.stencilTestFront); + SET_FIELD(STENCIL_TEST_BACK, DEFAULT.stencilTestBack, backTest, _values.stencilTestBack); } + void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) { + setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); } + + StencilActivation getStencilActivation() const { return _values.stencilActivation; } + StencilTest getStencilTestFront() const { return _values.stencilTestFront; } + StencilTest getStencilTestBack() const { return _values.stencilTestBack; } + + bool isStencilEnabled() const { return getStencilActivation().isEnabled(); } + uint8 getStencilWriteMaskFront() const { return getStencilActivation().getWriteMaskFront(); } + uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); } + + // Alpha to coverage + void setAlphaToCoverageEnable(bool enable) { SET_FIELD(ALPHA_TO_COVERAGE_ENABLE, DEFAULT.alphaToCoverageEnable, enable, _values.alphaToCoverageEnable); } + bool isAlphaToCoverageEnabled() const { return _values.alphaToCoverageEnable; } + + // Sample mask + void setSampleMask(uint32 mask) { SET_FIELD(SAMPLE_MASK, DEFAULT.sampleMask, mask, _values.sampleMask); } + uint32 getSampleMask() const { return _values.sampleMask; } + + // Blend Function + void setBlendFunction(BlendFunction function) { SET_FIELD(BLEND_FUNCTION, DEFAULT.blendFunction, function, _values.blendFunction); } + BlendFunction getBlendFunction() const { return _values.blendFunction; } + + void setBlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) { + setBlendFunction(BlendFunction(enabled, sourceColor, operationColor, destinationColor, sourceAlpha, operationAlpha, destinationAlpha)); } + void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) { + setBlendFunction(BlendFunction(enabled, source, operation, destination)); } + + bool isBlendEnabled() const { return getBlendFunction().isEnabled(); } + + // Color write mask + void setColorWriteMask(uint8 mask) { SET_FIELD(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, mask, _values.colorWriteMask); } + void setColorWriteMask(bool red, bool green, bool blue, bool alpha) { uint32 value = ((WRITE_RED * red) | (WRITE_GREEN * green) | (WRITE_BLUE * blue) | (WRITE_ALPHA * alpha)); SET_FIELD(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, value, _values.colorWriteMask); } + uint8 getColorWriteMask() const { return _values.colorWriteMask; } + + // All the possible fields + enum Field { + FILL_MODE, + CULL_MODE, + FRONT_FACE_CLOCKWISE, + DEPTH_CLAMP_ENABLE, + SCISSOR_ENABLE, + MULTISAMPLE_ENABLE, + ANTIALISED_LINE_ENABLE, + + DEPTH_BIAS, + DEPTH_BIAS_SLOPE_SCALE, + + DEPTH_TEST, + + STENCIL_ACTIVATION, + STENCIL_TEST_FRONT, + STENCIL_TEST_BACK, + + SAMPLE_MASK, + ALPHA_TO_COVERAGE_ENABLE, + + BLEND_FUNCTION, + + COLOR_WRITE_MASK, + + NUM_FIELDS, // not a valid field, just the count + }; + + // The signature of the state tells which fields of the state are not default + // this way during rendering the Backend can compare it's current state and try to minimize the job to do + typedef std::bitset Signature; + + Signature getSignature() const { return _signature; } + + static Signature evalSignature(const Data& state); + + // For convenience, create a State from the values directly + State(const Data& values); + const Data& getValues() const { return _values; } + +protected: + State(const State& state); + State& operator=(const State& state); + + Data _values; + Signature _signature{0}; + Stamp _stamp{0}; + + // This shouldn't be used by anything else than the Backend class with the proper casting. + mutable GPUObject* _gpuObject = nullptr; + void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } + GPUObject* getGPUObject() const { return _gpuObject; } + friend class Backend; +}; + +typedef std::shared_ptr< State > StatePointer; +typedef std::vector< StatePointer > States; + +}; + +#endif From b25f6df7af349cfceb407ba20fe5d0d5efce29ab Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 11 Aug 2015 10:22:56 -0700 Subject: [PATCH 03/47] quiet compiler --- interface/src/avatar/AvatarManager.cpp | 2 +- libraries/gpu/src/gpu/State.h | 2 +- libraries/physics/src/ObjectActionSpring.cpp | 2 +- libraries/shared/src/PhysicsCollisionGroups.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index ee59a01e07..1644f22b09 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -279,7 +279,7 @@ void AvatarManager::handleCollisionEvents(CollisionEvents& collisionEvents) { const QString& collisionSoundURL = myAvatar->getCollisionSoundURL(); if (!collisionSoundURL.isEmpty()) { const float velocityChange = glm::length(collision.velocityChange); - const float MIN_AVATAR_COLLISION_ACCELERATION = 0.01; + const float MIN_AVATAR_COLLISION_ACCELERATION = 0.01f; const bool isSound = (collision.type == CONTACT_EVENT_TYPE_START) && (velocityChange > MIN_AVATAR_COLLISION_ACCELERATION); if (!isSound) { diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 5e53284f36..1b4a02e301 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -125,7 +125,7 @@ public: bool isEnabled() const { return _enabled; } ComparisonFunction getFunction() const { return ComparisonFunction(_function); } - bool getWriteMask() const { return _writeMask; } + uint8 getWriteMask() const { return _writeMask; } int32 getRaw() const { return *(reinterpret_cast(this)); } DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } diff --git a/libraries/physics/src/ObjectActionSpring.cpp b/libraries/physics/src/ObjectActionSpring.cpp index 196cc8d3ea..313b089d1c 100644 --- a/libraries/physics/src/ObjectActionSpring.cpp +++ b/libraries/physics/src/ObjectActionSpring.cpp @@ -92,7 +92,7 @@ void ObjectActionSpring::updateActionWorker(btScalar deltaTimeStep) { // dQ = Q1 * Q0^ btQuaternion deltaQ = target * bodyRotation.inverse(); float angle = deltaQ.getAngle(); - const float MIN_ANGLE = 1.0e-4; + const float MIN_ANGLE = 1.0e-4f; if (angle > MIN_ANGLE) { targetVelocity = (angle / _angularTimeScale) * deltaQ.getAxis(); } diff --git a/libraries/shared/src/PhysicsCollisionGroups.h b/libraries/shared/src/PhysicsCollisionGroups.h index 08d83a29ca..42599a1b28 100644 --- a/libraries/shared/src/PhysicsCollisionGroups.h +++ b/libraries/shared/src/PhysicsCollisionGroups.h @@ -44,7 +44,7 @@ const int16_t COLLISION_GROUP_OTHER_AVATAR = 1 << 6; const int16_t COLLISION_GROUP_MY_ATTACHMENT = 1 << 7; const int16_t COLLISION_GROUP_OTHER_ATTACHMENT = 1 << 8; // ... -const int16_t COLLISION_GROUP_COLLISIONLESS = 1 << 15; +const int16_t COLLISION_GROUP_COLLISIONLESS = 1 << 14; /* Note: In order for objectA to collide with objectB at the filter stage From 804c1ecf8e2523545553b62da2d6587b883e63d0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 11 Aug 2015 10:46:53 -0700 Subject: [PATCH 04/47] quiet compiler --- libraries/gpu/src/gpu/State.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 42177e74dc..7ab723ac63 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -125,7 +125,7 @@ public: bool isEnabled() const { return _enabled != 0; } ComparisonFunction getFunction() const { return ComparisonFunction(_function); } - bool getWriteMask() const { return _writeMask; } + uint8 getWriteMask() const { return _writeMask != 0; } int32 getRaw() const { return *(reinterpret_cast(this)); } DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } @@ -301,7 +301,7 @@ public: DepthTest getDepthTest() const { return _values.depthTest; } bool isDepthTestEnabled() const { return getDepthTest().isEnabled(); } - bool getDepthTestWriteMask() const { return getDepthTest().getWriteMask(); } + uint8 getDepthTestWriteMask() const { return getDepthTest().getWriteMask(); } ComparisonFunction getDepthTestFunc() const { return getDepthTest().getFunction(); } // Stencil test From fedbfe88815d25b11e68e0963162549a398d38c0 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 11 Aug 2015 11:00:04 -0700 Subject: [PATCH 05/47] fix jumbled merge --- libraries/gpu/src/gpu/State.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 7ab723ac63..5500f20e06 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -125,7 +125,7 @@ public: bool isEnabled() const { return _enabled != 0; } ComparisonFunction getFunction() const { return ComparisonFunction(_function); } - uint8 getWriteMask() const { return _writeMask != 0; } + uint8 getWriteMask() const { return _writeMask; } int32 getRaw() const { return *(reinterpret_cast(this)); } DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } From ea834609c2cb6c28198b2417e916f58a37529274 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 13 Aug 2015 10:33:31 -0700 Subject: [PATCH 06/47] Kill the AvatarAppearanceDialog and rewire necessary parts of PreferencesDialog. --- interface/src/ui/AvatarAppearanceDialog.cpp | 215 --------- interface/src/ui/AvatarAppearanceDialog.h | 64 --- interface/src/ui/DialogsManager.cpp | 10 - interface/src/ui/DialogsManager.h | 3 - interface/src/ui/PreferencesDialog.cpp | 38 +- interface/src/ui/PreferencesDialog.h | 5 +- interface/ui/avatarAppearance.ui | 471 -------------------- interface/ui/preferencesDialog.ui | 5 - 8 files changed, 32 insertions(+), 779 deletions(-) delete mode 100644 interface/src/ui/AvatarAppearanceDialog.cpp delete mode 100644 interface/src/ui/AvatarAppearanceDialog.h delete mode 100644 interface/ui/avatarAppearance.ui diff --git a/interface/src/ui/AvatarAppearanceDialog.cpp b/interface/src/ui/AvatarAppearanceDialog.cpp deleted file mode 100644 index 54e48dca26..0000000000 --- a/interface/src/ui/AvatarAppearanceDialog.cpp +++ /dev/null @@ -1,215 +0,0 @@ -// -// AvatarAppearanceDialog.cpp -// interface/src/ui -// -// Created by Stojce Slavkovski on 2/20/14. -// Copyright 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 -// - -#include -#include - -#include -#include -#include -#include - -#include "Application.h" -#include "MainWindow.h" -#include "LODManager.h" -#include "Menu.h" -#include "AvatarAppearanceDialog.h" -#include "Snapshot.h" -#include "UserActivityLogger.h" -#include "UIUtil.h" -#include "ui/DialogsManager.h" -#include "ui/PreferencesDialog.h" - -AvatarAppearanceDialog::AvatarAppearanceDialog(QWidget* parent) : - QDialog(parent) { - - setAttribute(Qt::WA_DeleteOnClose); - - ui.setupUi(this); - - loadAvatarAppearance(); - - connect(ui.defaultButton, &QPushButton::clicked, this, &AvatarAppearanceDialog::accept); - - connect(ui.buttonBrowseHead, &QPushButton::clicked, this, &AvatarAppearanceDialog::openHeadModelBrowser); - connect(ui.buttonBrowseBody, &QPushButton::clicked, this, &AvatarAppearanceDialog::openBodyModelBrowser); - connect(ui.buttonBrowseFullAvatar, &QPushButton::clicked, this, &AvatarAppearanceDialog::openFullAvatarModelBrowser); - - connect(ui.useSeparateBodyAndHead, &QRadioButton::clicked, this, &AvatarAppearanceDialog::useSeparateBodyAndHead); - connect(ui.useFullAvatar, &QRadioButton::clicked, this, &AvatarAppearanceDialog::useFullAvatar); - - connect(Application::getInstance(), &Application::headURLChanged, this, &AvatarAppearanceDialog::headURLChanged); - connect(Application::getInstance(), &Application::bodyURLChanged, this, &AvatarAppearanceDialog::bodyURLChanged); - connect(Application::getInstance(), &Application::fullAvatarURLChanged, this, &AvatarAppearanceDialog::fullAvatarURLChanged); - - auto myAvatar = DependencyManager::get()->getMyAvatar(); - - ui.bodyNameLabel->setText("Body - " + myAvatar->getBodyModelName()); - ui.headNameLabel->setText("Head - " + myAvatar->getHeadModelName()); - ui.fullAvatarNameLabel->setText("Full Avatar - " + myAvatar->getFullAvartarModelName()); - - UIUtil::scaleWidgetFontSizes(this); -} - -void AvatarAppearanceDialog::useSeparateBodyAndHead(bool checked) { - QUrl headURL(ui.faceURLEdit->text()); - QUrl bodyURL(ui.skeletonURLEdit->text()); - DependencyManager::get()->getMyAvatar()->useHeadAndBodyURLs(headURL, bodyURL); - setUseFullAvatar(!checked); -} - -void AvatarAppearanceDialog::useFullAvatar(bool checked) { - QUrl fullAvatarURL(ui.fullAvatarURLEdit->text()); - DependencyManager::get()->getMyAvatar()->useFullAvatarURL(fullAvatarURL); - setUseFullAvatar(checked); -} - -void AvatarAppearanceDialog::setUseFullAvatar(bool useFullAvatar) { - _useFullAvatar = useFullAvatar; - ui.faceURLEdit->setEnabled(!_useFullAvatar); - ui.skeletonURLEdit->setEnabled(!_useFullAvatar); - ui.fullAvatarURLEdit->setEnabled(_useFullAvatar); - - ui.useFullAvatar->setChecked(_useFullAvatar); - ui.useSeparateBodyAndHead->setChecked(!_useFullAvatar); - - QPointer prefs = DependencyManager::get()->getPreferencesDialog(); - if (prefs) { // Preferences dialog may have been closed - prefs->avatarDescriptionChanged(); - } -} - -void AvatarAppearanceDialog::headURLChanged(const QString& newValue, const QString& modelName) { - ui.faceURLEdit->setText(newValue); - setUseFullAvatar(false); - ui.headNameLabel->setText("Head - " + modelName); -} - -void AvatarAppearanceDialog::bodyURLChanged(const QString& newValue, const QString& modelName) { - ui.skeletonURLEdit->setText(newValue); - setUseFullAvatar(false); - ui.bodyNameLabel->setText("Body - " + modelName); -} - -void AvatarAppearanceDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) { - ui.fullAvatarURLEdit->setText(newValue); - setUseFullAvatar(true); - ui.fullAvatarNameLabel->setText("Full Avatar - " + modelName); -} - -void AvatarAppearanceDialog::accept() { - saveAvatarAppearance(); - - QPointer prefs = DependencyManager::get()->getPreferencesDialog(); - if (prefs) { // Preferences dialog may have been closed - prefs->avatarDescriptionChanged(); - } - - close(); - delete _marketplaceWindow; - _marketplaceWindow = NULL; -} - -void AvatarAppearanceDialog::setHeadUrl(QString modelUrl) { - ui.faceURLEdit->setText(modelUrl); -} - -void AvatarAppearanceDialog::setSkeletonUrl(QString modelUrl) { - ui.skeletonURLEdit->setText(modelUrl); -} - -void AvatarAppearanceDialog::openFullAvatarModelBrowser() { - auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars"; - auto WIDTH = 900; - auto HEIGHT = 700; - if (!_marketplaceWindow) { - _marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false); - } - _marketplaceWindow->setVisible(true); -} - -void AvatarAppearanceDialog::openHeadModelBrowser() { - auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars"; - auto WIDTH = 900; - auto HEIGHT = 700; - if (!_marketplaceWindow) { - _marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false); - } - _marketplaceWindow->setVisible(true); -} - -void AvatarAppearanceDialog::openBodyModelBrowser() { - auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars"; - auto WIDTH = 900; - auto HEIGHT = 700; - if (!_marketplaceWindow) { - _marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false); - } - _marketplaceWindow->setVisible(true); -} - -void AvatarAppearanceDialog::resizeEvent(QResizeEvent *resizeEvent) { - - // keep buttons panel at the bottom - ui.buttonsPanel->setGeometry(0, - size().height() - ui.buttonsPanel->height(), - size().width(), - ui.buttonsPanel->height()); - - // set width and height of srcollarea to match bottom panel and width - ui.scrollArea->setGeometry(ui.scrollArea->geometry().x(), ui.scrollArea->geometry().y(), - size().width(), - size().height() - ui.buttonsPanel->height() - ui.scrollArea->geometry().y()); - -} - -void AvatarAppearanceDialog::loadAvatarAppearance() { - - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - - _useFullAvatar = myAvatar->getUseFullAvatar(); - _fullAvatarURLString = myAvatar->getFullAvatarURLFromPreferences().toString(); - _headURLString = myAvatar->getHeadURLFromPreferences().toString(); - _bodyURLString = myAvatar->getBodyURLFromPreferences().toString(); - - ui.fullAvatarURLEdit->setText(_fullAvatarURLString); - ui.faceURLEdit->setText(_headURLString); - ui.skeletonURLEdit->setText(_bodyURLString); - setUseFullAvatar(_useFullAvatar); -} - -void AvatarAppearanceDialog::saveAvatarAppearance() { - - MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - - QUrl headURL(ui.faceURLEdit->text()); - QString headURLString = headURL.toString(); - - QUrl bodyURL(ui.skeletonURLEdit->text()); - QString bodyURLString = bodyURL.toString(); - - QUrl fullAvatarURL(ui.fullAvatarURLEdit->text()); - QString fullAvatarURLString = fullAvatarURL.toString(); - - bool somethingChanged = - _useFullAvatar != myAvatar->getUseFullAvatar() || - fullAvatarURLString != myAvatar->getFullAvatarURLFromPreferences().toString() || - headURLString != myAvatar->getHeadURLFromPreferences().toString() || - bodyURLString != myAvatar->getBodyURLFromPreferences().toString(); - - if (somethingChanged) { - if (_useFullAvatar) { - myAvatar->useFullAvatarURL(fullAvatarURL); - } else { - myAvatar->useHeadAndBodyURLs(headURL, bodyURL); - } - } -} diff --git a/interface/src/ui/AvatarAppearanceDialog.h b/interface/src/ui/AvatarAppearanceDialog.h deleted file mode 100644 index be30caeedb..0000000000 --- a/interface/src/ui/AvatarAppearanceDialog.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// AvatarAppearanceDialog.h -// interface/src/ui -// -// Created by Stojce Slavkovski on 2/20/14. -// Copyright 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_AvatarAppearanceDialog_h -#define hifi_AvatarAppearanceDialog_h - -#include "ui_avatarAppearance.h" - -#include -#include - -#include "scripting/WebWindowClass.h" - -class AvatarAppearanceDialog : public QDialog { - Q_OBJECT - -public: - AvatarAppearanceDialog(QWidget* parent = nullptr); - -protected: - void resizeEvent(QResizeEvent* resizeEvent); - -private: - void loadAvatarAppearance(); - void saveAvatarAppearance(); - void openHeadModelBrowser(); - void openBodyModelBrowser(); - void openFullAvatarModelBrowser(); - void setUseFullAvatar(bool useFullAvatar); - - Ui_AvatarAppearanceDialog ui; - - bool _useFullAvatar; - QString _headURLString; - QString _bodyURLString; - QString _fullAvatarURLString; - - - QString _displayNameString; - - WebWindowClass* _marketplaceWindow = NULL; - -private slots: - void accept(); - void setHeadUrl(QString modelUrl); - void setSkeletonUrl(QString modelUrl); - void headURLChanged(const QString& newValue, const QString& modelName); - void bodyURLChanged(const QString& newValue, const QString& modelName); - void fullAvatarURLChanged(const QString& newValue, const QString& modelName); - void useSeparateBodyAndHead(bool checked); - void useFullAvatar(bool checked); - - -}; - -#endif // hifi_AvatarAppearanceDialog_h diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index ac5e6833fb..d8671f9798 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -20,7 +20,6 @@ #include "AddressBarDialog.h" #include "AnimationsDialog.h" #include "AttachmentsDialog.h" -#include "AvatarAppearanceDialog.h" #include "BandwidthDialog.h" #include "CachesSizeDialog.h" #include "DiskCacheEditor.h" @@ -88,15 +87,6 @@ void DialogsManager::editPreferences() { } } -void DialogsManager::changeAvatarAppearance() { - if (!_avatarAppearanceDialog) { - maybeCreateDialog(_avatarAppearanceDialog); - _avatarAppearanceDialog->show(); - } else { - _avatarAppearanceDialog->close(); - } -} - void DialogsManager::editAttachments() { if (!_attachmentsDialog) { maybeCreateDialog(_attachmentsDialog); diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 09e0274d86..2db700e72a 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -34,7 +34,6 @@ class OctreeStatsDialog; class PreferencesDialog; class ScriptEditorWindow; class QMessageBox; -class AvatarAppearanceDialog; class DomainConnectionDialog; class UpdateDialog; @@ -66,7 +65,6 @@ public slots: void hmdTools(bool showTools); void showScriptEditor(); void showIRCLink(); - void changeAvatarAppearance(); void showDomainConnectionDialog(); // Application Update @@ -110,7 +108,6 @@ private: QPointer _octreeStatsDialog; QPointer _preferencesDialog; QPointer _scriptEditor; - QPointer _avatarAppearanceDialog; QPointer _domainConnectionDialog; QPointer _updateDialog; }; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 8e9c164563..cec379c596 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -47,23 +47,25 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : connect(ui.buttonBrowseScriptsLocation, &QPushButton::clicked, this, &PreferencesDialog::openScriptsLocationBrowser); connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, Application::getInstance(), &Application::loadDefaultScripts); - DialogsManager* dialogsManager = DependencyManager::get().data(); - connect(ui.buttonChangeApperance, &QPushButton::clicked, dialogsManager, &DialogsManager::changeAvatarAppearance); + //FIXME remove DialogsManager* dialogsManager = DependencyManager::get().data(); + //FIXME remove connect(ui.buttonChangeApperance, &QPushButton::clicked, dialogsManager, &DialogsManager::changeAvatarAppearance); + connect(ui.buttonChangeApperance, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser); + connect(ui.apperanceDescription, &QLineEdit::textChanged, this, [this](const QString& url) { + this->fullAvatarURLChanged(url, ""); + }); - connect(Application::getInstance(), &Application::headURLChanged, this, &PreferencesDialog::headURLChanged); - connect(Application::getInstance(), &Application::bodyURLChanged, this, &PreferencesDialog::bodyURLChanged); + //FIXME remove connect(Application::getInstance(), &Application::headURLChanged, this, &PreferencesDialog::headURLChanged); + //FIXME remove connect(Application::getInstance(), &Application::bodyURLChanged, this, &PreferencesDialog::bodyURLChanged); connect(Application::getInstance(), &Application::fullAvatarURLChanged, this, &PreferencesDialog::fullAvatarURLChanged); // move dialog to left side move(parentWidget()->geometry().topLeft()); setFixedHeight(parentWidget()->size().height() - PREFERENCES_HEIGHT_PADDING); - ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); - UIUtil::scaleWidgetFontSizes(this); } -void PreferencesDialog::avatarDescriptionChanged() { +/*FIXME remove void PreferencesDialog::avatarDescriptionChanged() { ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); } @@ -74,9 +76,13 @@ void PreferencesDialog::headURLChanged(const QString& newValue, const QString& m void PreferencesDialog::bodyURLChanged(const QString& newValue, const QString& modelName) { ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); } - +*/ void PreferencesDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) { - ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); + //FIXME remove ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); + ui.apperanceDescription->setText(newValue); + const QString APPEARANCE_LABEL_TEXT("Appearance: "); + ui.appearanceLabel->setText(APPEARANCE_LABEL_TEXT + modelName); + DependencyManager::get()->getMyAvatar()->useFullAvatarURL(newValue, modelName); } void PreferencesDialog::accept() { @@ -103,6 +109,16 @@ void PreferencesDialog::openScriptsLocationBrowser() { ui.scriptsLocationEdit->setText(dir); } } +void PreferencesDialog::openFullAvatarModelBrowser() { + const auto MARKETPLACE_URL = NetworkingConstants::METAVERSE_SERVER_URL.toString() + "/marketplace?category=avatars"; + const auto WIDTH = 900; + const auto HEIGHT = 700; + if (!_marketplaceWindow) { + _marketplaceWindow = new WebWindowClass("Marketplace", MARKETPLACE_URL, WIDTH, HEIGHT, false); + } + _marketplaceWindow->setVisible(true); + +} void PreferencesDialog::resizeEvent(QResizeEvent *resizeEvent) { @@ -129,6 +145,9 @@ void PreferencesDialog::loadPreferences() { ui.collisionSoundURLEdit->setText(myAvatar->getCollisionSoundURL()); + fullAvatarURLChanged(myAvatar->getFullAvatarURLFromPreferences().toString(), + myAvatar->getFullAvartarModelName()); + ui.sendDataCheckBox->setChecked(!menuInstance->isOptionChecked(MenuOption::DisableActivityLogger)); ui.snapshotLocationEdit->setText(Snapshot::snapshotsLocation.get()); @@ -210,6 +229,7 @@ void PreferencesDialog::savePreferences() { } myAvatar->setCollisionSoundURL(ui.collisionSoundURLEdit->text()); + // avatar model url is already persisted by fullAvatarURLChanged() if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger) != ui.sendDataCheckBox->isChecked()) { diff --git a/interface/src/ui/PreferencesDialog.h b/interface/src/ui/PreferencesDialog.h index 8e699c80a2..6cdb4deba1 100644 --- a/interface/src/ui/PreferencesDialog.h +++ b/interface/src/ui/PreferencesDialog.h @@ -42,10 +42,11 @@ private: private slots: void accept(); + void openFullAvatarModelBrowser(); void openSnapshotLocationBrowser(); void openScriptsLocationBrowser(); - void headURLChanged(const QString& newValue, const QString& modelName); - void bodyURLChanged(const QString& newValue, const QString& modelName); + /* FIXME remove void headURLChanged(const QString& newValue, const QString& modelName); + void bodyURLChanged(const QString& newValue, const QString& modelName);*/ void fullAvatarURLChanged(const QString& newValue, const QString& modelName); }; diff --git a/interface/ui/avatarAppearance.ui b/interface/ui/avatarAppearance.ui deleted file mode 100644 index 5ebf2c705b..0000000000 --- a/interface/ui/avatarAppearance.ui +++ /dev/null @@ -1,471 +0,0 @@ - - - AvatarAppearanceDialog - - - - 0 - 0 - 500 - 350 - - - - - 0 - 0 - - - - - 500 - 350 - - - - - 500 - 16777215 - - - - - 13 - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - - 0 - 0 - - - - QFrame::NoFrame - - - QFrame::Plain - - - 0 - - - true - - - - - 0 - -107 - 485 - 1550 - - - - - 0 - - - 30 - - - 0 - - - 30 - - - 10 - - - - - - - 0 - - - 7 - - - 7 - - - - - - - - - Arial - - - - Use single avatar with Body and Head - - - - - - - - - - 0 - - - 10 - - - 0 - - - 0 - - - - - - - - Arial - - - - Full Avatar - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - fullAvatarURLEdit - - - - - - - - - - - - 0 - 0 - - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 0 - - - - - - - - - - Arial - - - - Browse - - - - 0 - 0 - - - - - - - - - - - - - - - - - - - - - - - - Arial - - - - Use separate Body and Head avatar files - - - - - - - - - 0 - - - 10 - - - 7 - - - 7 - - - - - - - - - Arial - - - - Head - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - - - - - - - - 0 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - Arial - - - - Browse - - - - 0 - 0 - - - - - - - - - - - - - - - 0 - - - 10 - - - 7 - - - 7 - - - - - - - Arial - - - - Body - - - Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - - - skeletonURLEdit - - - - - - - - 0 - - - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - Arial - - - - Browse - - - - 0 - 0 - - - - - - - - - - - - - - - - - - - - - - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - Arial - - - - Close - - - true - - - false - - - - - - - - - - - - diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui index df6d28c07b..71103da654 100644 --- a/interface/ui/preferencesDialog.ui +++ b/interface/ui/preferencesDialog.ui @@ -294,11 +294,6 @@ Arial - - - false - - From 62941c09140feeffcbe3e7ceb72efac1f024305f Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 13 Aug 2015 12:39:30 -0700 Subject: [PATCH 07/47] Remove dead code. --- interface/src/Application.cpp | 27 +---- interface/src/avatar/Avatar.cpp | 13 +-- interface/src/avatar/Avatar.h | 2 - interface/src/avatar/MyAvatar.cpp | 142 +------------------------ interface/src/avatar/MyAvatar.h | 24 +---- interface/src/ui/PreferencesDialog.cpp | 18 ---- interface/src/ui/PreferencesDialog.h | 2 - libraries/avatars/src/AvatarData.cpp | 2 +- libraries/avatars/src/AvatarData.h | 7 +- 9 files changed, 12 insertions(+), 225 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dba2ed3234..5dac571045 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3896,23 +3896,12 @@ bool Application::askToSetAvatarUrl(const QString& url) { QMessageBox msgBox; msgBox.setIcon(QMessageBox::Question); msgBox.setWindowTitle("Set Avatar"); - QPushButton* headButton = NULL; - QPushButton* bodyButton = NULL; QPushButton* bodyAndHeadButton = NULL; QString modelName = fstMapping["name"].toString(); QString message; QString typeInfo; switch (modelType) { - case FSTReader::HEAD_MODEL: - message = QString("Would you like to use '") + modelName + QString("' for your avatar head?"); - headButton = msgBox.addButton(tr("Yes"), QMessageBox::ActionRole); - break; - - case FSTReader::BODY_ONLY_MODEL: - message = QString("Would you like to use '") + modelName + QString("' for your avatar body?"); - bodyButton = msgBox.addButton(tr("Yes"), QMessageBox::ActionRole); - break; case FSTReader::HEAD_AND_BODY_MODEL: message = QString("Would you like to use '") + modelName + QString("' for your avatar?"); @@ -3920,10 +3909,7 @@ bool Application::askToSetAvatarUrl(const QString& url) { break; default: - message = QString("Would you like to use '") + modelName + QString("' for some part of your avatar head?"); - headButton = msgBox.addButton(tr("Use for Head"), QMessageBox::ActionRole); - bodyButton = msgBox.addButton(tr("Use for Body"), QMessageBox::ActionRole); - bodyAndHeadButton = msgBox.addButton(tr("Use for Body and Head"), QMessageBox::ActionRole); + message = QString(modelName + QString("Does not support a head and body as required.")); break; } @@ -3932,14 +3918,7 @@ bool Application::askToSetAvatarUrl(const QString& url) { msgBox.exec(); - if (msgBox.clickedButton() == headButton) { - _myAvatar->useHeadURL(url, modelName); - emit headURLChanged(url, modelName); - } else if (msgBox.clickedButton() == bodyButton) { - _myAvatar->useBodyURL(url, modelName); - emit bodyURLChanged(url, modelName); - } else if (msgBox.clickedButton() == bodyAndHeadButton) { - _myAvatar->useFullAvatarURL(url, modelName); + if (msgBox.clickedButton() == bodyAndHeadButton) { emit fullAvatarURLChanged(url, modelName); } else { qCDebug(interfaceapp) << "Declined to use the avatar: " << url; @@ -4426,7 +4405,7 @@ void Application::checkSkeleton() { msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); - _myAvatar->useBodyURL(DEFAULT_BODY_MODEL_URL, "Default"); + _myAvatar->useFullAvatarURL(DEFAULT_FULL_AVATAR_MODEL_URL, DEFAULT_FULL_AVATAR_MODEL_NAME); } else { _physicsEngine.setCharacterController(_myAvatar->getCharacterController()); } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 8ba58217c3..b537d5a5d8 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -953,20 +952,12 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { void Avatar::setFaceModelURL(const QUrl& faceModelURL) { AvatarData::setFaceModelURL(faceModelURL); - const QUrl DEFAULT_FACE_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_head.fst"); - getHead()->getFaceModel().setURL(_faceModelURL, DEFAULT_FACE_MODEL_URL, true, !isMyAvatar()); + getHead()->getFaceModel().setURL(_faceModelURL, DEFAULT_FULL_AVATAR_MODEL_URL, true, !isMyAvatar()); } void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { AvatarData::setSkeletonModelURL(skeletonModelURL); - const QUrl DEFAULT_FULL_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_full.fst"); - const QUrl DEFAULT_SKELETON_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_body.fst"); - if (isMyAvatar()) { - _skeletonModel.setURL(_skeletonModelURL, - getUseFullAvatar() ? DEFAULT_FULL_MODEL_URL : DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar()); - } else { - _skeletonModel.setURL(_skeletonModelURL, DEFAULT_SKELETON_MODEL_URL, true, !isMyAvatar()); - } + _skeletonModel.setURL(_skeletonModelURL, DEFAULT_FULL_AVATAR_MODEL_URL, true, !isMyAvatar()); } void Avatar::setAttachmentData(const QVector& attachmentData) { diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index a51da387d0..2adff1ce02 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -149,8 +149,6 @@ public: Q_INVOKABLE glm::vec3 getAcceleration() const { return _acceleration; } Q_INVOKABLE glm::vec3 getAngularVelocity() const { return _angularVelocity; } Q_INVOKABLE glm::vec3 getAngularAcceleration() const { return _angularAcceleration; } - - virtual bool getUseFullAvatar() const { return false; } /// Scales a world space position vector relative to the avatar position and scale /// \param vector position to be scaled. Will store the result diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2cc1105fdc..05bfac1523 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -651,12 +651,7 @@ void MyAvatar::saveData() { settings.setValue("leanScale", _leanScale); settings.setValue("scale", _targetScale); - settings.setValue("useFullAvatar", _useFullAvatar); settings.setValue("fullAvatarURL", _fullAvatarURLFromPreferences); - settings.setValue("faceModelURL", _headURLFromPreferences); - settings.setValue("skeletonModelURL", _skeletonURLFromPreferences); - settings.setValue("headModelName", _headModelName); - settings.setValue("bodyModelName", _bodyModelName); settings.setValue("fullAvatarModelName", _fullAvatarModelName); settings.beginWriteArray("attachmentData"); @@ -726,61 +721,10 @@ void MyAvatar::loadData() { _targetScale = loadSetting(settings, "scale", 1.0f); setScale(_scale); - // The old preferences only stored the face and skeleton URLs, we didn't track if the user wanted to use 1 or 2 urls - // for their avatar, So we need to attempt to detect this old case and set our new preferences accordingly. If - // the head URL is empty, then we will assume they are using a full url... - bool isOldSettings = !(settings.contains("useFullAvatar") || settings.contains("fullAvatarURL")); - - _useFullAvatar = settings.value("useFullAvatar").toBool(); - _headURLFromPreferences = settings.value("faceModelURL", DEFAULT_HEAD_MODEL_URL).toUrl(); _fullAvatarURLFromPreferences = settings.value("fullAvatarURL", DEFAULT_FULL_AVATAR_MODEL_URL).toUrl(); - _skeletonURLFromPreferences = settings.value("skeletonModelURL", DEFAULT_BODY_MODEL_URL).toUrl(); - _headModelName = settings.value("headModelName", DEFAULT_HEAD_MODEL_NAME).toString(); - _bodyModelName = settings.value("bodyModelName", DEFAULT_BODY_MODEL_NAME).toString(); _fullAvatarModelName = settings.value("fullAvatarModelName", DEFAULT_FULL_AVATAR_MODEL_NAME).toString(); - if (isOldSettings) { - bool assumeFullAvatar = _headURLFromPreferences.isEmpty(); - _useFullAvatar = assumeFullAvatar; - - if (_useFullAvatar) { - _fullAvatarURLFromPreferences = settings.value("skeletonModelURL").toUrl(); - _headURLFromPreferences = DEFAULT_HEAD_MODEL_URL; - _skeletonURLFromPreferences = DEFAULT_BODY_MODEL_URL; - - QVariantHash fullAvatarFST = FSTReader::downloadMapping(_fullAvatarURLFromPreferences.toString()); - - _headModelName = "Default"; - _bodyModelName = "Default"; - _fullAvatarModelName = fullAvatarFST["name"].toString(); - - } else { - _fullAvatarURLFromPreferences = DEFAULT_FULL_AVATAR_MODEL_URL; - _skeletonURLFromPreferences = settings.value("skeletonModelURL", DEFAULT_BODY_MODEL_URL).toUrl(); - - if (_skeletonURLFromPreferences == DEFAULT_BODY_MODEL_URL) { - _bodyModelName = DEFAULT_BODY_MODEL_NAME; - } else { - QVariantHash bodyFST = FSTReader::downloadMapping(_skeletonURLFromPreferences.toString()); - _bodyModelName = bodyFST["name"].toString(); - } - - if (_headURLFromPreferences == DEFAULT_HEAD_MODEL_URL) { - _headModelName = DEFAULT_HEAD_MODEL_NAME; - } else { - QVariantHash headFST = FSTReader::downloadMapping(_headURLFromPreferences.toString()); - _headModelName = headFST["name"].toString(); - } - - _fullAvatarModelName = "Default"; - } - } - - if (_useFullAvatar) { - useFullAvatarURL(_fullAvatarURLFromPreferences, _fullAvatarModelName); - } else { - useHeadAndBodyURLs(_headURLFromPreferences, _skeletonURLFromPreferences, _headModelName, _bodyModelName); - } + useFullAvatarURL(_fullAvatarURLFromPreferences, _fullAvatarModelName); QVector attachmentData; int attachmentCount = settings.beginReadArray("attachmentData"); @@ -1015,29 +959,6 @@ void MyAvatar::clearJointAnimationPriorities() { } } -QString MyAvatar::getModelDescription() const { - QString result; - if (_useFullAvatar) { - if (!getFullAvartarModelName().isEmpty()) { - result = "Full Avatar \"" + getFullAvartarModelName() + "\""; - } else { - result = "Full Avatar \"" + _fullAvatarURLFromPreferences.fileName() + "\""; - } - } else { - if (!getHeadModelName().isEmpty()) { - result = "Head \"" + getHeadModelName() + "\""; - } else { - result = "Head \"" + _headURLFromPreferences.fileName() + "\""; - } - if (!getBodyModelName().isEmpty()) { - result += " and Body \"" + getBodyModelName() + "\""; - } else { - result += " and Body \"" + _skeletonURLFromPreferences.fileName() + "\""; - } - } - return result; -} - void MyAvatar::setFaceModelURL(const QUrl& faceModelURL) { Avatar::setFaceModelURL(faceModelURL); @@ -1064,8 +985,6 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN return; } - _useFullAvatar = true; - if (_fullAvatarURLFromPreferences != fullAvatarURL) { _fullAvatarURLFromPreferences = fullAvatarURL; if (modelName.isEmpty()) { @@ -1087,59 +1006,6 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN sendIdentityPacket(); } -void MyAvatar::useHeadURL(const QUrl& headURL, const QString& modelName) { - useHeadAndBodyURLs(headURL, _skeletonURLFromPreferences, modelName, _bodyModelName); -} - -void MyAvatar::useBodyURL(const QUrl& bodyURL, const QString& modelName) { - useHeadAndBodyURLs(_headURLFromPreferences, bodyURL, _headModelName, modelName); -} - -void MyAvatar::useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL, const QString& headName, const QString& bodyName) { - if (QThread::currentThread() != thread()) { - QMetaObject::invokeMethod(this, "useFullAvatarURL", Qt::BlockingQueuedConnection, - Q_ARG(const QUrl&, headURL), - Q_ARG(const QUrl&, bodyURL), - Q_ARG(const QString&, headName), - Q_ARG(const QString&, bodyName)); - return; - } - - _useFullAvatar = false; - - if (_headURLFromPreferences != headURL) { - _headURLFromPreferences = headURL; - if (headName.isEmpty()) { - QVariantHash headFST = FSTReader::downloadMapping(_headURLFromPreferences.toString()); - _headModelName = headFST["name"].toString(); - } else { - _headModelName = headName; - } - } - - if (_skeletonURLFromPreferences != bodyURL) { - _skeletonURLFromPreferences = bodyURL; - if (bodyName.isEmpty()) { - QVariantHash bodyFST = FSTReader::downloadMapping(_skeletonURLFromPreferences.toString()); - _bodyModelName = bodyFST["name"].toString(); - } else { - _bodyModelName = bodyName; - } - } - - if (headURL != getFaceModelURL()) { - setFaceModelURL(headURL); - UserActivityLogger::getInstance().changedModel("head", headURL.toString()); - } - - if (bodyURL != getSkeletonModelURL()) { - setSkeletonModelURL(bodyURL); - UserActivityLogger::getInstance().changedModel("skeleton", bodyURL.toString()); - } - sendIdentityPacket(); -} - - void MyAvatar::setAttachmentData(const QVector& attachmentData) { Avatar::setAttachmentData(attachmentData); if (QThread::currentThread() != thread()) { @@ -1295,11 +1161,7 @@ void MyAvatar::preRender(RenderArgs* renderArgs) { } if (shouldDrawHead != _prevShouldDrawHead) { - if (_useFullAvatar) { - _skeletonModel.setCauterizeBones(!shouldDrawHead); - } else { - getHead()->getFaceModel().setVisibleInScene(shouldDrawHead, scene); - } + _skeletonModel.setCauterizeBones(!shouldDrawHead); } _prevShouldDrawHead = shouldDrawHead; } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 88649429f5..0cd56ec99c 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -126,22 +126,9 @@ public: virtual void clearJointsData(); Q_INVOKABLE void useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName = QString()); - Q_INVOKABLE void useHeadURL(const QUrl& headURL, const QString& modelName = QString()); - Q_INVOKABLE void useBodyURL(const QUrl& bodyURL, const QString& modelName = QString()); - Q_INVOKABLE void useHeadAndBodyURLs(const QUrl& headURL, const QUrl& bodyURL, - const QString& headName = QString(), const QString& bodyName = QString()); - - Q_INVOKABLE virtual bool getUseFullAvatar() const { return _useFullAvatar; } Q_INVOKABLE const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; } - Q_INVOKABLE const QUrl& getHeadURLFromPreferences() const { return _headURLFromPreferences; } - Q_INVOKABLE const QUrl& getBodyURLFromPreferences() const { return _skeletonURLFromPreferences; } - - Q_INVOKABLE const QString& getHeadModelName() const { return _headModelName; } - Q_INVOKABLE const QString& getBodyModelName() const { return _bodyModelName; } Q_INVOKABLE const QString& getFullAvartarModelName() const { return _fullAvatarModelName; } - Q_INVOKABLE QString getModelDescription() const; - virtual void setAttachmentData(const QVector& attachmentData); DynamicCharacterController* getCharacterController() { return &_characterController; } @@ -298,18 +285,9 @@ private: void initHeadBones(); // Avatar Preferences - bool _useFullAvatar = false; QUrl _fullAvatarURLFromPreferences; - QUrl _headURLFromPreferences; - QUrl _skeletonURLFromPreferences; - - QString _headModelName; - QString _bodyModelName; QString _fullAvatarModelName; - RigPointer _rig; - bool _prevShouldDrawHead; - // cache of the current HMD sensor position and orientation // in sensor space. glm::mat4 _hmdSensorMatrix; @@ -330,6 +308,8 @@ private: glm::quat _goToOrientation; std::unordered_set _headBoneSet; + RigPointer _rig; + bool _prevShouldDrawHead; }; #endif // hifi_MyAvatar_h diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index cec379c596..59701e5cf3 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -47,15 +47,10 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : connect(ui.buttonBrowseScriptsLocation, &QPushButton::clicked, this, &PreferencesDialog::openScriptsLocationBrowser); connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, Application::getInstance(), &Application::loadDefaultScripts); - //FIXME remove DialogsManager* dialogsManager = DependencyManager::get().data(); - //FIXME remove connect(ui.buttonChangeApperance, &QPushButton::clicked, dialogsManager, &DialogsManager::changeAvatarAppearance); connect(ui.buttonChangeApperance, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser); connect(ui.apperanceDescription, &QLineEdit::textChanged, this, [this](const QString& url) { this->fullAvatarURLChanged(url, ""); }); - - //FIXME remove connect(Application::getInstance(), &Application::headURLChanged, this, &PreferencesDialog::headURLChanged); - //FIXME remove connect(Application::getInstance(), &Application::bodyURLChanged, this, &PreferencesDialog::bodyURLChanged); connect(Application::getInstance(), &Application::fullAvatarURLChanged, this, &PreferencesDialog::fullAvatarURLChanged); // move dialog to left side @@ -65,20 +60,7 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : UIUtil::scaleWidgetFontSizes(this); } -/*FIXME remove void PreferencesDialog::avatarDescriptionChanged() { - ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); -} - -void PreferencesDialog::headURLChanged(const QString& newValue, const QString& modelName) { - ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); -} - -void PreferencesDialog::bodyURLChanged(const QString& newValue, const QString& modelName) { - ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); -} -*/ void PreferencesDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) { - //FIXME remove ui.apperanceDescription->setText(DependencyManager::get()->getMyAvatar()->getModelDescription()); ui.apperanceDescription->setText(newValue); const QString APPEARANCE_LABEL_TEXT("Appearance: "); ui.appearanceLabel->setText(APPEARANCE_LABEL_TEXT + modelName); diff --git a/interface/src/ui/PreferencesDialog.h b/interface/src/ui/PreferencesDialog.h index 6cdb4deba1..47341b8feb 100644 --- a/interface/src/ui/PreferencesDialog.h +++ b/interface/src/ui/PreferencesDialog.h @@ -45,8 +45,6 @@ private slots: void openFullAvatarModelBrowser(); void openSnapshotLocationBrowser(); void openScriptsLocationBrowser(); - /* FIXME remove void headURLChanged(const QString& newValue, const QString& modelName); - void bodyURLChanged(const QString& newValue, const QString& modelName);*/ void fullAvatarURLChanged(const QString& newValue, const QString& modelName); }; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 5b970a95a3..78fa00eed7 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -941,7 +941,7 @@ void AvatarData::setFaceModelURL(const QUrl& faceModelURL) { } void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) { - _skeletonModelURL = skeletonModelURL.isEmpty() ? DEFAULT_BODY_MODEL_URL : skeletonModelURL; + _skeletonModelURL = skeletonModelURL.isEmpty() ? DEFAULT_FULL_AVATAR_MODEL_URL : skeletonModelURL; qCDebug(avatars) << "Changing skeleton model for avatar to" << _skeletonModelURL.toString(); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 69783652fc..16003594c9 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -48,6 +48,7 @@ typedef unsigned long long quint64; #include #include +//FIXME #include #include #include @@ -107,12 +108,8 @@ const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000; const int AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS = 5000; -const QUrl DEFAULT_HEAD_MODEL_URL = QUrl("http://public.highfidelity.io/models/heads/defaultAvatar_head.fst"); -const QUrl DEFAULT_BODY_MODEL_URL = QUrl("http://public.highfidelity.io/models/skeletons/defaultAvatar_body.fst"); +//FIXME const QUrl DEFAULT_FULL_AVATAR_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_full.fst"); const QUrl DEFAULT_FULL_AVATAR_MODEL_URL = QUrl("http://public.highfidelity.io/marketplace/contents/029db3d4-da2c-4cb2-9c08-b9612ba576f5/02949063e7c4aed42ad9d1a58461f56d.fst"); - -const QString DEFAULT_HEAD_MODEL_NAME = QString("Robot"); -const QString DEFAULT_BODY_MODEL_NAME = QString("Robot"); const QString DEFAULT_FULL_AVATAR_MODEL_NAME = QString("Default"); From 4dae01a69c7bafbb10639212640340941adc7e3b Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 13 Aug 2015 12:54:16 -0700 Subject: [PATCH 08/47] Provide a consistent avatar default for the empty string. --- interface/src/avatar/MyAvatar.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 05bfac1523..ddc0b0b9d1 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -999,9 +999,10 @@ void MyAvatar::useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelN setFaceModelURL(QString()); } - if (fullAvatarURL != getSkeletonModelURL()) { + const QString& urlString = fullAvatarURL.toString(); + if (urlString.isEmpty() || (fullAvatarURL != getSkeletonModelURL())) { setSkeletonModelURL(fullAvatarURL); - UserActivityLogger::getInstance().changedModel("skeleton", fullAvatarURL.toString()); + UserActivityLogger::getInstance().changedModel("skeleton", urlString); } sendIdentityPacket(); } From 2756a0063877e2274a94df7a22ebcaaa8f9120d4 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 13 Aug 2015 14:23:34 -0700 Subject: [PATCH 09/47] Get default avatar url from resources. --- interface/src/Application.cpp | 2 +- interface/src/avatar/Avatar.cpp | 4 ++-- interface/src/avatar/MyAvatar.cpp | 2 +- libraries/avatars/src/AvatarData.cpp | 12 +++++++++++- libraries/avatars/src/AvatarData.h | 8 +++++--- 5 files changed, 20 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 5dac571045..914356fa45 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4405,7 +4405,7 @@ void Application::checkSkeleton() { msgBox.setIcon(QMessageBox::Warning); msgBox.exec(); - _myAvatar->useFullAvatarURL(DEFAULT_FULL_AVATAR_MODEL_URL, DEFAULT_FULL_AVATAR_MODEL_NAME); + _myAvatar->useFullAvatarURL(AvatarData::defaultFullAvatarModelUrl(), DEFAULT_FULL_AVATAR_MODEL_NAME); } else { _physicsEngine.setCharacterController(_myAvatar->getCharacterController()); } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index b537d5a5d8..893c9a9370 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -952,12 +952,12 @@ void Avatar::scaleVectorRelativeToPosition(glm::vec3 &positionToScale) const { void Avatar::setFaceModelURL(const QUrl& faceModelURL) { AvatarData::setFaceModelURL(faceModelURL); - getHead()->getFaceModel().setURL(_faceModelURL, DEFAULT_FULL_AVATAR_MODEL_URL, true, !isMyAvatar()); + getHead()->getFaceModel().setURL(_faceModelURL, AvatarData::defaultFullAvatarModelUrl(), true, !isMyAvatar()); } void Avatar::setSkeletonModelURL(const QUrl& skeletonModelURL) { AvatarData::setSkeletonModelURL(skeletonModelURL); - _skeletonModel.setURL(_skeletonModelURL, DEFAULT_FULL_AVATAR_MODEL_URL, true, !isMyAvatar()); + _skeletonModel.setURL(_skeletonModelURL, AvatarData::defaultFullAvatarModelUrl(), true, !isMyAvatar()); } void Avatar::setAttachmentData(const QVector& attachmentData) { diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ddc0b0b9d1..6425169e57 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -721,7 +721,7 @@ void MyAvatar::loadData() { _targetScale = loadSetting(settings, "scale", 1.0f); setScale(_scale); - _fullAvatarURLFromPreferences = settings.value("fullAvatarURL", DEFAULT_FULL_AVATAR_MODEL_URL).toUrl(); + _fullAvatarURLFromPreferences = settings.value("fullAvatarURL", AvatarData::defaultFullAvatarModelUrl()).toUrl(); _fullAvatarModelName = settings.value("fullAvatarModelName", DEFAULT_FULL_AVATAR_MODEL_NAME).toString(); useFullAvatarURL(_fullAvatarURLFromPreferences, _fullAvatarModelName); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 78fa00eed7..afcc3a98b2 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -70,6 +70,16 @@ AvatarData::~AvatarData() { delete _referential; } +// We cannot have a file-level variable (const or otherwise) in the header if it uses PathUtils, because that references Application, which will not yet initialized. +// Thus we have a static class getter, referencing a static class var. +QUrl AvatarData::_defaultFullAvatarModelUrl = {}; // In C++, if this initialization were in the header, every file would have it's own copy, even for class vars. +const QUrl AvatarData::defaultFullAvatarModelUrl() { + if (_defaultFullAvatarModelUrl.isEmpty()) { + _defaultFullAvatarModelUrl = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_full.fst"); + } + return _defaultFullAvatarModelUrl; +} + const glm::vec3& AvatarData::getPosition() const { if (_referential) { _referential->update(); @@ -941,7 +951,7 @@ void AvatarData::setFaceModelURL(const QUrl& faceModelURL) { } void AvatarData::setSkeletonModelURL(const QUrl& skeletonModelURL) { - _skeletonModelURL = skeletonModelURL.isEmpty() ? DEFAULT_FULL_AVATAR_MODEL_URL : skeletonModelURL; + _skeletonModelURL = skeletonModelURL.isEmpty() ? AvatarData::defaultFullAvatarModelUrl() : skeletonModelURL; qCDebug(avatars) << "Changing skeleton model for avatar to" << _skeletonModelURL.toString(); diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 16003594c9..c4412e1d09 100644 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -48,13 +48,13 @@ typedef unsigned long long quint64; #include #include -//FIXME #include #include #include #include "AABox.h" #include "HandData.h" #include "HeadData.h" +#include "PathUtils.h" #include "Player.h" #include "Recorder.h" #include "Referential.h" @@ -108,8 +108,7 @@ const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation const int AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS = 1000; const int AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS = 5000; -//FIXME const QUrl DEFAULT_FULL_AVATAR_MODEL_URL = QUrl::fromLocalFile(PathUtils::resourcesPath() + "meshes/defaultAvatar_full.fst"); -const QUrl DEFAULT_FULL_AVATAR_MODEL_URL = QUrl("http://public.highfidelity.io/marketplace/contents/029db3d4-da2c-4cb2-9c08-b9612ba576f5/02949063e7c4aed42ad9d1a58461f56d.fst"); +// See also static AvatarData::defaultFullAvatarModelUrl(). const QString DEFAULT_FULL_AVATAR_MODEL_NAME = QString("Default"); @@ -160,6 +159,8 @@ public: AvatarData(); virtual ~AvatarData(); + static const QUrl defaultFullAvatarModelUrl(); + virtual bool isMyAvatar() const { return false; } const QUuid& getSessionUUID() const { return _sessionUUID; } @@ -398,6 +399,7 @@ protected: SimpleMovingAverage _averageBytesReceived; private: + static QUrl _defaultFullAvatarModelUrl; // privatize the copy constructor and assignment operator so they cannot be called AvatarData(const AvatarData&); AvatarData& operator= (const AvatarData&); From a8a064990f64cd17257a0fdaeb6749571bacde23 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 13 Aug 2015 14:42:37 -0700 Subject: [PATCH 10/47] apperance => appearance --- interface/src/ui/PreferencesDialog.cpp | 6 +++--- interface/ui/preferencesDialog.ui | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 59701e5cf3..8479f6778c 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -47,8 +47,8 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : connect(ui.buttonBrowseScriptsLocation, &QPushButton::clicked, this, &PreferencesDialog::openScriptsLocationBrowser); connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, Application::getInstance(), &Application::loadDefaultScripts); - connect(ui.buttonChangeApperance, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser); - connect(ui.apperanceDescription, &QLineEdit::textChanged, this, [this](const QString& url) { + connect(ui.buttonChangeAppearance, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser); + connect(ui.appearanceDescription, &QLineEdit::textChanged, this, [this](const QString& url) { this->fullAvatarURLChanged(url, ""); }); connect(Application::getInstance(), &Application::fullAvatarURLChanged, this, &PreferencesDialog::fullAvatarURLChanged); @@ -61,7 +61,7 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : } void PreferencesDialog::fullAvatarURLChanged(const QString& newValue, const QString& modelName) { - ui.apperanceDescription->setText(newValue); + ui.appearanceDescription->setText(newValue); const QString APPEARANCE_LABEL_TEXT("Appearance: "); ui.appearanceLabel->setText(APPEARANCE_LABEL_TEXT + modelName); DependencyManager::get()->getMyAvatar()->useFullAvatarURL(newValue, modelName); diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui index 71103da654..b91367dcf1 100644 --- a/interface/ui/preferencesDialog.ui +++ b/interface/ui/preferencesDialog.ui @@ -275,7 +275,7 @@ Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft - apperanceDescription + appearanceDescription @@ -283,12 +283,12 @@ - + 0 - + Arial @@ -297,7 +297,7 @@ - + Qt::Horizontal @@ -313,7 +313,7 @@ - + Arial From 74dc6a3dc54b53b541b99195a7f752bb422771e9 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 13 Aug 2015 14:43:39 -0700 Subject: [PATCH 11/47] updateMotionBehavior => updateMotionBehaviorFromMenu --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 44f336e996..6d39326195 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -258,7 +258,7 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::NamesAboveHeads, 0, true); addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::BlueSpeechSphere, 0, true); addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::EnableCharacterController, 0, true, - avatar, SLOT(updateMotionBehavior())); + avatar, SLOT(updateMotionBehaviorFromMenu())); MenuWrapper* viewMenu = addMenu("View"); addActionToQMenuAndActionHash(viewMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); From 7d4c96cc29bd5ab021f969bea213cf7daeaa2b42 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 13 Aug 2015 14:53:12 -0700 Subject: [PATCH 12/47] avartar => avatar --- interface/src/avatar/MyAvatar.h | 2 +- interface/src/ui/PreferencesDialog.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 0cd56ec99c..8ff9211101 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -127,7 +127,7 @@ public: Q_INVOKABLE void useFullAvatarURL(const QUrl& fullAvatarURL, const QString& modelName = QString()); Q_INVOKABLE const QUrl& getFullAvatarURLFromPreferences() const { return _fullAvatarURLFromPreferences; } - Q_INVOKABLE const QString& getFullAvartarModelName() const { return _fullAvatarModelName; } + Q_INVOKABLE const QString& getFullAvatarModelName() const { return _fullAvatarModelName; } virtual void setAttachmentData(const QVector& attachmentData); diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 8479f6778c..41b91d65c3 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -128,7 +128,7 @@ void PreferencesDialog::loadPreferences() { ui.collisionSoundURLEdit->setText(myAvatar->getCollisionSoundURL()); fullAvatarURLChanged(myAvatar->getFullAvatarURLFromPreferences().toString(), - myAvatar->getFullAvartarModelName()); + myAvatar->getFullAvatarModelName()); ui.sendDataCheckBox->setChecked(!menuInstance->isOptionChecked(MenuOption::DisableActivityLogger)); From 722c024f610aaf9ce558303e6bee1a2e594216e8 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 13 Aug 2015 15:08:26 -0700 Subject: [PATCH 13/47] Remove obsolete code. --- interface/src/avatar/FaceModel.cpp | 56 ------------------------------ interface/src/avatar/FaceModel.h | 4 --- 2 files changed, 60 deletions(-) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index e31c804185..0e8e5a6a91 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -47,66 +47,10 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) { if (isActive()) { setOffset(-_geometry->getFBXGeometry().neckPivot); - - for (int i = 0; i < _rig->getJointStateCount(); i++) { - maybeUpdateNeckAndEyeRotation(i); - } - Model::simulateInternal(deltaTime); } } -void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const JointState& state, int index) { - // get the rotation axes in joint space and use them to adjust the rotation - glm::mat3 axes = glm::mat3_cast(glm::quat()); - glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * - glm::translate(_rig->getJointDefaultTranslationInConstrainedFrame(index)) * - state.getPreTransform() * glm::mat4_cast(state.getPreRotation()))); - glm::vec3 pitchYawRoll = safeEulerAngles(_owningHead->getFinalOrientationInLocalFrame()); - glm::vec3 lean = glm::radians(glm::vec3(_owningHead->getFinalLeanForward(), - _owningHead->getTorsoTwist(), - _owningHead->getFinalLeanSideways())); - pitchYawRoll -= lean; - _rig->setJointRotationInConstrainedFrame(index, - glm::angleAxis(-pitchYawRoll.z, glm::normalize(inverse * axes[2])) - * glm::angleAxis(pitchYawRoll.y, glm::normalize(inverse * axes[1])) - * glm::angleAxis(-pitchYawRoll.x, glm::normalize(inverse * axes[0])) - * state.getDefaultRotation(), DEFAULT_PRIORITY); -} - -void FaceModel::maybeUpdateEyeRotation(Model* model, const JointState& parentState, const JointState& state, int index) { - // likewise with the eye joints - // NOTE: at the moment we do the math in the world-frame, hence the inverse transform is more complex than usual. - glm::mat4 inverse = glm::inverse(glm::mat4_cast(model->getRotation()) * parentState.getTransform() * - glm::translate(_rig->getJointDefaultTranslationInConstrainedFrame(index)) * - state.getPreTransform() * glm::mat4_cast(state.getPreRotation() * state.getDefaultRotation())); - glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientationInWorldFrame() * IDENTITY_FRONT, 0.0f)); - glm::vec3 lookAtDelta = _owningHead->getCorrectedLookAtPosition() - model->getTranslation(); - glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(lookAtDelta + glm::length(lookAtDelta) * _owningHead->getSaccade(), 1.0f)); - glm::quat between = rotationBetween(front, lookAt); - const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE; - _rig->setJointRotationInConstrainedFrame(index, glm::angleAxis(glm::clamp(glm::angle(between), - -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) * - state.getDefaultRotation(), DEFAULT_PRIORITY); -} - -void FaceModel::maybeUpdateNeckAndEyeRotation(int index) { - const JointState& state = _rig->getJointState(index); - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - const int parentIndex = state.getParentIndex(); - - // guard against out-of-bounds access to _jointStates - if (parentIndex != -1 && parentIndex >= 0 && parentIndex < _rig->getJointStateCount()) { - const JointState& parentState = _rig->getJointState(parentIndex); - if (index == geometry.neckJointIndex) { - maybeUpdateNeckRotation(parentState, state, index); - - } else if (index == geometry.leftEyeJointIndex || index == geometry.rightEyeJointIndex) { - maybeUpdateEyeRotation(this, parentState, state, index); - } - } -} - bool FaceModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const { if (!isActive()) { return false; diff --git a/interface/src/avatar/FaceModel.h b/interface/src/avatar/FaceModel.h index ed1ea28508..5a19a8ea29 100644 --- a/interface/src/avatar/FaceModel.h +++ b/interface/src/avatar/FaceModel.h @@ -26,10 +26,6 @@ public: virtual void simulate(float deltaTime, bool fullUpdate = true); - void maybeUpdateNeckRotation(const JointState& parentState, const JointState& state, int index); - void maybeUpdateEyeRotation(Model* model, const JointState& parentState, const JointState& state, int index); - void maybeUpdateNeckAndEyeRotation(int index); - /// Retrieve the positions of up to two eye meshes. /// \return whether or not both eye meshes were found bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const; From 63608d8012c2c64c98ec8cc4ce4d9020a4675a3a Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 13 Aug 2015 15:55:43 -0700 Subject: [PATCH 14/47] Undo avatar choice if the whole preferences dialog is cancelled. --- interface/src/ui/PreferencesDialog.cpp | 23 ++++++++++++++++++++--- interface/src/ui/PreferencesDialog.h | 4 ++++ 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 41b91d65c3..63170fdd70 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -68,12 +68,24 @@ void PreferencesDialog::fullAvatarURLChanged(const QString& newValue, const QStr } void PreferencesDialog::accept() { + MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); + _lastGoodAvatarURL = myAvatar->getFullAvatarURLFromPreferences(); + _lastGoodAvatarName = myAvatar->getFullAvatarModelName(); savePreferences(); close(); delete _marketplaceWindow; _marketplaceWindow = NULL; } +void PreferencesDialog::restoreLastGoodAvatar() { + fullAvatarURLChanged(_lastGoodAvatarURL.toString(), _lastGoodAvatarName); +} + +void PreferencesDialog::reject() { + restoreLastGoodAvatar(); + QDialog::reject(); +} + void PreferencesDialog::openSnapshotLocationBrowser() { QString dir = QFileDialog::getExistingDirectory(this, tr("Snapshots Location"), QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), @@ -127,8 +139,9 @@ void PreferencesDialog::loadPreferences() { ui.collisionSoundURLEdit->setText(myAvatar->getCollisionSoundURL()); - fullAvatarURLChanged(myAvatar->getFullAvatarURLFromPreferences().toString(), - myAvatar->getFullAvatarModelName()); + _lastGoodAvatarURL = myAvatar->getFullAvatarURLFromPreferences(); + _lastGoodAvatarName = myAvatar->getFullAvatarModelName(); + fullAvatarURLChanged(_lastGoodAvatarURL.toString(), _lastGoodAvatarName); ui.sendDataCheckBox->setChecked(!menuInstance->isOptionChecked(MenuOption::DisableActivityLogger)); @@ -211,7 +224,11 @@ void PreferencesDialog::savePreferences() { } myAvatar->setCollisionSoundURL(ui.collisionSoundURLEdit->text()); - // avatar model url is already persisted by fullAvatarURLChanged() + + // MyAvatar persists its own data. If it doesn't agree with what the user has explicitly accepted, set it back to old values. + if (_lastGoodAvatarURL != myAvatar->getFullAvatarURLFromPreferences()) { + restoreLastGoodAvatar(); + } if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger) != ui.sendDataCheckBox->isChecked()) { diff --git a/interface/src/ui/PreferencesDialog.h b/interface/src/ui/PreferencesDialog.h index 47341b8feb..6d7a87b97c 100644 --- a/interface/src/ui/PreferencesDialog.h +++ b/interface/src/ui/PreferencesDialog.h @@ -33,6 +33,9 @@ protected: private: void loadPreferences(); void savePreferences(); + QUrl _lastGoodAvatarURL; + QString _lastGoodAvatarName; + void restoreLastGoodAvatar(); Ui_PreferencesDialog ui; @@ -42,6 +45,7 @@ private: private slots: void accept(); + void reject(); void openFullAvatarModelBrowser(); void openSnapshotLocationBrowser(); void openScriptsLocationBrowser(); From f00d3c037d99584892dcc468cd3b2509ae45205a Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 13 Aug 2015 17:36:03 -0700 Subject: [PATCH 15/47] whitespace --- interface/src/ui/PreferencesDialog.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 63170fdd70..a6340d3955 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -48,9 +48,9 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : connect(ui.buttonReloadDefaultScripts, &QPushButton::clicked, Application::getInstance(), &Application::loadDefaultScripts); connect(ui.buttonChangeAppearance, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser); - connect(ui.appearanceDescription, &QLineEdit::textChanged, this, [this](const QString& url) { - this->fullAvatarURLChanged(url, ""); - }); + connect(ui.appearanceDescription, &QLineEdit::textChanged, this, [this](const QString& url) { + this->fullAvatarURLChanged(url, ""); + }); connect(Application::getInstance(), &Application::fullAvatarURLChanged, this, &PreferencesDialog::fullAvatarURLChanged); // move dialog to left side From 27e5322cb4275276efb0828865553188e1491754 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 15 Aug 2015 11:25:27 -0700 Subject: [PATCH 16/47] compute polyvox collision hull differently for marching-cube surfaces --- .../src/RenderablePolyVoxEntityItem.cpp | 132 ++++++++++++------ 1 file changed, 91 insertions(+), 41 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 23093b9f3f..be2d9b8fe6 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -40,7 +40,7 @@ #include "EntityTreeRenderer.h" #include "polyvox_vert.h" #include "polyvox_frag.h" -#include "RenderablePolyVoxEntityItem.h" +#include "RenderablePolyVoxEntityItem.h" gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipeline = nullptr; @@ -553,53 +553,103 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { } _points.clear(); - unsigned int i = 0; - - glm::mat4 wToM = voxelToLocalMatrix(); - AABox box; + glm::mat4 vtoM = voxelToLocalMatrix(); - for (int z = 0; z < _voxelVolumeSize.z; z++) { - for (int y = 0; y < _voxelVolumeSize.y; y++) { - for (int x = 0; x < _voxelVolumeSize.x; x++) { - if (getVoxel(x, y, z) > 0) { - QVector pointsInPart; + if (_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_MARCHING_CUBES) { + unsigned int i = 0; + /* pull top-facing triangles into polyhedrons so they can be walked on */ + const model::MeshPointer& mesh = _modelGeometry.getMesh(); + const gpu::BufferView vertexBufferView = mesh->getVertexBuffer(); + const gpu::BufferView& indexBufferView = mesh->getIndexBuffer(); + gpu::BufferView::Iterator it = indexBufferView.cbegin(); + while (it != indexBufferView.cend()) { + uint32_t p0Index = *(it++); + uint32_t p1Index = *(it++); + uint32_t p2Index = *(it++); - float offL = -0.5f; - float offH = 0.5f; + const glm::vec3 p0 = vertexBufferView.get(p0Index); + const glm::vec3 p1 = vertexBufferView.get(p1Index); + const glm::vec3 p2 = vertexBufferView.get(p2Index); - glm::vec3 p000 = glm::vec3(wToM * glm::vec4(x + offL, y + offL, z + offL, 1.0f)); - glm::vec3 p001 = glm::vec3(wToM * glm::vec4(x + offL, y + offL, z + offH, 1.0f)); - glm::vec3 p010 = glm::vec3(wToM * glm::vec4(x + offL, y + offH, z + offL, 1.0f)); - glm::vec3 p011 = glm::vec3(wToM * glm::vec4(x + offL, y + offH, z + offH, 1.0f)); - glm::vec3 p100 = glm::vec3(wToM * glm::vec4(x + offH, y + offL, z + offL, 1.0f)); - glm::vec3 p101 = glm::vec3(wToM * glm::vec4(x + offH, y + offL, z + offH, 1.0f)); - glm::vec3 p110 = glm::vec3(wToM * glm::vec4(x + offH, y + offH, z + offL, 1.0f)); - glm::vec3 p111 = glm::vec3(wToM * glm::vec4(x + offH, y + offH, z + offH, 1.0f)); + qDebug() << p0Index << p1Index << p2Index; + qDebug() << (int)p0.x << (int)p0.y << (int)p0.z; - box += p000; - box += p001; - box += p010; - box += p011; - box += p100; - box += p101; - box += p110; - box += p111; + glm::vec3 av = (p0 + p1 + p2) / 3.0f; // center of the triangular face + glm::vec3 normal = glm::normalize(glm::cross(p1 - p0, p2 - p0)); + float threshold = 1.0f / sqrtf(3.0f); + if (normal.y > -threshold && normal.y < threshold) { + // this triangle is more a wall than a floor, skip it. + } else { + float dropAmount = 2.0f; // XXX magic + glm::vec3 p3 = av - glm::vec3(0.0f, dropAmount, 0.0f); - pointsInPart << p000; - pointsInPart << p001; - pointsInPart << p010; - pointsInPart << p011; - pointsInPart << p100; - pointsInPart << p101; - pointsInPart << p110; - pointsInPart << p111; + glm::vec3 p0Model = glm::vec3(vtoM * glm::vec4(p0, 1.0f)); + glm::vec3 p1Model = glm::vec3(vtoM * glm::vec4(p1, 1.0f)); + glm::vec3 p2Model = glm::vec3(vtoM * glm::vec4(p2, 1.0f)); + glm::vec3 p3Model = glm::vec3(vtoM * glm::vec4(p3, 1.0f)); - // add next convex hull - QVector newMeshPoints; - _points << newMeshPoints; - // add points to the new convex hull - _points[i++] << pointsInPart; + box += p0Model; + box += p1Model; + box += p2Model; + box += p3Model; + + QVector pointsInPart; + pointsInPart << p0Model; + pointsInPart << p1Model; + pointsInPart << p2Model; + pointsInPart << p3Model; + // add next convex hull + QVector newMeshPoints; + _points << newMeshPoints; + // add points to the new convex hull + _points[i++] << pointsInPart; + } + } + } else { + unsigned int i = 0; + for (int z = 0; z < _voxelVolumeSize.z; z++) { + for (int y = 0; y < _voxelVolumeSize.y; y++) { + for (int x = 0; x < _voxelVolumeSize.x; x++) { + if (getVoxel(x, y, z) > 0) { + QVector pointsInPart; + + float offL = -0.5f; + float offH = 0.5f; + + glm::vec3 p000 = glm::vec3(vtoM * glm::vec4(x + offL, y + offL, z + offL, 1.0f)); + glm::vec3 p001 = glm::vec3(vtoM * glm::vec4(x + offL, y + offL, z + offH, 1.0f)); + glm::vec3 p010 = glm::vec3(vtoM * glm::vec4(x + offL, y + offH, z + offL, 1.0f)); + glm::vec3 p011 = glm::vec3(vtoM * glm::vec4(x + offL, y + offH, z + offH, 1.0f)); + glm::vec3 p100 = glm::vec3(vtoM * glm::vec4(x + offH, y + offL, z + offL, 1.0f)); + glm::vec3 p101 = glm::vec3(vtoM * glm::vec4(x + offH, y + offL, z + offH, 1.0f)); + glm::vec3 p110 = glm::vec3(vtoM * glm::vec4(x + offH, y + offH, z + offL, 1.0f)); + glm::vec3 p111 = glm::vec3(vtoM * glm::vec4(x + offH, y + offH, z + offH, 1.0f)); + + box += p000; + box += p001; + box += p010; + box += p011; + box += p100; + box += p101; + box += p110; + box += p111; + + pointsInPart << p000; + pointsInPart << p001; + pointsInPart << p010; + pointsInPart << p011; + pointsInPart << p100; + pointsInPart << p101; + pointsInPart << p110; + pointsInPart << p111; + + // add next convex hull + QVector newMeshPoints; + _points << newMeshPoints; + // add points to the new convex hull + _points[i++] << pointsInPart; + } } } } From 79a7755cdbc762163394195d5de829ba2ba0405f Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 15 Aug 2015 12:18:36 -0700 Subject: [PATCH 17/47] add SURFACE_EDGED_MARCHING_CUBES polyvox surface extraction style --- examples/html/entityProperties.html | 1 + .../src/RenderablePolyVoxEntityItem.cpp | 21 +++++++++++-------- libraries/entities/src/PolyVoxEntityItem.h | 3 ++- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index a2358b40d5..ad489afddf 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -1072,6 +1072,7 @@ + diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index be2d9b8fe6..07026f073c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -78,6 +78,7 @@ bool inUserBounds(const PolyVox::SimpleVolume* vol, PolyVoxEntityItem:: return true; case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: + case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: if (x < 0 || y < 0 || z < 0 || x >= vol->getWidth() - 2 || y >= vol->getHeight() - 2 || z >= vol->getDepth() - 2) { return false; @@ -112,7 +113,7 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) _onCount = 0; - if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC) { + if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) { // with _EDGED_ we maintain an extra box of voxels around those that the user asked for. This // changes how the surface extractor acts -- mainly it becomes impossible to have holes in the // generated mesh. The non _EDGED_ modes will leave holes in the mesh at the edges of the @@ -156,8 +157,7 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) void RenderablePolyVoxEntityItem::updateVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) { // if we are switching to or from "edged" we need to force a resize of _volData. - if (voxelSurfaceStyle == SURFACE_EDGED_CUBIC || - _voxelSurfaceStyle == SURFACE_EDGED_CUBIC) { + if (voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) { if (_volData) { delete _volData; } @@ -182,11 +182,11 @@ glm::vec3 RenderablePolyVoxEntityItem::getSurfacePositionAdjustment() const { glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units switch (_voxelSurfaceStyle) { case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: - return scale / 2.0f; - case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: - return scale / -2.0f; case PolyVoxEntityItem::SURFACE_CUBIC: return scale / 2.0f; + case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: + case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: + return scale / -2.0f; } return glm::vec3(0.0f, 0.0f, 0.0f); } @@ -223,7 +223,7 @@ uint8_t RenderablePolyVoxEntityItem::getVoxel(int x, int y, int z) { // voxels all around the requested voxel space. Having the empty voxels around // the edges changes how the surface extractor behaves. - if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC) { + if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) { return _volData->getVoxelAt(x + 1, y + 1, z + 1); } return _volData->getVoxelAt(x, y, z); @@ -238,7 +238,7 @@ void RenderablePolyVoxEntityItem::setVoxelInternal(int x, int y, int z, uint8_t updateOnCount(x, y, z, toValue); - if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC) { + if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) { _volData->setVoxelAt(x + 1, y + 1, z + 1, toValue); } else { _volData->setVoxelAt(x, y, z, toValue); @@ -399,6 +399,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o glm::vec4 result = callback._result; switch (_voxelSurfaceStyle) { case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: + case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: result -= glm::vec4(1, 1, 1, 0); // compensate for the extra voxel border break; case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: @@ -556,7 +557,8 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { AABox box; glm::mat4 vtoM = voxelToLocalMatrix(); - if (_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_MARCHING_CUBES) { + if (_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_MARCHING_CUBES || + _voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES) { unsigned int i = 0; /* pull top-facing triangles into polyhedrons so they can be walked on */ const model::MeshPointer& mesh = _modelGeometry.getMesh(); @@ -683,6 +685,7 @@ void RenderablePolyVoxEntityItem::getModel() { PolyVox::SurfaceMesh polyVoxMesh; switch (_voxelSurfaceStyle) { + case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: { PolyVox::MarchingCubesSurfaceExtractor> surfaceExtractor (_volData, _volData->getEnclosingRegion(), &polyVoxMesh); diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 0d0ab060f9..29d0b2e595 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -58,7 +58,8 @@ class PolyVoxEntityItem : public EntityItem { enum PolyVoxSurfaceStyle { SURFACE_MARCHING_CUBES, SURFACE_CUBIC, - SURFACE_EDGED_CUBIC + SURFACE_EDGED_CUBIC, + SURFACE_EDGED_MARCHING_CUBES }; void setVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle); From 09a9deabdbfd3a19038135f145da2746b1a65781 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 15 Aug 2015 12:55:24 -0700 Subject: [PATCH 18/47] compute polyvox collision hull differently for marching-cube surfaces --- .../src/RenderablePolyVoxEntityItem.cpp | 50 ++++++++----------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 07026f073c..b803e32e1e 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -43,6 +43,7 @@ #include "RenderablePolyVoxEntityItem.h" gpu::PipelinePointer RenderablePolyVoxEntityItem::_pipeline = nullptr; +const float MARCHING_CUBE_COLLISION_HULL_OFFSET = 0.5; EntityItemPointer RenderablePolyVoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) { return std::make_shared(entityID, properties); @@ -574,39 +575,30 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { const glm::vec3 p1 = vertexBufferView.get(p1Index); const glm::vec3 p2 = vertexBufferView.get(p2Index); - qDebug() << p0Index << p1Index << p2Index; - qDebug() << (int)p0.x << (int)p0.y << (int)p0.z; - glm::vec3 av = (p0 + p1 + p2) / 3.0f; // center of the triangular face glm::vec3 normal = glm::normalize(glm::cross(p1 - p0, p2 - p0)); - float threshold = 1.0f / sqrtf(3.0f); - if (normal.y > -threshold && normal.y < threshold) { - // this triangle is more a wall than a floor, skip it. - } else { - float dropAmount = 2.0f; // XXX magic - glm::vec3 p3 = av - glm::vec3(0.0f, dropAmount, 0.0f); + glm::vec3 p3 = av - normal * MARCHING_CUBE_COLLISION_HULL_OFFSET; - glm::vec3 p0Model = glm::vec3(vtoM * glm::vec4(p0, 1.0f)); - glm::vec3 p1Model = glm::vec3(vtoM * glm::vec4(p1, 1.0f)); - glm::vec3 p2Model = glm::vec3(vtoM * glm::vec4(p2, 1.0f)); - glm::vec3 p3Model = glm::vec3(vtoM * glm::vec4(p3, 1.0f)); + glm::vec3 p0Model = glm::vec3(vtoM * glm::vec4(p0, 1.0f)); + glm::vec3 p1Model = glm::vec3(vtoM * glm::vec4(p1, 1.0f)); + glm::vec3 p2Model = glm::vec3(vtoM * glm::vec4(p2, 1.0f)); + glm::vec3 p3Model = glm::vec3(vtoM * glm::vec4(p3, 1.0f)); - box += p0Model; - box += p1Model; - box += p2Model; - box += p3Model; + box += p0Model; + box += p1Model; + box += p2Model; + box += p3Model; - QVector pointsInPart; - pointsInPart << p0Model; - pointsInPart << p1Model; - pointsInPart << p2Model; - pointsInPart << p3Model; - // add next convex hull - QVector newMeshPoints; - _points << newMeshPoints; - // add points to the new convex hull - _points[i++] << pointsInPart; - } + QVector pointsInPart; + pointsInPart << p0Model; + pointsInPart << p1Model; + pointsInPart << p2Model; + pointsInPart << p3Model; + // add next convex hull + QVector newMeshPoints; + _points << newMeshPoints; + // add points to the new convex hull + _points[i++] << pointsInPart; } } else { unsigned int i = 0; @@ -790,8 +782,6 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { _zTexture = DependencyManager::get()->getTexture(_zTextureURL); } - batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - if (_xTexture) { batch.setResourceTexture(0, _xTexture->getGPUTexture()); } else { From 5ecdbaa19d591cbd4f51f6914cfe696c63a58161 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 15 Aug 2015 15:18:25 -0700 Subject: [PATCH 19/47] have functions that change polyvox voxes return true if they changed anything, else false. added voxelCoordsToWorldCoords and worldCoordsToVoxelCoords --- examples/voxels.js | 16 +++- .../src/RenderablePolyVoxEntityItem.cpp | 59 +++++++++------ .../src/RenderablePolyVoxEntityItem.h | 18 ++--- .../entities/src/EntityScriptingInterface.cpp | 75 ++++++++++++++----- .../entities/src/EntityScriptingInterface.h | 5 +- libraries/entities/src/PolyVoxEntityItem.h | 15 ++-- 6 files changed, 128 insertions(+), 60 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index 9627b40701..c70111153b 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -7,10 +7,15 @@ function attemptVoxelChange(intersection) { var success = false; for (var i = 0; i < ids.length; i++) { var id = ids[i]; + // var voxelCoords = Entities.worldCoordsToVoxelCoords(id, intersection.intersection); + if (controlHeld) { // hold control to erase a sphere - if (Entities.setVoxelSphere(id, intersection.intersection, 1.0, 0)) { - success = true; + for (var r = 1.0; r < 17.0; r++) { + if (Entities.setVoxelSphere(id, intersection.intersection, r, 0)) { + success = true; + break; + } } } else if (shiftHeld) { // hold shift to set all voxels to 255 @@ -19,8 +24,11 @@ function attemptVoxelChange(intersection) { } } else { // no modifier key means to add a sphere - if (Entities.setVoxelSphere(id, intersection.intersection, 1.0, 255)) { - success = true; + for (var r = 1.0; r < 17.0; r++) { + if (Entities.setVoxelSphere(id, intersection.intersection, r, 255)) { + success = true; + break; + } } } } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index b803e32e1e..5b0c4ee691 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -230,78 +230,88 @@ uint8_t RenderablePolyVoxEntityItem::getVoxel(int x, int y, int z) { return _volData->getVoxelAt(x, y, z); } -void RenderablePolyVoxEntityItem::setVoxelInternal(int x, int y, int z, uint8_t toValue) { +bool RenderablePolyVoxEntityItem::setVoxelInternal(int x, int y, int z, uint8_t toValue) { // set a voxel without recompressing the voxel data assert(_volData); + bool result = false; if (!inUserBounds(_volData, _voxelSurfaceStyle, x, y, z)) { - return; + return false; } - updateOnCount(x, y, z, toValue); + result = updateOnCount(x, y, z, toValue); if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) { _volData->setVoxelAt(x + 1, y + 1, z + 1, toValue); } else { _volData->setVoxelAt(x, y, z, toValue); } + + return result; } -void RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) { +bool RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) { if (_locked) { - return; + return false; } - setVoxelInternal(x, y, z, toValue); + bool result = setVoxelInternal(x, y, z, toValue); compressVolumeData(); + return result; } -void RenderablePolyVoxEntityItem::updateOnCount(int x, int y, int z, uint8_t toValue) { +bool RenderablePolyVoxEntityItem::updateOnCount(int x, int y, int z, uint8_t toValue) { // keep _onCount up to date if (!inUserBounds(_volData, _voxelSurfaceStyle, x, y, z)) { - return; + return false; } uint8_t uVoxelValue = getVoxel(x, y, z); if (toValue != 0) { if (uVoxelValue == 0) { _onCount++; + return true; } } else { // toValue == 0 if (uVoxelValue != 0) { _onCount--; assert(_onCount >= 0); + return true; } } + return false; } -void RenderablePolyVoxEntityItem::setAll(uint8_t toValue) { +bool RenderablePolyVoxEntityItem::setAll(uint8_t toValue) { + bool result = false; if (_locked) { - return; + return false; } for (int z = 0; z < _voxelVolumeSize.z; z++) { for (int y = 0; y < _voxelVolumeSize.y; y++) { for (int x = 0; x < _voxelVolumeSize.x; x++) { - setVoxelInternal(x, y, z, toValue); + result |= setVoxelInternal(x, y, z, toValue); } } } compressVolumeData(); + return result; } -void RenderablePolyVoxEntityItem::setVoxelInVolume(glm::vec3 position, uint8_t toValue) { +bool RenderablePolyVoxEntityItem::setVoxelInVolume(glm::vec3 position, uint8_t toValue) { if (_locked) { - return; + return false; } // same as setVoxel but takes a vector rather than 3 floats. - setVoxel((int)position.x, (int)position.y, (int)position.z, toValue); + return setVoxel((int)position.x, (int)position.y, (int)position.z, toValue); } -void RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) { +bool RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) { + bool result = false; if (_locked) { - return; + return false; } // This three-level for loop iterates over every voxel in the volume @@ -314,22 +324,22 @@ void RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radi float fDistToCenter = glm::distance(pos, center); // If the current voxel is less than 'radius' units from the center then we make it solid. if (fDistToCenter <= radius) { - updateOnCount(x, y, z, toValue); - setVoxelInternal(x, y, z, toValue); + result |= setVoxelInternal(x, y, z, toValue); } } } } compressVolumeData(); + return result; } -void RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords, uint8_t toValue) { +bool RenderablePolyVoxEntityItem::setSphere(glm::vec3 centerWorldCoords, float radiusWorldCoords, uint8_t toValue) { // glm::vec3 centerVoxelCoords = worldToVoxelCoordinates(centerWorldCoords); glm::vec4 centerVoxelCoords = worldToVoxelMatrix() * glm::vec4(centerWorldCoords, 1.0f); glm::vec3 scale = getDimensions() / _voxelVolumeSize; // meters / voxel-units float scaleY = scale.y; float radiusVoxelCoords = radiusWorldCoords / scaleY; - setSphereInVolume(glm::vec3(centerVoxelCoords), radiusVoxelCoords, toValue); + return setSphereInVolume(glm::vec3(centerVoxelCoords), radiusVoxelCoords, toValue); } class RaycastFunctor @@ -508,7 +518,6 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() { for (int y = 0; y < voxelYSize; y++) { for (int x = 0; x < voxelXSize; x++) { int uncompressedIndex = (z * voxelYSize * voxelXSize) + (y * voxelZSize) + x; - updateOnCount(x, y, z, uncompressedData[uncompressedIndex]); setVoxelInternal(x, y, z, uncompressedData[uncompressedIndex]); } } @@ -845,3 +854,11 @@ namespace render { } } } + +glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToWorldCoords(glm::vec3 voxelCoords) { + return glm::vec3(voxelToWorldMatrix() * glm::vec4(voxelCoords, 1.0f)); +} + +glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3 worldCoords) { + return glm::vec3(worldToVoxelMatrix() * glm::vec4(worldCoords, 1.0f)); +} diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index d495900ce9..17c8934577 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -54,9 +54,9 @@ public: } virtual uint8_t getVoxel(int x, int y, int z); - virtual void setVoxel(int x, int y, int z, uint8_t toValue); + virtual bool setVoxel(int x, int y, int z, uint8_t toValue); - void updateOnCount(int x, int y, int z, uint8_t new_value); + bool updateOnCount(int x, int y, int z, uint8_t new_value); void render(RenderArgs* args); virtual bool supportsDetailedRayIntersection() const { return true; } @@ -78,16 +78,16 @@ public: virtual bool isReadyToComputeShape(); virtual void computeShapeInfo(ShapeInfo& info); + virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3 voxelCoords); + virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3 worldCoords); // coords are in voxel-volume space - virtual void setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue); + virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue); + virtual bool setVoxelInVolume(glm::vec3 position, uint8_t toValue); // coords are in world-space - virtual void setSphere(glm::vec3 center, float radius, uint8_t toValue); - - virtual void setAll(uint8_t toValue); - - virtual void setVoxelInVolume(glm::vec3 position, uint8_t toValue); + virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue); + virtual bool setAll(uint8_t toValue); virtual void setXTextureURL(QString xTextureURL); virtual void setYTextureURL(QString yTextureURL); @@ -107,7 +107,7 @@ private: // The PolyVoxEntityItem class has _voxelData which contains dimensions and compressed voxel data. The dimensions // may not match _voxelVolumeSize. - void setVoxelInternal(int x, int y, int z, uint8_t toValue); + bool setVoxelInternal(int x, int y, int z, uint8_t toValue); void compressVolumeData(); void decompressVolumeData(); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 9654de0fc4..c3e71cef82 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -415,7 +415,7 @@ void RayToEntityIntersectionResultFromScriptValue(const QScriptValue& object, Ra } bool EntityScriptingInterface::setVoxels(QUuid entityID, - std::function actor) { + std::function actor) { if (!_entityTree) { return false; } @@ -435,7 +435,7 @@ bool EntityScriptingInterface::setVoxels(QUuid entityID, auto polyVoxEntity = std::dynamic_pointer_cast(entity); _entityTree->lockForWrite(); - actor(*polyVoxEntity); + bool result = actor(*polyVoxEntity); entity->setLastEdited(now); entity->setLastBroadcast(now); _entityTree->unlock(); @@ -448,42 +448,41 @@ bool EntityScriptingInterface::setVoxels(QUuid entityID, properties.setLastEdited(now); queueEntityMessage(PacketType::EntityEdit, entityID, properties); - return true; + return result; } bool EntityScriptingInterface::setPoints(QUuid entityID, std::function actor) { if (!_entityTree) { return false; } - + EntityItemPointer entity = static_cast(_entityTree->findEntityByEntityItemID(entityID)); if (!entity) { qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID; } - + EntityTypes::EntityType entityType = entity->getType(); - + if (entityType != EntityTypes::Line) { return false; } - + auto now = usecTimestampNow(); - + auto lineEntity = std::static_pointer_cast(entity); _entityTree->lockForWrite(); bool success = actor(*lineEntity); entity->setLastEdited(now); entity->setLastBroadcast(now); _entityTree->unlock(); - + _entityTree->lockForRead(); EntityItemProperties properties = entity->getProperties(); _entityTree->unlock(); - + properties.setLinePointsDirty(); properties.setLastEdited(now); - - + queueEntityMessage(PacketType::EntityEdit, entityID, properties); return success; } @@ -491,19 +490,19 @@ bool EntityScriptingInterface::setPoints(QUuid entityID, std::functiongetType(); - + if (entityType == EntityTypes::Line) { return setPoints(entityID, [points](LineEntityItem& lineEntity) -> bool { return (LineEntityItem*)lineEntity.setLinePoints(points); }); } - + return false; } @@ -658,3 +657,43 @@ QVariantMap EntityScriptingInterface::getActionArguments(const QUuid& entityID, }); return result; } + +glm::vec3 EntityScriptingInterface::voxelCoordsToWorldCoords(const QUuid& entityID, glm::vec3 voxelCoords) { + if (!_entityTree) { + return glm::vec3(0.0f); + } + + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID); + if (!entity) { + qCDebug(entities) << "EntityScriptingInterface::voxelCoordsToWorldCoords no entity with ID" << entityID; + return glm::vec3(0.0f); + } + + EntityTypes::EntityType entityType = entity->getType(); + if (entityType != EntityTypes::PolyVox) { + return glm::vec3(0.0f); + } + + auto polyVoxEntity = std::dynamic_pointer_cast(entity); + return polyVoxEntity->voxelCoordsToWorldCoords(voxelCoords); +} + +glm::vec3 EntityScriptingInterface::worldCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 worldCoords) { + if (!_entityTree) { + return glm::vec3(0.0f); + } + + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID); + if (!entity) { + qCDebug(entities) << "EntityScriptingInterface::worldCoordsToVoxelCoords no entity with ID" << entityID; + return glm::vec3(0.0f); + } + + EntityTypes::EntityType entityType = entity->getType(); + if (entityType != EntityTypes::PolyVox) { + return glm::vec3(0.0f); + } + + auto polyVoxEntity = std::dynamic_pointer_cast(entity); + return polyVoxEntity->worldCoordsToVoxelCoords(worldCoords); +} diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 434134d2cd..e5bff8e80a 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -134,6 +134,9 @@ public slots: Q_INVOKABLE QVector getActionIDs(const QUuid& entityID); Q_INVOKABLE QVariantMap getActionArguments(const QUuid& entityID, const QUuid& actionID); + Q_INVOKABLE glm::vec3 voxelCoordsToWorldCoords(const QUuid& entityID, glm::vec3 voxelCoords); + Q_INVOKABLE glm::vec3 worldCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 worldCoords); + signals: void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); void collisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); @@ -162,7 +165,7 @@ signals: private: bool actionWorker(const QUuid& entityID, std::function actor); - bool setVoxels(QUuid entityID, std::function actor); + bool setVoxels(QUuid entityID, std::function actor); bool setPoints(QUuid entityID, std::function actor); void queueEntityMessage(PacketType::Value packetType, EntityItemID entityID, const EntityItemProperties& properties); diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 29d0b2e595..563624a1c7 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -74,17 +74,18 @@ class PolyVoxEntityItem : public EntityItem { static const PolyVoxSurfaceStyle DEFAULT_VOXEL_SURFACE_STYLE; // coords are in voxel-volume space - virtual void setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) {} + virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) { return false; } + virtual bool setVoxelInVolume(glm::vec3 position, uint8_t toValue) { return false; } + + virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3 voxelCoords) { return glm::vec3(0.0f); } + virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3 worldCoords) { return glm::vec3(0.0f); } // coords are in world-space - virtual void setSphere(glm::vec3 center, float radius, uint8_t toValue) {} - - virtual void setAll(uint8_t toValue) {} - - virtual void setVoxelInVolume(glm::vec3 position, uint8_t toValue) {} + virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue) { return false; } + virtual bool setAll(uint8_t toValue) { return false; } virtual uint8_t getVoxel(int x, int y, int z) { return 0; } - virtual void setVoxel(int x, int y, int z, uint8_t toValue) {} + virtual bool setVoxel(int x, int y, int z, uint8_t toValue) { return false; } static QByteArray makeEmptyVoxelData(quint16 voxelXSize = 16, quint16 voxelYSize = 16, quint16 voxelZSize = 16); From c6530c4cecbc5e9f552570869af6a942e3149396 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 15 Aug 2015 16:16:27 -0700 Subject: [PATCH 20/47] fix newly created polyvox collision-hull bug --- .../src/RenderablePolyVoxEntityItem.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 5b0c4ee691..9f97585fab 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -158,7 +158,10 @@ void RenderablePolyVoxEntityItem::setVoxelVolumeSize(glm::vec3 voxelVolumeSize) void RenderablePolyVoxEntityItem::updateVoxelSurfaceStyle(PolyVoxSurfaceStyle voxelSurfaceStyle) { // if we are switching to or from "edged" we need to force a resize of _volData. - if (voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) { + bool wasEdged = (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES); + bool willBeEdged = (voxelSurfaceStyle == SURFACE_EDGED_CUBIC || voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES); + + if (wasEdged != willBeEdged) { if (_volData) { delete _volData; } @@ -611,6 +614,7 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { } } else { unsigned int i = 0; + for (int z = 0; z < _voxelVolumeSize.z; z++) { for (int y = 0; y < _voxelVolumeSize.y; y++) { for (int x = 0; x < _voxelVolumeSize.x; x++) { @@ -619,6 +623,11 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { float offL = -0.5f; float offH = 0.5f; + if (_voxelSurfaceStyle == PolyVoxEntityItem::SURFACE_EDGED_CUBIC) { + offL += 1.0f; + offH += 1.0f; + } + glm::vec3 p000 = glm::vec3(vtoM * glm::vec4(x + offL, y + offL, z + offL, 1.0f)); glm::vec3 p001 = glm::vec3(vtoM * glm::vec4(x + offL, y + offL, z + offH, 1.0f)); From 558f68c150af1ba21ebad03937dbdb5d894d9b91 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sat, 15 Aug 2015 16:53:47 -0700 Subject: [PATCH 21/47] increase max polyvox dimension from 32 to 128. don't recompress compressed data unless something changed../../libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp --- libraries/entities/src/PolyVoxEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/PolyVoxEntityItem.cpp b/libraries/entities/src/PolyVoxEntityItem.cpp index c9f3705712..30dded3714 100644 --- a/libraries/entities/src/PolyVoxEntityItem.cpp +++ b/libraries/entities/src/PolyVoxEntityItem.cpp @@ -22,7 +22,7 @@ const glm::vec3 PolyVoxEntityItem::DEFAULT_VOXEL_VOLUME_SIZE = glm::vec3(32, 32, 32); -const float PolyVoxEntityItem::MAX_VOXEL_DIMENSION = 32.0f; +const float PolyVoxEntityItem::MAX_VOXEL_DIMENSION = 128.0f; const QByteArray PolyVoxEntityItem::DEFAULT_VOXEL_DATA(PolyVoxEntityItem::makeEmptyVoxelData()); const PolyVoxEntityItem::PolyVoxSurfaceStyle PolyVoxEntityItem::DEFAULT_VOXEL_SURFACE_STYLE = PolyVoxEntityItem::SURFACE_MARCHING_CUBES; From f6cbeb37f866d46a5cd44735b27e42c50fd5eabb Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 16 Aug 2015 09:35:50 -0700 Subject: [PATCH 22/47] put a green sphere at the point being pointed to --- examples/pointer.js | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/examples/pointer.js b/examples/pointer.js index 2791e06466..99c2bcb23b 100644 --- a/examples/pointer.js +++ b/examples/pointer.js @@ -12,6 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html var lineEntityID = null; +var sphereEntityID = null; var lineIsRezzed = false; var BUTTON_SIZE = 32; @@ -56,16 +57,24 @@ function nearLinePoint(targetPosition) { function removeLine() { - if (lineIsRezzed) { - Entities.deleteEntity(lineEntityID); - lineEntityID = null; - lineIsRezzed = false; - } + if (lineIsRezzed) { + Entities.deleteEntity(lineEntityID); + if (sphereEntityID) { + Entities.deleteEntity(sphereEntityID); + } + lineEntityID = null; + sphereEntityID = null; + lineIsRezzed = false; + } } function createOrUpdateLine(event) { var pickRay = Camera.computePickRay(event.x, event.y); + if (sphereEntityID) { + Entities.deleteEntity(sphereEntityID); + sphereEntityID = null; + } var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking var props = Entities.getEntityProperties(intersection.entityID); @@ -78,7 +87,6 @@ function createOrUpdateLine(event) { position: MyAvatar.position, lifetime: 15 + props.lifespan // renew lifetime }); - // Entities.setAllPoints(lineEntityID, points); } else { lineIsRezzed = true; lineEntityID = Entities.addEntity({ @@ -90,6 +98,15 @@ function createOrUpdateLine(event) { lifetime: 15 // if someone crashes while pointing, don't leave the line there forever. }); } + + sphereEntityID = Entities.addEntity({ + type: "Sphere", + position: intersection.intersection, + ignoreForCollisions: 1, + dimensions: { x: 0.6, y: 0.6, z: 0.6 }, + color: { red: 0, green: 255, blue: 0 }, + lifetime: 15 // if someone crashes while pointing, don't leave the line there forever. + }); } else { removeLine(); } From 6db115bed59f5b1f0577ec39ba09461bcc7bd887 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 16 Aug 2015 09:36:13 -0700 Subject: [PATCH 23/47] try to make adding and removing voxels work more like expected --- examples/voxels.js | 120 ++++++++++++++++++++++++++++++++------------- 1 file changed, 85 insertions(+), 35 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index c70111153b..0ef9fe9fab 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -1,38 +1,81 @@ var controlHeld = false; var shiftHeld = false; +function floorVector(v) { + return {x: Math.floor(v.x), y: Math.floor(v.y), z: Math.floor(v.z)}; +} -function attemptVoxelChange(intersection) { - var ids = Entities.findEntities(intersection.intersection, 10); - var success = false; - for (var i = 0; i < ids.length; i++) { - var id = ids[i]; - // var voxelCoords = Entities.worldCoordsToVoxelCoords(id, intersection.intersection); - - if (controlHeld) { - // hold control to erase a sphere - for (var r = 1.0; r < 17.0; r++) { - if (Entities.setVoxelSphere(id, intersection.intersection, r, 0)) { - success = true; - break; - } - } - } else if (shiftHeld) { - // hold shift to set all voxels to 255 - if (Entities.setAllVoxels(id, 255)) { - success = true; - } - } else { - // no modifier key means to add a sphere - for (var r = 1.0; r < 17.0; r++) { - if (Entities.setVoxelSphere(id, intersection.intersection, r, 255)) { - success = true; - break; - } - } - } +function backUpByOneVoxel(pickRayDirInVoxelSpace, originalVoxelPosition, low, high) { + // try to back up along pickRay an amount that changes only one coordinate. this does + // a binary search for a pickRay multiplier that only causes one of the 3 coordinates to change. + var originalVoxelCoords = floorVector(originalVoxelPosition) + if (high - low < 0.001) { + print("voxel backup-by-1 failed"); + // give up. + return oCoords; } - return success; + var middle = (low + high) / 2.0; + + var backupVector = Vec3.multiply(pickRayDirInVoxelSpace, -middle); + print("backupVector = " + "{" + backupVector.x + ", " + backupVector.y + ", " + backupVector.z + "}"); + var nPosition = Vec3.sum(originalVoxelPosition, backupVector); // possible neighbor coordinates + var nCoords = floorVector(nPosition); + + print("middle = " + middle + + " -- {" + originalVoxelCoords.x + ", " + originalVoxelCoords.y + ", " + originalVoxelCoords.z + "}" + + " -- {" + nCoords.x + ", " + nCoords.y + ", " + nCoords.z + "}"); + + + if (nCoords.x == originalVoxelCoords.x && + nCoords.y == originalVoxelCoords.y && + nCoords.z == originalVoxelCoords.z) { + // still in the original voxel. back up more... + return backUpByOneVoxel(pickRayDirInVoxelSpace, originalVoxelPosition, middle, high); + } + + if (nCoords.x != originalVoxelCoords.x && + nCoords.y == originalVoxelCoords.y && + nCoords.z == originalVoxelCoords.z) { + return nCoords; + } + if (nCoords.x == originalVoxelCoords.x && + nCoords.y != originalVoxelCoords.y && + nCoords.z == originalVoxelCoords.z) { + return nCoords; + } + if (nCoords.x == originalVoxelCoords.x && + nCoords.y == originalVoxelCoords.y && + nCoords.z != originalVoxelCoords.z) { + return nCoords; + } + + // more than one coordinate changed, but no less... + return backUpByOneVoxel(pickRayDirInVoxelSpace, originalVoxelPosition, low, middle); +} + + +function attemptVoxelChange(pickRayDir, intersection) { + var voxelPosition = Entities.worldCoordsToVoxelCoords(intersection.entityID, intersection.intersection); + var pickRayDirInVoxelSpace = Entities.localCoordsToVoxelCoords(intersection.entityID, pickRayDir); + + print("voxelPosition = " + voxelPosition.x + ", " + voxelPosition.y + ", " + voxelPosition.z); + print("pickRay = " + pickRayDir.x + ", " + pickRayDir.y + ", " + pickRayDir.z); + print("pickRayInVoxelSpace = " + + pickRayDirInVoxelSpace.x + ", " + pickRayDirInVoxelSpace.y + ", " + pickRayDirInVoxelSpace.z); + + if (controlHeld) { + // hold control to erase a voxel + return Entities.setVoxel(intersection.entityID, floorVector(voxelPosition), 0); + } else if (shiftHeld) { + // hold shift to set all voxels to 255 + return Entities.setAllVoxels(intersection.entityID, 255); + } else { + // no modifier key to add a voxel + var backOneVoxel = backUpByOneVoxel(pickRayDirInVoxelSpace, voxelPosition, 0.0, 1.0); + return Entities.setVoxel(intersection.entityID, backOneVoxel, 255); + } + + // Entities.setVoxelSphere(id, intersection.intersection, radius, 0) } @@ -43,20 +86,27 @@ function mousePressEvent(event) { var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking + var properties; - // we've used a picking ray to decide where to add the new sphere of voxels. If we pick nothing - // or if we pick a non-PolyVox entity, we fall through to the next picking attempt. if (intersection.intersects) { - if (attemptVoxelChange(intersection)) { - return; + properties = Entities.getEntityProperties(intersection.entityID); + print("got accurate pick"); + if (properties.type == "PolyVox") { + if (attemptVoxelChange(pickRay.direction, intersection)) { + return; + } + } else { + print("not a polyvox: " + properties.type); } } + print("trying bounding-box pick"); + // if the PolyVox entity is empty, we can't pick against its "on" voxels. try picking against its // bounding box, instead. intersection = Entities.findRayIntersection(pickRay, false); // bounding box picking if (intersection.intersects) { - attemptVoxelChange(intersection); + attemptVoxelChange(pickRay.direction, intersection); } } From b129c2a93342c0c86363ad1c6959406affe81c54 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 16 Aug 2015 09:36:54 -0700 Subject: [PATCH 24/47] in edged mode, make sure border voxels are zeroed out. expose some more voxel matrix math to javascript --- .../src/RenderablePolyVoxEntityItem.cpp | 84 +++++++++++++++---- .../src/RenderablePolyVoxEntityItem.h | 7 +- .../entities/src/EntityScriptingInterface.cpp | 40 +++++++++ .../entities/src/EntityScriptingInterface.h | 2 + libraries/entities/src/PolyVoxEntityItem.h | 2 + 5 files changed, 117 insertions(+), 18 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 9f97585fab..108660f386 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #if defined(__GNUC__) && !defined(__clang__) @@ -67,7 +68,7 @@ RenderablePolyVoxEntityItem::~RenderablePolyVoxEntityItem() { } bool inUserBounds(const PolyVox::SimpleVolume* vol, PolyVoxEntityItem::PolyVoxSurfaceStyle surfaceStyle, - int x, int y, int z) { + int x, int y, int z) { // x, y, z are in user voxel-coords, not adjusted-for-edge voxel-coords. switch (surfaceStyle) { case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: @@ -206,6 +207,11 @@ glm::mat4 RenderablePolyVoxEntityItem::voxelToLocalMatrix() const { return scaled; } +glm::mat4 RenderablePolyVoxEntityItem::localToVoxelMatrix() const { + glm::mat4 localToModelMatrix = glm::inverse(voxelToLocalMatrix()); + return localToModelMatrix; +} + glm::mat4 RenderablePolyVoxEntityItem::voxelToWorldMatrix() const { glm::mat4 rotation = glm::mat4_cast(getRotation()); glm::mat4 translation = glm::translate(getPosition()); @@ -252,13 +258,32 @@ bool RenderablePolyVoxEntityItem::setVoxelInternal(int x, int y, int z, uint8_t return result; } +void RenderablePolyVoxEntityItem::clearEdges() { + // if we are in an edged mode, make sure the outside surfaces are zeroed out. + if (_voxelSurfaceStyle == SURFACE_EDGED_CUBIC || _voxelSurfaceStyle == SURFACE_EDGED_MARCHING_CUBES) { + for (int z = 0; z < _volData->getDepth(); z++) { + for (int y = 0; y < _volData->getHeight(); y++) { + for (int x = 0; x < _volData->getWidth(); x++) { + if (x == 0 || y == 0 || z == 0 || + x == _volData->getWidth() - 1 || + y == _volData->getHeight() - 1 || + z == _volData->getDepth() - 1) { + _volData->setVoxelAt(x, y, z, 0); + } + } + } + } + } +} bool RenderablePolyVoxEntityItem::setVoxel(int x, int y, int z, uint8_t toValue) { if (_locked) { return false; } bool result = setVoxelInternal(x, y, z, toValue); - compressVolumeData(); + if (result) { + compressVolumeData(); + } return result; } @@ -298,7 +323,9 @@ bool RenderablePolyVoxEntityItem::setAll(uint8_t toValue) { } } } - compressVolumeData(); + if (result) { + compressVolumeData(); + } return result; } @@ -308,7 +335,7 @@ bool RenderablePolyVoxEntityItem::setVoxelInVolume(glm::vec3 position, uint8_t t } // same as setVoxel but takes a vector rather than 3 floats. - return setVoxel((int)position.x, (int)position.y, (int)position.z, toValue); + return setVoxel(roundf(position.x), roundf(position.y), roundf(position.z), toValue); } bool RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) { @@ -332,7 +359,9 @@ bool RenderablePolyVoxEntityItem::setSphereInVolume(glm::vec3 center, float radi } } } - compressVolumeData(); + if (result) { + compressVolumeData(); + } return result; } @@ -354,9 +383,10 @@ public: } bool operator()(PolyVox::SimpleVolume::Sampler& sampler) { - int x = sampler.getPosition().getX(); - int y = sampler.getPosition().getY(); - int z = sampler.getPosition().getZ(); + PolyVox::Vector3DInt32 positionIndex = sampler.getPosition(); + int x = positionIndex.getX(); + int y = positionIndex.getY(); + int z = positionIndex.getZ(); if (!inBounds(_vol, x, y, z)) { return true; @@ -365,8 +395,9 @@ public: if (sampler.getVoxel() == 0) { return true; // keep raycasting } - PolyVox::Vector3DInt32 positionIndex = sampler.getPosition(); - _result = glm::vec4(positionIndex.getX(), positionIndex.getY(), positionIndex.getZ(), 1.0f); + // qDebug() << "RaycastFunctor hit" << x << y << z; + // add {0.5, 0.5, 0.5} to result so it's centered on the voxel + _result = glm::vec4((float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f, 1.0f); return false; } glm::vec4 _result; @@ -386,7 +417,6 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o return true; } - // the PolyVox ray intersection code requires a near and far point. glm::mat4 wtvMatrix = worldToVoxelMatrix(); glm::vec3 normDirection = glm::normalize(direction); @@ -411,23 +441,29 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o } glm::vec4 result = callback._result; + switch (_voxelSurfaceStyle) { case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: - result -= glm::vec4(1, 1, 1, 0); // compensate for the extra voxel border + result -= glm::vec4(1.0f, 1.0f, 1.0f, 0.0f); // compensate for the extra voxel border break; case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: case PolyVoxEntityItem::SURFACE_CUBIC: break; } - result -= glm::vec4(0.5f, 0.5f, 0.5f, 0.0f); + // result -= glm::vec4(0.5f, 0.5f, 0.5f, 0.0f); glm::vec4 intersectedWorldPosition = voxelToWorldMatrix() * result; - distance = glm::distance(glm::vec3(intersectedWorldPosition), origin); + // TODO: use this to find the actual point of intersection rather than using the center of the voxel + // GeometryUtil.h + // bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::quat& rotation, + // const glm::vec3& position, const glm::vec2& dimensions, float& distance);; - face = BoxFace::MIN_X_FACE; // XXX + face = BoxFace::MIN_X_FACE; + + distance = glm::distance(glm::vec3(intersectedWorldPosition), origin); return true; } @@ -436,6 +472,8 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o // compress the data in _volData and save the results. The compressed form is used during // saves to disk and for transmission over the wire void RenderablePolyVoxEntityItem::compressVolumeData() { + auto startTime = usecTimestampNow(); + quint16 voxelXSize = _voxelVolumeSize.x; quint16 voxelYSize = _voxelVolumeSize.y; quint16 voxelZSize = _voxelVolumeSize.z; @@ -486,6 +524,8 @@ void RenderablePolyVoxEntityItem::compressVolumeData() { _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; _needsModelReload = true; + + qDebug() << "RenderablePolyVoxEntityItem::compressVolumeData" << (usecTimestampNow() - startTime) << getName(); } @@ -525,6 +565,7 @@ void RenderablePolyVoxEntityItem::decompressVolumeData() { } } } + clearEdges(); #ifdef WANT_DEBUG qDebug() << "--------------- voxel decompress ---------------"; @@ -628,7 +669,6 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { offH += 1.0f; } - glm::vec3 p000 = glm::vec3(vtoM * glm::vec4(x + offL, y + offL, z + offL, 1.0f)); glm::vec3 p001 = glm::vec3(vtoM * glm::vec4(x + offL, y + offL, z + offH, 1.0f)); glm::vec3 p010 = glm::vec3(vtoM * glm::vec4(x + offL, y + offH, z + offL, 1.0f)); @@ -691,6 +731,8 @@ void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) { } void RenderablePolyVoxEntityItem::getModel() { + auto startTime = usecTimestampNow(); + // A mesh object to hold the result of surface extraction PolyVox::SurfaceMesh polyVoxMesh; @@ -745,6 +787,8 @@ void RenderablePolyVoxEntityItem::getModel() { #endif _needsModelReload = false; + + qDebug() << "RenderablePolyVoxEntityItem::getModel" << (usecTimestampNow() - startTime) << getName(); } void RenderablePolyVoxEntityItem::render(RenderArgs* args) { @@ -871,3 +915,11 @@ glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToWorldCoords(glm::vec3 voxelC glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3 worldCoords) { return glm::vec3(worldToVoxelMatrix() * glm::vec4(worldCoords, 1.0f)); } + +glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToLocalCoords(glm::vec3 voxelCoords) { + return glm::vec3(voxelToLocalMatrix() * glm::vec4(voxelCoords, 1.0f)); +} + +glm::vec3 RenderablePolyVoxEntityItem::localCoordsToVoxelCoords(glm::vec3 localCoords) { + return glm::vec3(localToVoxelMatrix() * glm::vec4(localCoords, 1.0f)); +} diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index 17c8934577..ffc45beb22 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -71,8 +71,9 @@ public: virtual void setVoxelVolumeSize(glm::vec3 voxelVolumeSize); glm::vec3 getSurfacePositionAdjustment() const; glm::mat4 voxelToWorldMatrix() const; - glm::mat4 voxelToLocalMatrix() const; glm::mat4 worldToVoxelMatrix() const; + glm::mat4 voxelToLocalMatrix() const; + glm::mat4 localToVoxelMatrix() const; virtual ShapeType getShapeType() const; virtual bool isReadyToComputeShape(); @@ -80,6 +81,8 @@ public: virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3 voxelCoords); virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3 worldCoords); + virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3 voxelCoords); + virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3 localCoords); // coords are in voxel-volume space virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue); @@ -110,7 +113,7 @@ private: bool setVoxelInternal(int x, int y, int z, uint8_t toValue); void compressVolumeData(); void decompressVolumeData(); - + void clearEdges(); PolyVox::SimpleVolume* _volData = nullptr; model::Geometry _modelGeometry; diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index c3e71cef82..41ca6a91ac 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -697,3 +697,43 @@ glm::vec3 EntityScriptingInterface::worldCoordsToVoxelCoords(const QUuid& entity auto polyVoxEntity = std::dynamic_pointer_cast(entity); return polyVoxEntity->worldCoordsToVoxelCoords(worldCoords); } + +glm::vec3 EntityScriptingInterface::voxelCoordsToLocalCoords(const QUuid& entityID, glm::vec3 voxelCoords) { + if (!_entityTree) { + return glm::vec3(0.0f); + } + + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID); + if (!entity) { + qCDebug(entities) << "EntityScriptingInterface::voxelCoordsToLocalCoords no entity with ID" << entityID; + return glm::vec3(0.0f); + } + + EntityTypes::EntityType entityType = entity->getType(); + if (entityType != EntityTypes::PolyVox) { + return glm::vec3(0.0f); + } + + auto polyVoxEntity = std::dynamic_pointer_cast(entity); + return polyVoxEntity->voxelCoordsToLocalCoords(voxelCoords); +} + +glm::vec3 EntityScriptingInterface::localCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 localCoords) { + if (!_entityTree) { + return glm::vec3(0.0f); + } + + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID); + if (!entity) { + qCDebug(entities) << "EntityScriptingInterface::localCoordsToVoxelCoords no entity with ID" << entityID; + return glm::vec3(0.0f); + } + + EntityTypes::EntityType entityType = entity->getType(); + if (entityType != EntityTypes::PolyVox) { + return glm::vec3(0.0f); + } + + auto polyVoxEntity = std::dynamic_pointer_cast(entity); + return polyVoxEntity->localCoordsToVoxelCoords(localCoords); +} diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index e5bff8e80a..a51ebfb61c 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -136,6 +136,8 @@ public slots: Q_INVOKABLE glm::vec3 voxelCoordsToWorldCoords(const QUuid& entityID, glm::vec3 voxelCoords); Q_INVOKABLE glm::vec3 worldCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 worldCoords); + Q_INVOKABLE glm::vec3 voxelCoordsToLocalCoords(const QUuid& entityID, glm::vec3 voxelCoords); + Q_INVOKABLE glm::vec3 localCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 localCoords); signals: void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision); diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 563624a1c7..2ba57f85de 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -79,6 +79,8 @@ class PolyVoxEntityItem : public EntityItem { virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3 voxelCoords) { return glm::vec3(0.0f); } virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3 worldCoords) { return glm::vec3(0.0f); } + virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3 voxelCoords) { return glm::vec3(0.0f); } + virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3 localCoords) { return glm::vec3(0.0f); } // coords are in world-space virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue) { return false; } From 0230d9397cb04cf09803cc582cd94a0c9083aa09 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 16 Aug 2015 11:04:52 -0700 Subject: [PATCH 25/47] attempt to find exact ray intersection with cubic polyvox -- not working right, yet. --- .../src/RenderablePolyVoxEntityItem.cpp | 56 ++++++++++++++++--- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 108660f386..760fe5ad16 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -418,6 +418,8 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o } glm::mat4 wtvMatrix = worldToVoxelMatrix(); + glm::mat4 vtwMatrix = voxelToWorldMatrix(); + glm::mat4 vtlMatrix = voxelToLocalMatrix(); glm::vec3 normDirection = glm::normalize(direction); // the PolyVox ray intersection code requires a near and far point. @@ -440,6 +442,7 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o return false; } + // result is in voxel-space coordinates. glm::vec4 result = callback._result; switch (_voxelSurfaceStyle) { @@ -452,18 +455,55 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o break; } - // result -= glm::vec4(0.5f, 0.5f, 0.5f, 0.0f); - glm::vec4 intersectedWorldPosition = voxelToWorldMatrix() * result; + // close-ish, but not right + // glm::vec4 intersectedWorldPosition = vtwMatrix * result; + // distance = glm::distance(glm::vec3(intersectedWorldPosition), origin); - // TODO: use this to find the actual point of intersection rather than using the center of the voxel - // GeometryUtil.h - // bool findRayRectangleIntersection(const glm::vec3& origin, const glm::vec3& direction, const glm::quat& rotation, - // const glm::vec3& position, const glm::vec2& dimensions, float& distance);; + glm::vec3 minXPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.0f, 0.5f, 0.5f, 0.0f))); + glm::vec3 maxXPosition = glm::vec3(vtwMatrix * (result + glm::vec4(1.0f, 0.5f, 0.5f, 0.0f))); + glm::vec3 minYPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 0.0f, 0.5f, 0.0f))); + glm::vec3 maxYPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 1.0f, 0.5f, 0.0f))); + glm::vec3 minZPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 0.5f, 0.0f, 0.0f))); + glm::vec3 maxZPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 0.5f, 1.0f, 0.0f))); - face = BoxFace::MIN_X_FACE; + glm::vec4 baseDimensions = glm::vec4(1.0, 1.0, 1.0, 0.0); + glm::vec3 worldDimensions = glm::vec3(vtlMatrix * baseDimensions); + glm::vec2 xDimensions = glm::vec2(worldDimensions.y, worldDimensions.z); + glm::vec2 yDimensions = glm::vec2(worldDimensions.x, worldDimensions.z); + glm::vec2 zDimensions = glm::vec2(worldDimensions.x, worldDimensions.y); - distance = glm::distance(glm::vec3(intersectedWorldPosition), origin); + glm::quat minXRotation = extractRotation(vtwMatrix) * glm::quat(0.0f, 1.0f, 0.0f, PI_OVER_TWO); + glm::quat maxXRotation = extractRotation(vtwMatrix) * glm::quat(0.0f, 1.0f, 0.0f, PI_OVER_TWO); + glm::quat minYRotation = extractRotation(vtwMatrix) * glm::quat(1.0f, 0.0f, 0.0f, PI_OVER_TWO); + glm::quat maxYRotation = extractRotation(vtwMatrix) * glm::quat(1.0f, 0.0f, 0.0f, PI_OVER_TWO); + glm::quat minZRotation = extractRotation(vtwMatrix) * glm::quat(0.0f, 0.0f, 1.0f, 0.0f); + glm::quat maxZRotation = extractRotation(vtwMatrix) * glm::quat(0.0f, 0.0f, 1.0f, 0.0f); + + float bestDx = FLT_MAX; + bool hit[ 6 ]; + float dx[ 6 ] = {FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX}; + + hit[0] = findRayRectangleIntersection(origin, direction, minXRotation, minXPosition, xDimensions, dx[0]); + hit[1] = findRayRectangleIntersection(origin, direction, maxXRotation, maxXPosition, xDimensions, dx[1]); + hit[2] = findRayRectangleIntersection(origin, direction, minYRotation, minYPosition, yDimensions, dx[2]); + hit[3] = findRayRectangleIntersection(origin, direction, maxYRotation, maxYPosition, yDimensions, dx[3]); + hit[4] = findRayRectangleIntersection(origin, direction, minZRotation, minZPosition, zDimensions, dx[4]); + hit[5] = findRayRectangleIntersection(origin, direction, maxZRotation, maxZPosition, zDimensions, dx[5]); + + bool ok = false; + for (int i = 0; i < 6; i ++) { + if (hit[ i ] && dx[ i ] < bestDx) { + face = (BoxFace)i; + distance = dx[ i ]; + ok = true; + } + } + + if (!ok) { + qWarning() << "RenderablePolyVoxEntityItem::findDetailedRayIntersection -- failed to determine face"; + return false; + } return true; } From a57278ba3c063b6ee576714766d9f395517c4f0c Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 16 Aug 2015 11:51:04 -0700 Subject: [PATCH 26/47] ray-picks against cubic-voxels seem right, now --- examples/voxels.js | 2 +- .../src/RenderablePolyVoxEntityItem.cpp | 46 ++++++++----------- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index 0ef9fe9fab..b198ac3948 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -12,7 +12,7 @@ function backUpByOneVoxel(pickRayDirInVoxelSpace, originalVoxelPosition, low, hi if (high - low < 0.001) { print("voxel backup-by-1 failed"); // give up. - return oCoords; + return originalVoxelPosition; } var middle = (low + high) / 2.0; diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 760fe5ad16..4819d46e39 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -397,7 +397,9 @@ public: } // qDebug() << "RaycastFunctor hit" << x << y << z; // add {0.5, 0.5, 0.5} to result so it's centered on the voxel - _result = glm::vec4((float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f, 1.0f); + // _result = glm::vec4((float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f, 1.0f); + + _result = glm::vec4((float)x, (float)y, (float)z, 1.0f); return false; } glm::vec4 _result; @@ -412,6 +414,8 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o void** intersectedObject, bool precisionPicking) const { + // TODO -- correctly pick against marching-cube generated meshes + if (_needsModelReload || !precisionPicking) { // just intersect with bounding box return true; @@ -443,23 +447,9 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o } // result is in voxel-space coordinates. - glm::vec4 result = callback._result; - - switch (_voxelSurfaceStyle) { - case PolyVoxEntityItem::SURFACE_EDGED_CUBIC: - case PolyVoxEntityItem::SURFACE_EDGED_MARCHING_CUBES: - result -= glm::vec4(1.0f, 1.0f, 1.0f, 0.0f); // compensate for the extra voxel border - break; - case PolyVoxEntityItem::SURFACE_MARCHING_CUBES: - case PolyVoxEntityItem::SURFACE_CUBIC: - break; - } - - - // close-ish, but not right - // glm::vec4 intersectedWorldPosition = vtwMatrix * result; - // distance = glm::distance(glm::vec3(intersectedWorldPosition), origin); + glm::vec4 result = callback._result - glm::vec4(0.5f, 0.5f, 0.5f, 0.0f); + // set up ray tests against each face of the voxel. glm::vec3 minXPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.0f, 0.5f, 0.5f, 0.0f))); glm::vec3 maxXPosition = glm::vec3(vtwMatrix * (result + glm::vec4(1.0f, 0.5f, 0.5f, 0.0f))); glm::vec3 minYPosition = glm::vec3(vtwMatrix * (result + glm::vec4(0.5f, 0.0f, 0.5f, 0.0f))); @@ -469,16 +459,17 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o glm::vec4 baseDimensions = glm::vec4(1.0, 1.0, 1.0, 0.0); glm::vec3 worldDimensions = glm::vec3(vtlMatrix * baseDimensions); - glm::vec2 xDimensions = glm::vec2(worldDimensions.y, worldDimensions.z); + glm::vec2 xDimensions = glm::vec2(worldDimensions.z, worldDimensions.y); glm::vec2 yDimensions = glm::vec2(worldDimensions.x, worldDimensions.z); glm::vec2 zDimensions = glm::vec2(worldDimensions.x, worldDimensions.y); - glm::quat minXRotation = extractRotation(vtwMatrix) * glm::quat(0.0f, 1.0f, 0.0f, PI_OVER_TWO); - glm::quat maxXRotation = extractRotation(vtwMatrix) * glm::quat(0.0f, 1.0f, 0.0f, PI_OVER_TWO); - glm::quat minYRotation = extractRotation(vtwMatrix) * glm::quat(1.0f, 0.0f, 0.0f, PI_OVER_TWO); - glm::quat maxYRotation = extractRotation(vtwMatrix) * glm::quat(1.0f, 0.0f, 0.0f, PI_OVER_TWO); - glm::quat minZRotation = extractRotation(vtwMatrix) * glm::quat(0.0f, 0.0f, 1.0f, 0.0f); - glm::quat maxZRotation = extractRotation(vtwMatrix) * glm::quat(0.0f, 0.0f, 1.0f, 0.0f); + glm::quat vtwRotation = extractRotation(vtwMatrix); + glm::quat minXRotation = vtwRotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f)); + glm::quat maxXRotation = vtwRotation * glm::quat(glm::vec3(0.0f, PI_OVER_TWO, 0.0f)); + glm::quat minYRotation = vtwRotation * glm::quat(glm::vec3(PI_OVER_TWO, 0.0f, 0.0f)); + glm::quat maxYRotation = vtwRotation * glm::quat(glm::vec3(PI_OVER_TWO, 0.0f, 0.0f)); + glm::quat minZRotation = vtwRotation * glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); + glm::quat maxZRotation = vtwRotation * glm::quat(glm::vec3(0.0f, 0.0f, 0.0f)); float bestDx = FLT_MAX; bool hit[ 6 ]; @@ -497,12 +488,15 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o face = (BoxFace)i; distance = dx[ i ]; ok = true; + bestDx = dx[ i ]; } } if (!ok) { - qWarning() << "RenderablePolyVoxEntityItem::findDetailedRayIntersection -- failed to determine face"; - return false; + // if the attempt to put the ray against one of the voxel-faces fails, just return the center + glm::vec4 intersectedWorldPosition = vtwMatrix * (result + vec4(0.5f, 0.5f, 0.5f, 0.0f)); + distance = glm::distance(glm::vec3(intersectedWorldPosition), origin); + face = BoxFace::MIN_X_FACE; } return true; From c60a8e7dfcbe610d7d51790dd7d1642964c74885 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 16 Aug 2015 12:52:55 -0700 Subject: [PATCH 27/47] minecraft style voxel editing largely works --- examples/voxels.js | 85 ++++--------------- .../src/RenderablePolyVoxEntityItem.cpp | 15 ++-- 2 files changed, 25 insertions(+), 75 deletions(-) diff --git a/examples/voxels.js b/examples/voxels.js index b198ac3948..cc3453202a 100644 --- a/examples/voxels.js +++ b/examples/voxels.js @@ -5,80 +5,34 @@ function floorVector(v) { return {x: Math.floor(v.x), y: Math.floor(v.y), z: Math.floor(v.z)}; } -function backUpByOneVoxel(pickRayDirInVoxelSpace, originalVoxelPosition, low, high) { - // try to back up along pickRay an amount that changes only one coordinate. this does - // a binary search for a pickRay multiplier that only causes one of the 3 coordinates to change. - var originalVoxelCoords = floorVector(originalVoxelPosition) - if (high - low < 0.001) { - print("voxel backup-by-1 failed"); - // give up. - return originalVoxelPosition; - } - var middle = (low + high) / 2.0; - - var backupVector = Vec3.multiply(pickRayDirInVoxelSpace, -middle); - print("backupVector = " + "{" + backupVector.x + ", " + backupVector.y + ", " + backupVector.z + "}"); - var nPosition = Vec3.sum(originalVoxelPosition, backupVector); // possible neighbor coordinates - var nCoords = floorVector(nPosition); - - print("middle = " + middle + - " -- {" + originalVoxelCoords.x + ", " + originalVoxelCoords.y + ", " + originalVoxelCoords.z + "}" + - " -- {" + nCoords.x + ", " + nCoords.y + ", " + nCoords.z + "}"); - - - if (nCoords.x == originalVoxelCoords.x && - nCoords.y == originalVoxelCoords.y && - nCoords.z == originalVoxelCoords.z) { - // still in the original voxel. back up more... - return backUpByOneVoxel(pickRayDirInVoxelSpace, originalVoxelPosition, middle, high); - } - - if (nCoords.x != originalVoxelCoords.x && - nCoords.y == originalVoxelCoords.y && - nCoords.z == originalVoxelCoords.z) { - return nCoords; - } - if (nCoords.x == originalVoxelCoords.x && - nCoords.y != originalVoxelCoords.y && - nCoords.z == originalVoxelCoords.z) { - return nCoords; - } - if (nCoords.x == originalVoxelCoords.x && - nCoords.y == originalVoxelCoords.y && - nCoords.z != originalVoxelCoords.z) { - return nCoords; - } - - // more than one coordinate changed, but no less... - return backUpByOneVoxel(pickRayDirInVoxelSpace, originalVoxelPosition, low, middle); -} - - function attemptVoxelChange(pickRayDir, intersection) { - var voxelPosition = Entities.worldCoordsToVoxelCoords(intersection.entityID, intersection.intersection); - var pickRayDirInVoxelSpace = Entities.localCoordsToVoxelCoords(intersection.entityID, pickRayDir); - print("voxelPosition = " + voxelPosition.x + ", " + voxelPosition.y + ", " + voxelPosition.z); - print("pickRay = " + pickRayDir.x + ", " + pickRayDir.y + ", " + pickRayDir.z); - print("pickRayInVoxelSpace = " + - pickRayDirInVoxelSpace.x + ", " + pickRayDirInVoxelSpace.y + ", " + pickRayDirInVoxelSpace.z); + var properties = Entities.getEntityProperties(intersection.entityID); + if (properties.type != "PolyVox") { + return false; + } + + var voxelPosition = Entities.worldCoordsToVoxelCoords(intersection.entityID, intersection.intersection); + voxelPosition = Vec3.subtract(voxelPosition, {x: 0.5, y: 0.5, z: 0.5}); + var pickRayDirInVoxelSpace = Entities.localCoordsToVoxelCoords(intersection.entityID, pickRayDir); + pickRayDirInVoxelSpace = Vec3.normalize(pickRayDirInVoxelSpace); if (controlHeld) { // hold control to erase a voxel - return Entities.setVoxel(intersection.entityID, floorVector(voxelPosition), 0); + var toErasePosition = Vec3.sum(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1)); + return Entities.setVoxel(intersection.entityID, floorVector(toErasePosition), 0); } else if (shiftHeld) { // hold shift to set all voxels to 255 return Entities.setAllVoxels(intersection.entityID, 255); } else { // no modifier key to add a voxel - var backOneVoxel = backUpByOneVoxel(pickRayDirInVoxelSpace, voxelPosition, 0.0, 1.0); - return Entities.setVoxel(intersection.entityID, backOneVoxel, 255); + var toDrawPosition = Vec3.subtract(voxelPosition, Vec3.multiply(pickRayDirInVoxelSpace, 0.1)); + return Entities.setVoxel(intersection.entityID, floorVector(toDrawPosition), 255); } // Entities.setVoxelSphere(id, intersection.intersection, radius, 0) } - function mousePressEvent(event) { if (!event.isLeftButton) { return; @@ -86,22 +40,13 @@ function mousePressEvent(event) { var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking - var properties; if (intersection.intersects) { - properties = Entities.getEntityProperties(intersection.entityID); - print("got accurate pick"); - if (properties.type == "PolyVox") { - if (attemptVoxelChange(pickRay.direction, intersection)) { - return; - } - } else { - print("not a polyvox: " + properties.type); + if (attemptVoxelChange(pickRay.direction, intersection)) { + return; } } - print("trying bounding-box pick"); - // if the PolyVox entity is empty, we can't pick against its "on" voxels. try picking against its // bounding box, instead. intersection = Entities.findRayIntersection(pickRay, false); // bounding box picking diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 4819d46e39..7044eb0b3c 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -395,9 +395,6 @@ public: if (sampler.getVoxel() == 0) { return true; // keep raycasting } - // qDebug() << "RaycastFunctor hit" << x << y << z; - // add {0.5, 0.5, 0.5} to result so it's centered on the voxel - // _result = glm::vec4((float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f, 1.0f); _result = glm::vec4((float)x, (float)y, (float)z, 1.0f); return false; @@ -506,7 +503,9 @@ bool RenderablePolyVoxEntityItem::findDetailedRayIntersection(const glm::vec3& o // compress the data in _volData and save the results. The compressed form is used during // saves to disk and for transmission over the wire void RenderablePolyVoxEntityItem::compressVolumeData() { + #ifdef WANT_DEBUG auto startTime = usecTimestampNow(); + #endif quint16 voxelXSize = _voxelVolumeSize.x; quint16 voxelYSize = _voxelVolumeSize.y; @@ -559,7 +558,9 @@ void RenderablePolyVoxEntityItem::compressVolumeData() { _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; _needsModelReload = true; + #ifdef WANT_DEBUG qDebug() << "RenderablePolyVoxEntityItem::compressVolumeData" << (usecTimestampNow() - startTime) << getName(); + #endif } @@ -765,7 +766,9 @@ void RenderablePolyVoxEntityItem::setZTextureURL(QString zTextureURL) { } void RenderablePolyVoxEntityItem::getModel() { + #ifdef WANT_DEBUG auto startTime = usecTimestampNow(); + #endif // A mesh object to hold the result of surface extraction PolyVox::SurfaceMesh polyVoxMesh; @@ -822,7 +825,9 @@ void RenderablePolyVoxEntityItem::getModel() { _needsModelReload = false; + #ifdef WANT_DEBUG qDebug() << "RenderablePolyVoxEntityItem::getModel" << (usecTimestampNow() - startTime) << getName(); + #endif } void RenderablePolyVoxEntityItem::render(RenderArgs* args) { @@ -951,9 +956,9 @@ glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3 worldC } glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToLocalCoords(glm::vec3 voxelCoords) { - return glm::vec3(voxelToLocalMatrix() * glm::vec4(voxelCoords, 1.0f)); + return glm::vec3(voxelToLocalMatrix() * glm::vec4(voxelCoords, 0.0f)); } glm::vec3 RenderablePolyVoxEntityItem::localCoordsToVoxelCoords(glm::vec3 localCoords) { - return glm::vec3(localToVoxelMatrix() * glm::vec4(localCoords, 1.0f)); + return glm::vec3(localToVoxelMatrix() * glm::vec4(localCoords, 0.0f)); } From 1ee773a5322ff08fbf0204b995e6be06fad25066 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Sun, 16 Aug 2015 14:11:37 -0700 Subject: [PATCH 28/47] don't include interrior voxels in cubic collision hull --- .../src/RenderablePolyVoxEntityItem.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 7044eb0b3c..edccffd397 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -695,6 +695,18 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { for (int y = 0; y < _voxelVolumeSize.y; y++) { for (int x = 0; x < _voxelVolumeSize.x; x++) { if (getVoxel(x, y, z) > 0) { + + if ((x > 0 && getVoxel(x - 1, y, z) == 0) && + (y > 0 && getVoxel(x, y - 1, z) == 0) && + (z > 0 && getVoxel(x, y, z - 1) == 0) && + (x < _voxelVolumeSize.x - 1 && getVoxel(x + 1, y, z) == 0) && + (y < _voxelVolumeSize.y - 1 && getVoxel(x, y + 1, z) == 0) && + (z < _voxelVolumeSize.z - 1 && getVoxel(x, y, z + 1) == 0)) { + // this voxel has neighbors in every cardinal direction, so there's no need + // to include it in the collision hull. + continue; + } + QVector pointsInPart; float offL = -0.5f; From af11e97daad8d8aa4a5c06e8d8cf7f59c683debb Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 17 Aug 2015 08:49:00 -0700 Subject: [PATCH 29/47] fix broken optimisation for skipping internal voxels when making collision hull --- .../src/RenderablePolyVoxEntityItem.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index edccffd397..5c0a7888e5 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -696,12 +696,12 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { for (int x = 0; x < _voxelVolumeSize.x; x++) { if (getVoxel(x, y, z) > 0) { - if ((x > 0 && getVoxel(x - 1, y, z) == 0) && - (y > 0 && getVoxel(x, y - 1, z) == 0) && - (z > 0 && getVoxel(x, y, z - 1) == 0) && - (x < _voxelVolumeSize.x - 1 && getVoxel(x + 1, y, z) == 0) && - (y < _voxelVolumeSize.y - 1 && getVoxel(x, y + 1, z) == 0) && - (z < _voxelVolumeSize.z - 1 && getVoxel(x, y, z + 1) == 0)) { + if ((x > 0 && getVoxel(x - 1, y, z) > 0) && + (y > 0 && getVoxel(x, y - 1, z) > 0) && + (z > 0 && getVoxel(x, y, z - 1) > 0) && + (x < _voxelVolumeSize.x - 1 && getVoxel(x + 1, y, z) > 0) && + (y < _voxelVolumeSize.y - 1 && getVoxel(x, y + 1, z) > 0) && + (z < _voxelVolumeSize.z - 1 && getVoxel(x, y, z + 1) > 0)) { // this voxel has neighbors in every cardinal direction, so there's no need // to include it in the collision hull. continue; From 1c8030472ae6a06f85ec0d9f71aa61278fd78d1b Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 17 Aug 2015 12:40:56 -0700 Subject: [PATCH 30/47] back out the more controversial changes --- libraries/fbx/src/FBXReader.cpp | 20 ++++++++++++-------- libraries/render-utils/src/Model.cpp | 11 +++++++++++ 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index ebffa4410a..2db5f5fa51 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -976,7 +976,7 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) { data.extracted.mesh.meshIndex = meshIndex++; QVector materials; QVector textures; - // bool isMaterialPerPolygon = false; + bool isMaterialPerPolygon = false; foreach (const FBXNode& child, object.children) { if (child.name == "Vertices") { @@ -1107,13 +1107,12 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) { foreach (const FBXNode& subdata, child.children) { if (subdata.name == "Materials") { materials = getIntVector(subdata); - } // else if (subdata.name == "MappingInformationType") { - // if (subdata.properties.at(0) == "ByPolygon") - // isMaterialPerPolygon = true; - // } else { - // isMaterialPerPolygon = false; - // } - // } + } else if (subdata.name == "MappingInformationType") { + if (subdata.properties.at(0) == "ByPolygon") + isMaterialPerPolygon = true; + } else { + isMaterialPerPolygon = false; + } } @@ -1126,6 +1125,11 @@ ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex) { } } + bool isMultiMaterial = false; + if (isMaterialPerPolygon) { + isMultiMaterial = true; + } + // convert the polygons to quads and triangles int polygonIndex = 0; QHash, int> materialTextureParts; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 8a9a3f68dc..7452c32ed2 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1808,6 +1808,17 @@ void Model::segregateMeshGroups() { const FBXMesh& mesh = geometry.meshes.at(i); const MeshState& state = _meshStates.at(i); + bool translucentMesh = networkMesh.getTranslucentPartCount(mesh) == networkMesh.parts.size(); + bool hasTangents = !mesh.tangents.isEmpty(); + bool hasSpecular = mesh.hasSpecularTexture(); + bool hasLightmap = mesh.hasEmissiveTexture(); + bool isSkinned = state.clusterMatrices.size() > 1; + bool wireframe = isWireframe(); + + if (wireframe) { + translucentMesh = hasTangents = hasSpecular = hasLightmap = isSkinned = false; + } + // Create the render payloads int totalParts = mesh.parts.size(); for (int partIndex = 0; partIndex < totalParts; partIndex++) { From 4a456488a1dede351aaf1c43312f025134ad076a Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Mon, 17 Aug 2015 14:01:25 -0700 Subject: [PATCH 31/47] remove the option to persist entities as anything other than json.gz files --- assignment-client/src/octree/OctreeServer.cpp | 7 +---- .../resources/describe-settings.json | 26 ++----------------- 2 files changed, 3 insertions(+), 30 deletions(-) diff --git a/assignment-client/src/octree/OctreeServer.cpp b/assignment-client/src/octree/OctreeServer.cpp index 76d701f0e3..062fe39dbd 100644 --- a/assignment-client/src/octree/OctreeServer.cpp +++ b/assignment-client/src/octree/OctreeServer.cpp @@ -971,12 +971,7 @@ void OctreeServer::readConfiguration() { strcpy(_persistFilename, qPrintable(persistFilename)); qDebug("persistFilename=%s", _persistFilename); - QString persistAsFileType; - if (!readOptionString(QString("persistAsFileType"), settingsSectionObject, persistAsFileType)) { - persistAsFileType = "svo"; - } - _persistAsFileType = persistAsFileType; - qDebug() << "persistAsFileType=" << _persistAsFileType; + _persistAsFileType = "json.gz"; _persistInterval = OctreePersistThread::DEFAULT_PERSIST_INTERVAL; readOptionInt(QString("persistInterval"), settingsSectionObject, _persistInterval); diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 696a87d2b8..b04ea95a23 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -371,30 +371,8 @@ "name": "persistFilename", "label": "Entities Filename", "help": "the path to the file entities are stored in. Make sure the path exists.", - "placeholder": "resources/models.svo", - "default": "resources/models.svo", - "advanced": true - }, - { - "name": "persistAsFileType", - "label": "File format for entity server's persistent data", - "help": "This defines how the entity server will save entities to disk.", - "default": "svo", - "type": "select", - "options": [ - { - "value": "svo", - "label": "Entity server persists data as SVO" - }, - { - "value": "json", - "label": "Entity server persists data as JSON" - }, - { - "value": "json.gz", - "label": "Entity server persists data as gzipped JSON" - } - ], + "placeholder": "resources/models.json.gz", + "default": "resources/models.json.gz", "advanced": true }, { From 3cbbb5fb7975f369d0e2d4d90bbbad34721c965b Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 18 Aug 2015 00:05:02 -0700 Subject: [PATCH 32/47] Fix crash on mouse click --- interface/src/Application.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 449afae5d1..4e790bfa88 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -712,6 +712,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _keyboardFocusHighlightID = getOverlays().addOverlay(_keyboardFocusHighlight); } } + if (_keyboardFocusedItem == UNKNOWN_ENTITY_ID && _keyboardFocusHighlight) { + _keyboardFocusHighlight->setVisible(false); + } + } }); @@ -719,7 +723,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : connect(getEntities(), &EntityTreeRenderer::mousePressOffEntity, [=](const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId) { _keyboardFocusedItem = UNKNOWN_ENTITY_ID; - _keyboardFocusHighlight->setVisible(false); + if (_keyboardFocusHighlight) { + _keyboardFocusHighlight->setVisible(false); + } }); } From 551f0aaba3b0514eea1c616f55210f6e867a96e5 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 18 Aug 2015 01:37:11 -0700 Subject: [PATCH 33/47] show how many times per second Application::idle is called --- interface/resources/qml/Stats.qml | 5 +++++ interface/src/Application.cpp | 19 +++++++++++++------ interface/src/Application.h | 8 ++++++++ interface/src/ui/Stats.cpp | 1 + interface/src/ui/Stats.h | 2 ++ 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 996f9f02ef..b7081afadf 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -47,6 +47,11 @@ Item { font.pixelSize: root.fontSize text: "Framerate: " + root.framerate } + Text { + color: root.fontColor; + font.pixelSize: root.fontSize + text: "Simrate: " + root.simrate + } Text { color: root.fontColor; font.pixelSize: root.fontSize diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4e790bfa88..58ef83efff 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -89,7 +89,6 @@ #include #include #include -#include #include #include #include @@ -2003,19 +2002,27 @@ void Application::checkFPS() { void Application::idle() { PROFILE_RANGE(__FUNCTION__); - static SimpleAverage interIdleDurations; + + static uint64_t lastIdleStart{ 0 }; static uint64_t lastIdleEnd{ 0 }; + uint64_t now = usecTimestampNow(); + uint64_t idleStartToStartDuration = now - lastIdleStart; + + if (lastIdleStart > 0 && idleStartToStartDuration > 0) { + _simsPerSecond.updateAverage((float)USECS_PER_SECOND / (float)idleStartToStartDuration); + } + + lastIdleStart = now; if (lastIdleEnd != 0) { - uint64_t now = usecTimestampNow(); - interIdleDurations.update(now - lastIdleEnd); + _interIdleDurations.update(now - lastIdleEnd); static uint64_t lastReportTime = now; if ((now - lastReportTime) >= (USECS_PER_SECOND)) { static QString LOGLINE("Average inter-idle time: %1 us for %2 samples"); if (Menu::getInstance()->isOptionChecked(MenuOption::LogExtraTimings)) { - qCDebug(interfaceapp_timing) << LOGLINE.arg((int)interIdleDurations.getAverage()).arg(interIdleDurations.getCount()); + qCDebug(interfaceapp_timing) << LOGLINE.arg((int)_interIdleDurations.getAverage()).arg(_interIdleDurations.getCount()); } - interIdleDurations.reset(); + _interIdleDurations.reset(); lastReportTime = now; } } diff --git a/interface/src/Application.h b/interface/src/Application.h index e0d4fa559d..fd57406249 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -38,6 +38,8 @@ #include #include #include +#include +#include #include "AudioClient.h" #include "Bookmarks.h" @@ -350,6 +352,9 @@ public: const QRect& getMirrorViewRect() const { return _mirrorViewRect; } + float getAverageInterIdleDuration() { return _interIdleDurations.getAverage(); } + float getAverageSimsPerSecond() { return _simsPerSecond.getAverage(); } + signals: /// Fired when we're simulating; allows external parties to hook in. @@ -681,6 +686,9 @@ private: EntityItemID _keyboardFocusedItem; quint64 _lastAcceptedKeyPress = 0; + + SimpleAverage _interIdleDurations; + SimpleMovingAverage _simsPerSecond; }; #endif // hifi_Application_h diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index d7c4bb5ed7..74e3a8f44f 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -114,6 +114,7 @@ void Stats::updateStats() { STAT_UPDATE(avatarCount, avatarManager->size() - 1); STAT_UPDATE(serverCount, nodeList->size()); STAT_UPDATE(framerate, (int)qApp->getFps()); + STAT_UPDATE(simrate, (int)Application::getInstance()->getAverageSimsPerSecond()); auto bandwidthRecorder = DependencyManager::get(); STAT_UPDATE(packetInCount, bandwidthRecorder->getCachedTotalAverageInputPacketsPerSecond()); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index af6824d1a3..4f0619d9c8 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -30,6 +30,7 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, serverCount, 0) STATS_PROPERTY(int, framerate, 0) + STATS_PROPERTY(int, simrate, 0) STATS_PROPERTY(int, avatarCount, 0) STATS_PROPERTY(int, packetInCount, 0) STATS_PROPERTY(int, packetOutCount, 0) @@ -95,6 +96,7 @@ signals: void timingExpandedChanged(); void serverCountChanged(); void framerateChanged(); + void simrateChanged(); void avatarCountChanged(); void packetInCountChanged(); void packetOutCountChanged(); From 8435550fe9a20fd9f15926bd217733d4ff7fc021 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 18 Aug 2015 02:05:50 -0700 Subject: [PATCH 34/47] only update simRate once per second --- interface/src/Application.cpp | 17 ++++++++++++++--- interface/src/Application.h | 8 ++++---- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 58ef83efff..de77b95e23 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2014,15 +2014,16 @@ void Application::idle() { lastIdleStart = now; + static SimpleAverage interIdleDurations; if (lastIdleEnd != 0) { - _interIdleDurations.update(now - lastIdleEnd); + interIdleDurations.update(now - lastIdleEnd); static uint64_t lastReportTime = now; if ((now - lastReportTime) >= (USECS_PER_SECOND)) { static QString LOGLINE("Average inter-idle time: %1 us for %2 samples"); if (Menu::getInstance()->isOptionChecked(MenuOption::LogExtraTimings)) { - qCDebug(interfaceapp_timing) << LOGLINE.arg((int)_interIdleDurations.getAverage()).arg(_interIdleDurations.getCount()); + qCDebug(interfaceapp_timing) << LOGLINE.arg((int)interIdleDurations.getAverage()).arg(interIdleDurations.getCount()); } - _interIdleDurations.reset(); + interIdleDurations.reset(); lastReportTime = now; } } @@ -2109,6 +2110,16 @@ void Application::idle() { lastIdleEnd = usecTimestampNow(); } +float Application::getAverageSimsPerSecond() { + uint64_t now = usecTimestampNow(); + + if (now - _lastSimsPerSecondUpdate > USECS_PER_SECOND) { + _simsPerSecondReport = _simsPerSecond.getAverage(); + _lastSimsPerSecondUpdate = now; + } + return _simsPerSecondReport; +} + void Application::setLowVelocityFilter(bool lowVelocityFilter) { InputDevice::setLowVelocityFilter(lowVelocityFilter); } diff --git a/interface/src/Application.h b/interface/src/Application.h index fd57406249..f49fb38e57 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -352,8 +352,7 @@ public: const QRect& getMirrorViewRect() const { return _mirrorViewRect; } - float getAverageInterIdleDuration() { return _interIdleDurations.getAverage(); } - float getAverageSimsPerSecond() { return _simsPerSecond.getAverage(); } + float getAverageSimsPerSecond(); signals: @@ -687,8 +686,9 @@ private: EntityItemID _keyboardFocusedItem; quint64 _lastAcceptedKeyPress = 0; - SimpleAverage _interIdleDurations; - SimpleMovingAverage _simsPerSecond; + SimpleMovingAverage _simsPerSecond{10}; + int _simsPerSecondReport = 0; + quint64 _lastSimsPerSecondUpdate = 0; }; #endif // hifi_Application_h From e29bb9183b230bce810617c2f75a1aa911072ba1 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 18 Aug 2015 02:08:21 -0700 Subject: [PATCH 35/47] minimize diff --- interface/src/Application.cpp | 3 ++- interface/src/Application.h | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index de77b95e23..c9c3b94e03 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -89,6 +89,7 @@ #include #include #include +#include #include #include #include @@ -2002,6 +2003,7 @@ void Application::checkFPS() { void Application::idle() { PROFILE_RANGE(__FUNCTION__); + static SimpleAverage interIdleDurations; static uint64_t lastIdleStart{ 0 }; static uint64_t lastIdleEnd{ 0 }; @@ -2014,7 +2016,6 @@ void Application::idle() { lastIdleStart = now; - static SimpleAverage interIdleDurations; if (lastIdleEnd != 0) { interIdleDurations.update(now - lastIdleEnd); static uint64_t lastReportTime = now; diff --git a/interface/src/Application.h b/interface/src/Application.h index f49fb38e57..4819bd08a4 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -38,7 +38,6 @@ #include #include #include -#include #include #include "AudioClient.h" From 44399da41cc6e315341916f3ee74b4f59a671730 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 18 Aug 2015 14:54:21 +0200 Subject: [PATCH 36/47] Removed the minimize button from the tool window. Close it to hide it. Fixes bug where ToolWindow hides forever. --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4e790bfa88..35206c64de 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -560,7 +560,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _toolWindow = new ToolWindow(); - _toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint); + _toolWindow->setWindowFlags((_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint) & ~Qt::WindowMinimizeButtonHint); _toolWindow->setWindowTitle("Tools"); _offscreenContext->makeCurrent(); From 00aa336a2bda14ee9eb8279640f13c6ba53331f2 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 18 Aug 2015 10:01:00 -0700 Subject: [PATCH 37/47] Add further temporary debug for tracking down invalid scale value assert --- interface/src/avatar/Avatar.cpp | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 55809646c0..0adf2589cd 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -688,6 +688,23 @@ glm::vec3 Avatar::getDisplayNamePosition() const { const float HEAD_PROPORTION = 0.75f; namePosition = _position + getBodyUpDirection() * (getBillboardSize() * HEAD_PROPORTION); } +#ifdef DEBUG + // TODO: Temporary logging to track cause of invalid scale value; remove once cause has been fixed. + // See other TODO below. + if (glm::isnan(namePosition.x) || glm::isnan(namePosition.y) || glm::isnan(namePosition.z) + || glm::isinf(namePosition.x) || glm::isinf(namePosition.y) || glm::isinf(namePosition.z)) { + qDebug() << "namePosition =" << namePosition; + glm::vec3 tempPosition(0.0f); + if (getSkeletonModel().getNeckPosition(tempPosition)) { + qDebug() << "getBodyUpDirection() =" << getBodyUpDirection(); + qDebug() << "getHeadHeight() =" << getHeadHeight(); + } else { + qDebug() << "_position =" << _position; + qDebug() << "getBodyUpDirection() =" << getBodyUpDirection(); + qDebug() << "getBillboardSize() =" << getBillboardSize(); + } + } +#endif return namePosition; } @@ -722,7 +739,8 @@ Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, floa // Compute correct scale to apply float scale = DESIRED_HIGHT_ON_SCREEN / (fontSize * pixelHeight) * devicePixelRatio; #ifdef DEBUG - // TODO: Temporary logging to track cause of invalid scale vale; remove once cause has been fixed. + // TODO: Temporary logging to track cause of invalid scale value; remove once cause has been fixed. + // Problem is probably due to an invalid getDisplayNamePosition(). See extra logging above. if (scale == 0.0f || glm::isnan(scale) || glm::isinf(scale)) { if (scale == 0.0f) { qDebug() << "ASSERT because scale == 0.0f"; @@ -733,6 +751,7 @@ Transform Avatar::calculateDisplayNameTransform(const ViewFrustum& frustum, floa if (glm::isinf(scale)) { qDebug() << "ASSERT because isinf(scale)"; } + qDebug() << "textPosition =" << textPosition; qDebug() << "windowSizeY =" << windowSizeY; qDebug() << "p1.y =" << p1.y; qDebug() << "p1.w =" << p1.w; From f6815c215a5b4afa79747b87e3b942177d1eb665 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Tue, 18 Aug 2015 10:59:49 -0700 Subject: [PATCH 38/47] Fix edit toolbar moving to top left of screen --- examples/libraries/toolBars.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/libraries/toolBars.js b/examples/libraries/toolBars.js index 16c68a73fb..abe8de8cc3 100644 --- a/examples/libraries/toolBars.js +++ b/examples/libraries/toolBars.js @@ -362,8 +362,11 @@ ToolBar = function(x, y, direction, optionalPersistenceKey, optionalInitialPosit this.fractionKey = optionalPersistenceKey + '.fraction'; this.save = function () { var screenSize = Controller.getViewportDimensions(); - var fraction = {x: that.x / screenSize.x, y: that.y / screenSize.y}; - Settings.setValue(this.fractionKey, JSON.stringify(fraction)); + if (screenSize.x > 0 && screenSize.y > 0) { + // Guard against invalid screen size that can occur at shut-down. + var fraction = {x: that.x / screenSize.x, y: that.y / screenSize.y}; + Settings.setValue(this.fractionKey, JSON.stringify(fraction)); + } } } else { this.save = function () { }; // Called on move. Can be overriden or extended by clients. From 2dc2757ecabf501ed5c92f4c1d069b028d172b50 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 18 Aug 2015 13:03:54 -0700 Subject: [PATCH 39/47] code review --- .../src/RenderablePolyVoxEntityItem.cpp | 14 +++++++------- .../src/RenderablePolyVoxEntityItem.h | 8 ++++---- libraries/entities/src/PolyVoxEntityItem.h | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 5c0a7888e5..5d139a719a 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -659,9 +659,9 @@ void RenderablePolyVoxEntityItem::computeShapeInfo(ShapeInfo& info) { uint32_t p1Index = *(it++); uint32_t p2Index = *(it++); - const glm::vec3 p0 = vertexBufferView.get(p0Index); - const glm::vec3 p1 = vertexBufferView.get(p1Index); - const glm::vec3 p2 = vertexBufferView.get(p2Index); + const glm::vec3& p0 = vertexBufferView.get(p0Index); + const glm::vec3& p1 = vertexBufferView.get(p1Index); + const glm::vec3& p2 = vertexBufferView.get(p2Index); glm::vec3 av = (p0 + p1 + p2) / 3.0f; // center of the triangular face glm::vec3 normal = glm::normalize(glm::cross(p1 - p0, p2 - p0)); @@ -959,18 +959,18 @@ namespace render { } } -glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToWorldCoords(glm::vec3 voxelCoords) { +glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const { return glm::vec3(voxelToWorldMatrix() * glm::vec4(voxelCoords, 1.0f)); } -glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3 worldCoords) { +glm::vec3 RenderablePolyVoxEntityItem::worldCoordsToVoxelCoords(glm::vec3& worldCoords) const { return glm::vec3(worldToVoxelMatrix() * glm::vec4(worldCoords, 1.0f)); } -glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToLocalCoords(glm::vec3 voxelCoords) { +glm::vec3 RenderablePolyVoxEntityItem::voxelCoordsToLocalCoords(glm::vec3& voxelCoords) const { return glm::vec3(voxelToLocalMatrix() * glm::vec4(voxelCoords, 0.0f)); } -glm::vec3 RenderablePolyVoxEntityItem::localCoordsToVoxelCoords(glm::vec3 localCoords) { +glm::vec3 RenderablePolyVoxEntityItem::localCoordsToVoxelCoords(glm::vec3& localCoords) const { return glm::vec3(localToVoxelMatrix() * glm::vec4(localCoords, 0.0f)); } diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h index ffc45beb22..e2fcdedc31 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.h @@ -79,10 +79,10 @@ public: virtual bool isReadyToComputeShape(); virtual void computeShapeInfo(ShapeInfo& info); - virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3 voxelCoords); - virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3 worldCoords); - virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3 voxelCoords); - virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3 localCoords); + virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const; + virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3& worldCoords) const; + virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3& voxelCoords) const; + virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3& localCoords) const; // coords are in voxel-volume space virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue); diff --git a/libraries/entities/src/PolyVoxEntityItem.h b/libraries/entities/src/PolyVoxEntityItem.h index 2ba57f85de..9fbaade407 100644 --- a/libraries/entities/src/PolyVoxEntityItem.h +++ b/libraries/entities/src/PolyVoxEntityItem.h @@ -77,10 +77,10 @@ class PolyVoxEntityItem : public EntityItem { virtual bool setSphereInVolume(glm::vec3 center, float radius, uint8_t toValue) { return false; } virtual bool setVoxelInVolume(glm::vec3 position, uint8_t toValue) { return false; } - virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3 voxelCoords) { return glm::vec3(0.0f); } - virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3 worldCoords) { return glm::vec3(0.0f); } - virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3 voxelCoords) { return glm::vec3(0.0f); } - virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3 localCoords) { return glm::vec3(0.0f); } + virtual glm::vec3 voxelCoordsToWorldCoords(glm::vec3& voxelCoords) const { return glm::vec3(0.0f); } + virtual glm::vec3 worldCoordsToVoxelCoords(glm::vec3& worldCoords) const { return glm::vec3(0.0f); } + virtual glm::vec3 voxelCoordsToLocalCoords(glm::vec3& voxelCoords) const { return glm::vec3(0.0f); } + virtual glm::vec3 localCoordsToVoxelCoords(glm::vec3& localCoords) const { return glm::vec3(0.0f); } // coords are in world-space virtual bool setSphere(glm::vec3 center, float radius, uint8_t toValue) { return false; } From 944734fed2d38ad47ed25a9d0f33d90b21b0eddb Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 18 Aug 2015 13:59:39 -0700 Subject: [PATCH 40/47] Remove focus highlight on delete entity --- interface/src/Application.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c9c3b94e03..a9997c7426 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -719,6 +719,16 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : } }); + connect(entityScriptingInterface.data(), &EntityScriptingInterface::deletingEntity, + [=](const EntityItemID& entityItemID) { + if (entityItemID == _keyboardFocusedItem) { + _keyboardFocusedItem = UNKNOWN_ENTITY_ID; + if (_keyboardFocusHighlight) { + _keyboardFocusHighlight->setVisible(false); + } + } + }); + // If the user clicks somewhere where there is NO entity at all, we will release focus connect(getEntities(), &EntityTreeRenderer::mousePressOffEntity, [=](const RayToEntityIntersectionResult& entityItemID, const QMouseEvent* event, unsigned int deviceId) { From 5fcbd37e439c95c8c0d983430a27cc165b3457aa Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 18 Aug 2015 15:45:17 -0700 Subject: [PATCH 41/47] possible fix for invisible other's-avatar bug --- interface/src/avatar/Avatar.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 0adf2589cd..4d8e3d99dd 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -563,6 +563,9 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { } void Avatar::fixupModelsInScene() { + if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { + return; + } // check to see if when we added our models to the scene they were ready, if they were not ready, then // fix them up in the scene From eba446e7f66010436b70a331394f5a507f0b8103 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 17 Aug 2015 10:52:05 -0700 Subject: [PATCH 42/47] Updating to the new version of the sixense library --- CMakeLists.txt | 1 + cmake/externals/sixense/CMakeLists.txt | 61 +++++++++++++------------- cmake/modules/FindSixense.cmake | 2 +- libraries/input-plugins/CMakeLists.txt | 8 ++-- 4 files changed, 37 insertions(+), 35 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 38bcb42e26..41b88e4cea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,6 +187,7 @@ option(GET_OPENVR "Get OpenVR library automatically as external project" 1) option(GET_BOOSTCONFIG "Get Boost-config library automatically as external project" 1) option(GET_OGLPLUS "Get OGLplus library automatically as external project" 1) option(GET_GLEW "Get GLEW library automatically as external project" 1) +option(GET_SIXENSE "Get Sixense library automatically as external project" 1) option(USE_NSIGHT "Attempt to find the nSight libraries" 1) diff --git a/cmake/externals/sixense/CMakeLists.txt b/cmake/externals/sixense/CMakeLists.txt index c80b492509..d0778774cb 100644 --- a/cmake/externals/sixense/CMakeLists.txt +++ b/cmake/externals/sixense/CMakeLists.txt @@ -7,54 +7,55 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) ExternalProject_Add( ${EXTERNAL_NAME} - URL ./SixenseSDK_062612.zip - URL_MD5 10cc8dc470d2ac1244a88cf04bc549cc + URL http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_071615.zip + URL_MD5 752a3901f334124e9cffc2ba4136ef7d CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" LOG_DOWNLOAD 1 ) -if (APPLE) - find_library(SIXENSE_LIBRARY_RELEASE lib/osx_x64/release_dll/libsixense_x64.dylib HINTS ${SIXENSE_SEARCH_DIRS}) - find_library(SIXENSE_LIBRARY_DEBUG lib/osx_x64/debug_dll/libsixensed_x64.dylib HINTS ${SIXENSE_SEARCH_DIRS}) -elseif (UNIX) - find_library(SIXENSE_LIBRARY_RELEASE lib/linux_x64/release/libsixense_x64.so HINTS ${SIXENSE_SEARCH_DIRS}) - # find_library(SIXENSE_LIBRARY_DEBUG lib/linux_x64/debug/libsixensed_x64.so HINTS ${SIXENSE_SEARCH_DIRS}) -elseif (WIN32) -endif () - - - ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL) if (WIN32) - - if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") - set(ARCH_DIR "x64") - set(ARCH_SUFFIX "_x64") - else() - set(ARCH_DIR "Win32") - set(ARCH_SUFFIX "") - endif() + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(ARCH_DIR "x64/VS2013") + set(ARCH_SUFFIX "_x64") + else() + set(ARCH_DIR "Win32/VS2013") + set(ARCH_SUFFIX "") + endif() + + set(LIB_DIR "${SOURCE_DIR}/lib/${ARCH_DIR}") + set(BIN_DIR "${SOURCE_DIR}/bin/${ARCH_DIR}") + set(SIXENSE_LIBRARY_RELEASE "${LIB_DIR}/release_dll/sixense${ARCH_SUFFIX}.lib" CACHE FILEPATH "Sixense release lib") + set(SIXENSE_LIBRARY_DEBUG "${LIB_DIR}/debug_dll/sixensed${ARCH_SUFFIX}.lib" CACHE FILEPATH "Sixense debug lib") + set(SIXENSE_RELEASE_DLL_PATH "${BIN_DIR}/release_dll" CACHE FILEPATH "Sixense release DLL path") + set(SIXENSE_DEBUG_DLL_PATH "${BIN_DIR}/debug_dll" CACHE FILEPATH "Sixense debug DLL path") # FIXME need to account for different architectures - set(${EXTERNAL_NAME_UPPER}_LIBRARIES "${SOURCE_DIR}/lib/${ARCH_DIR}/release_dll/sixense${ARCH_SUFFIX}.lib" CACHE TYPE INTERNAL) - add_paths_to_fixup_libs(${SOURCE_DIR}/bin/win32) + add_paths_to_fixup_libs(${SIXENSE_DEBUG_DLL_PATH}) + add_paths_to_fixup_libs(${SIXENSE_RELEASE_DLL_PATH}) elseif(APPLE) - # FIXME need to account for different architectures - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/osx32/libopenvr_api.dylib CACHE TYPE INTERNAL) - add_paths_to_fixup_libs(${SOURCE_DIR}/bin/osx32) + set(ARCH_DIR "osx_x64") + set(ARCH_SUFFIX "_x64") + set(LIB_DIR "${SOURCE_DIR}/lib/${ARCH_DIR}") + + set(SIXENSE_LIBRARY_RELEASE "${LIB_DIR}/release_dll/libsixense${ARCH_SUFFIX}.dylib" CACHE FILEPATH "Sixense release lib") + set(SIXENSE_LIBRARY_DEBUG "${LIB_DIR}/debug_dll/libsixensed${ARCH_SUFFIX}.dylib" CACHE FILEPATH "Sixense debug lib") elseif(NOT ANDROID) - # FIXME need to account for different architectures - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/linux32/libopenvr_api.so CACHE TYPE INTERNAL) - add_paths_to_fixup_libs(${SOURCE_DIR}/bin/linux32) - + set(ARCH_DIR "linux_x64") + set(ARCH_SUFFIX "_x64") + set(LIB_DIR "${SOURCE_DIR}/lib/${ARCH_DIR}") + + set(SIXENSE_LIBRARY_RELEASE "${LIB_DIR}/release/libsixense${ARCH_SUFFIX}.so" CACHE FILEPATH "Sixense release lib") + set(SIXENSE_LIBRARY_DEBUG "${LIB_DIR}/debug/libsixensed${ARCH_SUFFIX}.so" CACHE FILEPATH "Sixense debug lib") + endif() diff --git a/cmake/modules/FindSixense.cmake b/cmake/modules/FindSixense.cmake index 98b37d5410..64cc1e0ffb 100644 --- a/cmake/modules/FindSixense.cmake +++ b/cmake/modules/FindSixense.cmake @@ -51,7 +51,7 @@ select_library_configurations(SIXENSE) set(SIXENSE_REQUIREMENTS SIXENSE_INCLUDE_DIRS SIXENSE_LIBRARIES) if (WIN32) - list(APPEND SIXENSE_REQUIREMENTS SIXENSE_DEBUG_DLL_PATH SIXENSE_RELEASE_DLL_PATH SIXENSE_DEVICE_DLL_PATH) + list(APPEND SIXENSE_REQUIREMENTS SIXENSE_DEBUG_DLL_PATH SIXENSE_RELEASE_DLL_PATH) endif () set(SIXENSE_LIBRARIES "${SIXENSE_LIBRARY}") diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index c3ded6c587..41cee2f666 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -28,10 +28,10 @@ if (WIN32) target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES}) endif() -#add_dependency_external_projects(Sixense) -#find_package(Sixense REQUIRED) -#target_include_directories(${TARGET_NAME} PRIVATE ${SIXENSE_INCLUDE_DIRS}) -#target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES}) +add_dependency_external_projects(Sixense) +find_package(Sixense REQUIRED) +target_include_directories(${TARGET_NAME} PRIVATE ${SIXENSE_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES}) # perform standard include and linking for found externals foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) From 86e21c91ba3fa3e5057786aee1beec3ce296f6a0 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 18 Aug 2015 15:08:48 -0700 Subject: [PATCH 43/47] Case issues again --- cmake/externals/{sixense => Sixense}/CMakeLists.txt | 8 +++----- libraries/input-plugins/CMakeLists.txt | 3 ++- 2 files changed, 5 insertions(+), 6 deletions(-) rename cmake/externals/{sixense => Sixense}/CMakeLists.txt (96%) diff --git a/cmake/externals/sixense/CMakeLists.txt b/cmake/externals/Sixense/CMakeLists.txt similarity index 96% rename from cmake/externals/sixense/CMakeLists.txt rename to cmake/externals/Sixense/CMakeLists.txt index d0778774cb..7991ccea1b 100644 --- a/cmake/externals/sixense/CMakeLists.txt +++ b/cmake/externals/Sixense/CMakeLists.txt @@ -1,10 +1,5 @@ -include(ExternalProject) -include(SelectLibraryConfigurations) - set(EXTERNAL_NAME Sixense) -string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) - ExternalProject_Add( ${EXTERNAL_NAME} URL http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_071615.zip @@ -15,8 +10,11 @@ ExternalProject_Add( LOG_DOWNLOAD 1 ) +set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") + ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL) if (WIN32) diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index 41cee2f666..28af865c7a 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -32,6 +32,7 @@ add_dependency_external_projects(Sixense) find_package(Sixense REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${SIXENSE_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES}) +message( ${SIXENSE_INCLUDE_DIRS}) # perform standard include and linking for found externals foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) @@ -69,4 +70,4 @@ foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) add_definitions(-DSIXENSE_LIB_FILENAME=\"${${${EXTERNAL}_UPPERCASE}_LIBRARY_RELEASE}\") endif () endif () -endforeach() \ No newline at end of file +endforeach() From 7f09df1d0ba4877a6a9c7b032dab6bc25e8f389c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 18 Aug 2015 16:17:27 -0700 Subject: [PATCH 44/47] Fixing external --- cmake/externals/Sixense/CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmake/externals/Sixense/CMakeLists.txt b/cmake/externals/Sixense/CMakeLists.txt index 7991ccea1b..46341bd37b 100644 --- a/cmake/externals/Sixense/CMakeLists.txt +++ b/cmake/externals/Sixense/CMakeLists.txt @@ -1,3 +1,6 @@ +include(ExternalProject) +include(SelectLibraryConfigurations) + set(EXTERNAL_NAME Sixense) ExternalProject_Add( From 940390ee46b1fa9663ba19282d271b076f401539 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Tue, 18 Aug 2015 19:31:05 -0700 Subject: [PATCH 45/47] make enable-avatar-collisions menu item work again --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 939d733a13..f074dc5ac7 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -258,7 +258,7 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::NamesAboveHeads, 0, true); addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::BlueSpeechSphere, 0, true); addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::EnableCharacterController, 0, true, - avatar, SLOT(updateMotionBehavior())); + avatar, SLOT(updateMotionBehaviorFromMenu())); MenuWrapper* viewMenu = addMenu("View"); addActionToQMenuAndActionHash(viewMenu, MenuOption::ReloadContent, 0, qApp, SLOT(reloadResourceCaches())); From aba7bebf6e5623be7c352ab79336703e51dd6f48 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 19 Aug 2015 09:44:51 -0700 Subject: [PATCH 46/47] Revert "Updating to the new version of the sixense library" --- CMakeLists.txt | 1 - cmake/externals/Sixense/CMakeLists.txt | 62 -------------------------- cmake/externals/sixense/CMakeLists.txt | 60 +++++++++++++++++++++++++ cmake/modules/FindSixense.cmake | 2 +- libraries/input-plugins/CMakeLists.txt | 11 +++-- 5 files changed, 66 insertions(+), 70 deletions(-) delete mode 100644 cmake/externals/Sixense/CMakeLists.txt create mode 100644 cmake/externals/sixense/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 41b88e4cea..38bcb42e26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -187,7 +187,6 @@ option(GET_OPENVR "Get OpenVR library automatically as external project" 1) option(GET_BOOSTCONFIG "Get Boost-config library automatically as external project" 1) option(GET_OGLPLUS "Get OGLplus library automatically as external project" 1) option(GET_GLEW "Get GLEW library automatically as external project" 1) -option(GET_SIXENSE "Get Sixense library automatically as external project" 1) option(USE_NSIGHT "Attempt to find the nSight libraries" 1) diff --git a/cmake/externals/Sixense/CMakeLists.txt b/cmake/externals/Sixense/CMakeLists.txt deleted file mode 100644 index 46341bd37b..0000000000 --- a/cmake/externals/Sixense/CMakeLists.txt +++ /dev/null @@ -1,62 +0,0 @@ -include(ExternalProject) -include(SelectLibraryConfigurations) - -set(EXTERNAL_NAME Sixense) - -ExternalProject_Add( - ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/SixenseSDK_071615.zip - URL_MD5 752a3901f334124e9cffc2ba4136ef7d - CONFIGURE_COMMAND "" - BUILD_COMMAND "" - INSTALL_COMMAND "" - LOG_DOWNLOAD 1 -) - -set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") - -ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) - -string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL) - -if (WIN32) - if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") - set(ARCH_DIR "x64/VS2013") - set(ARCH_SUFFIX "_x64") - else() - set(ARCH_DIR "Win32/VS2013") - set(ARCH_SUFFIX "") - endif() - - set(LIB_DIR "${SOURCE_DIR}/lib/${ARCH_DIR}") - set(BIN_DIR "${SOURCE_DIR}/bin/${ARCH_DIR}") - set(SIXENSE_LIBRARY_RELEASE "${LIB_DIR}/release_dll/sixense${ARCH_SUFFIX}.lib" CACHE FILEPATH "Sixense release lib") - set(SIXENSE_LIBRARY_DEBUG "${LIB_DIR}/debug_dll/sixensed${ARCH_SUFFIX}.lib" CACHE FILEPATH "Sixense debug lib") - set(SIXENSE_RELEASE_DLL_PATH "${BIN_DIR}/release_dll" CACHE FILEPATH "Sixense release DLL path") - set(SIXENSE_DEBUG_DLL_PATH "${BIN_DIR}/debug_dll" CACHE FILEPATH "Sixense debug DLL path") - - # FIXME need to account for different architectures - add_paths_to_fixup_libs(${SIXENSE_DEBUG_DLL_PATH}) - add_paths_to_fixup_libs(${SIXENSE_RELEASE_DLL_PATH}) - -elseif(APPLE) - - set(ARCH_DIR "osx_x64") - set(ARCH_SUFFIX "_x64") - set(LIB_DIR "${SOURCE_DIR}/lib/${ARCH_DIR}") - - set(SIXENSE_LIBRARY_RELEASE "${LIB_DIR}/release_dll/libsixense${ARCH_SUFFIX}.dylib" CACHE FILEPATH "Sixense release lib") - set(SIXENSE_LIBRARY_DEBUG "${LIB_DIR}/debug_dll/libsixensed${ARCH_SUFFIX}.dylib" CACHE FILEPATH "Sixense debug lib") - -elseif(NOT ANDROID) - - set(ARCH_DIR "linux_x64") - set(ARCH_SUFFIX "_x64") - set(LIB_DIR "${SOURCE_DIR}/lib/${ARCH_DIR}") - - set(SIXENSE_LIBRARY_RELEASE "${LIB_DIR}/release/libsixense${ARCH_SUFFIX}.so" CACHE FILEPATH "Sixense release lib") - set(SIXENSE_LIBRARY_DEBUG "${LIB_DIR}/debug/libsixensed${ARCH_SUFFIX}.so" CACHE FILEPATH "Sixense debug lib") - -endif() - diff --git a/cmake/externals/sixense/CMakeLists.txt b/cmake/externals/sixense/CMakeLists.txt new file mode 100644 index 0000000000..c80b492509 --- /dev/null +++ b/cmake/externals/sixense/CMakeLists.txt @@ -0,0 +1,60 @@ +include(ExternalProject) +include(SelectLibraryConfigurations) + +set(EXTERNAL_NAME Sixense) + +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + +ExternalProject_Add( + ${EXTERNAL_NAME} + URL ./SixenseSDK_062612.zip + URL_MD5 10cc8dc470d2ac1244a88cf04bc549cc + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 +) + +if (APPLE) + find_library(SIXENSE_LIBRARY_RELEASE lib/osx_x64/release_dll/libsixense_x64.dylib HINTS ${SIXENSE_SEARCH_DIRS}) + find_library(SIXENSE_LIBRARY_DEBUG lib/osx_x64/debug_dll/libsixensed_x64.dylib HINTS ${SIXENSE_SEARCH_DIRS}) +elseif (UNIX) + find_library(SIXENSE_LIBRARY_RELEASE lib/linux_x64/release/libsixense_x64.so HINTS ${SIXENSE_SEARCH_DIRS}) + # find_library(SIXENSE_LIBRARY_DEBUG lib/linux_x64/debug/libsixensed_x64.so HINTS ${SIXENSE_SEARCH_DIRS}) +elseif (WIN32) +endif () + + + +ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL) + +if (WIN32) + + if ("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(ARCH_DIR "x64") + set(ARCH_SUFFIX "_x64") + else() + set(ARCH_DIR "Win32") + set(ARCH_SUFFIX "") + endif() + + # FIXME need to account for different architectures + set(${EXTERNAL_NAME_UPPER}_LIBRARIES "${SOURCE_DIR}/lib/${ARCH_DIR}/release_dll/sixense${ARCH_SUFFIX}.lib" CACHE TYPE INTERNAL) + add_paths_to_fixup_libs(${SOURCE_DIR}/bin/win32) + +elseif(APPLE) + + # FIXME need to account for different architectures + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/osx32/libopenvr_api.dylib CACHE TYPE INTERNAL) + add_paths_to_fixup_libs(${SOURCE_DIR}/bin/osx32) + +elseif(NOT ANDROID) + + # FIXME need to account for different architectures + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/linux32/libopenvr_api.so CACHE TYPE INTERNAL) + add_paths_to_fixup_libs(${SOURCE_DIR}/bin/linux32) + +endif() + diff --git a/cmake/modules/FindSixense.cmake b/cmake/modules/FindSixense.cmake index 64cc1e0ffb..98b37d5410 100644 --- a/cmake/modules/FindSixense.cmake +++ b/cmake/modules/FindSixense.cmake @@ -51,7 +51,7 @@ select_library_configurations(SIXENSE) set(SIXENSE_REQUIREMENTS SIXENSE_INCLUDE_DIRS SIXENSE_LIBRARIES) if (WIN32) - list(APPEND SIXENSE_REQUIREMENTS SIXENSE_DEBUG_DLL_PATH SIXENSE_RELEASE_DLL_PATH) + list(APPEND SIXENSE_REQUIREMENTS SIXENSE_DEBUG_DLL_PATH SIXENSE_RELEASE_DLL_PATH SIXENSE_DEVICE_DLL_PATH) endif () set(SIXENSE_LIBRARIES "${SIXENSE_LIBRARY}") diff --git a/libraries/input-plugins/CMakeLists.txt b/libraries/input-plugins/CMakeLists.txt index 28af865c7a..c3ded6c587 100644 --- a/libraries/input-plugins/CMakeLists.txt +++ b/libraries/input-plugins/CMakeLists.txt @@ -28,11 +28,10 @@ if (WIN32) target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES}) endif() -add_dependency_external_projects(Sixense) -find_package(Sixense REQUIRED) -target_include_directories(${TARGET_NAME} PRIVATE ${SIXENSE_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES}) -message( ${SIXENSE_INCLUDE_DIRS}) +#add_dependency_external_projects(Sixense) +#find_package(Sixense REQUIRED) +#target_include_directories(${TARGET_NAME} PRIVATE ${SIXENSE_INCLUDE_DIRS}) +#target_link_libraries(${TARGET_NAME} ${SIXENSE_LIBRARIES}) # perform standard include and linking for found externals foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) @@ -70,4 +69,4 @@ foreach(EXTERNAL ${OPTIONAL_EXTERNALS}) add_definitions(-DSIXENSE_LIB_FILENAME=\"${${${EXTERNAL}_UPPERCASE}_LIBRARY_RELEASE}\") endif () endif () -endforeach() +endforeach() \ No newline at end of file From 0a8c1846e9539e5320cefde79d8416bbd0cb1124 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 19 Aug 2015 10:24:31 -0700 Subject: [PATCH 47/47] This assert causes dev builds to fail when starting interface. --- libraries/render-utils/src/OffscreenQmlSurface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/OffscreenQmlSurface.cpp b/libraries/render-utils/src/OffscreenQmlSurface.cpp index 0dfd95a725..9923849aab 100644 --- a/libraries/render-utils/src/OffscreenQmlSurface.cpp +++ b/libraries/render-utils/src/OffscreenQmlSurface.cpp @@ -239,7 +239,7 @@ private: return; } - Q_ASSERT(toGlm(_quickWindow->geometry().size()) == _size); + //Q_ASSERT(toGlm(_quickWindow->geometry().size()) == _size); //Q_ASSERT(toGlm(_quickWindow->geometry().size()) == _textures._size); _renderControl->sync();