From af5883e1c0b214bc8a163c03efba8f4453b5d875 Mon Sep 17 00:00:00 2001 From: xG5 Date: Tue, 26 Jul 2022 10:02:18 +0200 Subject: [PATCH 1/6] add node size varying. --- include/polyscope/curve_network.h | 33 ++++++ src/curve_network.cpp | 144 +++++++++++++++++++++++++- src/curve_network_scalar_quantity.cpp | 2 +- 3 files changed, 175 insertions(+), 4 deletions(-) diff --git a/include/polyscope/curve_network.h b/include/polyscope/curve_network.h index 78a326e3..de81dc20 100644 --- a/include/polyscope/curve_network.h +++ b/include/polyscope/curve_network.h @@ -124,10 +124,32 @@ class CurveNetwork : public QuantityStructure { CurveNetwork* setColor(glm::vec3 newVal); glm::vec3 getColor(); + + // === Set radius from a scalar quantity + // effect is multiplicative with pointRadius + // negative values are always clamped to 0 + // if autoScale==true, values are rescaled such that the largest has size pointRadius + void setNodeRadiusQuantity(CurveNetworkNodeScalarQuantity* quantity, bool autoScale = true); + void setNodeRadiusQuantity(std::string name, bool autoScale = true); + void clearNodeRadiusQuantity(); + // void setNodeRadiusQuantity(CurveNetworkNodeScalarQuantity* quantity, bool autoScale = true); + // void setNodeRadiusQuantity(std::string name, bool autoScale = true); + // void clearNodeRadiusQuantity(); + + // void setEdgeRadiusQuantity(CurveNetworkEdgeScalarQuantity* quantity, bool autoScale = true); + // void setEdgeRadiusQuantity(std::string name, bool autoScale = true); + // void clearEdgeRadiusQuantity(); + // set the radius of the points CurveNetwork* setRadius(float newVal, bool isRelative = true); float getRadius(); + // CurveNetwork* setNodeRadius(float newVal, bool isRelative = true); + // float getNodeRadius(); + + // CurveNetwork* setEdgeRadius(float newVal, bool isRelative = true); + // float getEdgeRadius(); + // Material CurveNetwork* setMaterial(std::string name); std::string getMaterial(); @@ -137,6 +159,8 @@ class CurveNetwork : public QuantityStructure { // === Visualization parameters PersistentValue color; PersistentValue> radius; + // PersistentValue> nodeRadius; + // PersistentValue> edgeRadius; PersistentValue material; @@ -168,6 +192,15 @@ class CurveNetwork : public QuantityStructure { CurveNetworkNodeVectorQuantity* addNodeVectorQuantityImpl(std::string name, const std::vector& vectors, VectorType vectorType); CurveNetworkEdgeVectorQuantity* addEdgeVectorQuantityImpl(std::string name, const std::vector& vectors, VectorType vectorType); // clang-format on + + // Manage varying node, edge size + std::string nodeRadiusQuantityName = ""; // e empty string means none + bool nodeRadiusQuantityAutoscale = true; + std::vector resolveNodeRadiusQuantity(); // helper + + // std::string edgeRadiusQuantityName = ""; // e empty string means none + // bool edgeRadiusQuantityAutoscale = true; + // std::vector resolveEdgeRadiusQuantity(); // helper }; diff --git a/src/curve_network.cpp b/src/curve_network.cpp index 85d736ff..7519542a 100644 --- a/src/curve_network.cpp +++ b/src/curve_network.cpp @@ -56,7 +56,12 @@ void CurveNetwork::setCurveNetworkNodeUniforms(render::ShaderProgram& p) { glm::mat4 Pinv = glm::inverse(P); p.setUniform("u_invProjMatrix", glm::value_ptr(Pinv)); p.setUniform("u_viewport", render::engine->getCurrentViewport()); - p.setUniform("u_pointRadius", getRadius()); + if (nodeRadiusQuantityName != "" && nodeRadiusQuantityAutoscale) { + p.setUniform("u_pointRadius", 1.); // u_pointRadius in sphere shader + } else { + p.setUniform("u_pointRadius", getRadius()); + } + // p.setUniform("u_pointRadius", getRadius()); } void CurveNetwork::setCurveNetworkEdgeUniforms(render::ShaderProgram& p) { @@ -64,7 +69,7 @@ void CurveNetwork::setCurveNetworkEdgeUniforms(render::ShaderProgram& p) { glm::mat4 Pinv = glm::inverse(P); p.setUniform("u_invProjMatrix", glm::value_ptr(Pinv)); p.setUniform("u_viewport", render::engine->getCurrentViewport()); - p.setUniform("u_radius", getRadius()); + p.setUniform("u_radius", getRadius()); // u_radius in cylinder shader } void CurveNetwork::draw() { @@ -124,6 +129,9 @@ void CurveNetwork::drawPick() { std::vector CurveNetwork::addCurveNetworkNodeRules(std::vector initRules) { initRules = addStructureRules(initRules); + if (nodeRadiusQuantityName != "") { + initRules.push_back("SPHERE_VARIABLE_SIZE"); + } if (wantsCullPosition()) { initRules.push_back("SPHERE_CULLPOS_FROM_CENTER"); } @@ -223,6 +231,12 @@ void CurveNetwork::preparePick() { void CurveNetwork::fillNodeGeometryBuffers(render::ShaderProgram& program) { program.setAttribute("a_position", nodes); + + if (nodeRadiusQuantityName != "") { + // Resolve the quantity + std::vector nodeRadiusQuantityVals = resolveNodeRadiusQuantity(); + program.setAttribute("a_pointRadius", nodeRadiusQuantityVals); + } } void CurveNetwork::fillEdgeGeometryBuffers(render::ShaderProgram& program) { @@ -371,12 +385,61 @@ CurveNetwork* CurveNetwork::setColor(glm::vec3 newVal) { } glm::vec3 CurveNetwork::getColor() { return color.get(); } +void CurveNetwork::setNodeRadiusQuantity(CurveNetworkNodeScalarQuantity* quantity, bool autoScale) { + setNodeRadiusQuantity(quantity->name, autoScale); +} +void CurveNetwork::setNodeRadiusQuantity(std::string name, bool autoScale) { + nodeRadiusQuantityName = name; + nodeRadiusQuantityAutoscale = autoScale; + + resolveNodeRadiusQuantity(); // do it once, just so we fail fast if it doesn't exist + + refresh(); // TODO this is a bit overkill +} +void CurveNetwork::clearNodeRadiusQuantity() { + nodeRadiusQuantityName = ""; + refresh(); +}; +// void CurveNetwork::setEdgeRadiusQuantity(CurveNetworkEdgeScalarQuantity* quantity, bool autoScale) { +// setEdgeRadiusQuantity(quantity->name, autoScale); +// } +// +// void CurveNetwork::setEdgeRadiusQuantity(std::string name, bool autoScale) { +// edgeRadiusQuantityName = name; +// edgeRadiusQuantityAutoscale = autoScale; +// +// resolveEdgeRadiusQuantity(); // do it once, just so we fail fast if it doesn't exist +// +// refresh(); // TODO this is a bit overkill +// } +// +// void CurveNetwork::clearEdgeRadiusQuantity() { +// edgeRadiusQuantityName = ""; +// refresh(); +// } + CurveNetwork* CurveNetwork::setRadius(float newVal, bool isRelative) { radius = ScaledValue(newVal, isRelative); + // nodeRadius = ScaledValue(newVal, isRelative); + // edgeRadius = ScaledValue(newVal, isRelative); polyscope::requestRedraw(); return this; } -float CurveNetwork::getRadius() { return radius.get().asAbsolute(); } +float CurveNetwork::getRadius() { return radius.get().asAbsolute(); } // TODO: what should we return? + +// CurveNetwork* CurveNetwork::setNodeRadius(float newVal, bool isRelative) { +// nodeRadius = ScaledValue(newVal, isRelative); +// polyscope::requestRedraw(); +// return this; +// } +// float CurveNetwork::getNodeRadius() { return nodeRadius.get().asAbsolute(); } +// +// CurveNetwork* CurveNetwork::setEdgeRadius(float newVal, bool isRelative) { +// edgeRadius = ScaledValue(newVal, isRelative); +// polyscope::requestRedraw(); +// return this; +// } +// float CurveNetwork::getEdgeRadius() { return edgeRadius.get().asAbsolute(); } CurveNetwork* CurveNetwork::setMaterial(std::string m) { material = m; @@ -445,5 +508,80 @@ CurveNetworkEdgeVectorQuantity* CurveNetwork::addEdgeVectorQuantityImpl(std::str return q; } +std::vector CurveNetwork::resolveNodeRadiusQuantity() { + CurveNetworkScalarQuantity* sizeScalarQ = nullptr; + CurveNetworkQuantity* sizeQ = getQuantity(nodeRadiusQuantityName); + if (sizeQ != nullptr) { + sizeScalarQ = dynamic_cast(sizeQ); + if (sizeScalarQ == nullptr) { + polyscope::error("Cannot populate point size from quantity [" + name + "], it is not a scalar quantity"); + } + } else { + polyscope::error("Cannot populate point size from quantity [" + name + "], it does not exist"); + } + + std::vector sizes; + if (sizeScalarQ == nullptr || sizeScalarQ->values.size() != nNodes()) { + // we failed to resolve above; populate with dummy data so we can continue processing + std::vector ones(nNodes(), 1.); + sizes = ones; + polyscope::error("quantity # != node #"); + } else { + sizes = sizeScalarQ->values; + } + + // clamp to nonnegative and autoscale (if requested) + double max = 0; + for (double& x : sizes) { + if (!(x > 0)) x = 0; // ensure all nonnegative + max = std::fmax(max, x); + } + if (max == 0) max = 1e-6; + if (nodeRadiusQuantityAutoscale) { + for (double& x : sizes) { + x /= max; + } + } + + return sizes; +} + +// std::vector CurveNetwork::resolveEdgeRadiusQuantity() { +// CurveNetworkScalarQuantity* sizeScalarQ = nullptr; +// CurveNetworkQuantity* sizeQ = getQuantity(nodeRadiusQuantityName); +// if (sizeQ != nullptr) { +// sizeScalarQ = dynamic_cast(sizeQ); +// if (sizeScalarQ == nullptr) { +// polyscope::error("Cannot populate point size from quantity [" + name + "], it is not a scalar quantity"); +// } +// } else { +// polyscope::error("Cannot populate point size from quantity [" + name + "], it does not exist"); +// } +// +// std::vector sizes; +// if (sizeScalarQ == nullptr || sizeScalarQ->values.size() != nEdges()) { +// // we failed to resolve above; populate with dummy data so we can continue processing +// std::vector ones(nEdges(), 1.); +// sizes = ones; +// polyscope::error("quantity # != edge #"); +// } else { +// sizes = sizeScalarQ->values; +// } +// +// // clamp to nonnegative and autoscale (if requested) +// double max = 0; +// for (double& x : sizes) { +// if (!(x > 0)) x = 0; // ensure all nonnegative +// max = std::fmax(max, x); +// } +// if (max == 0) max = 1e-6; +// if (nodeRadiusQuantityAutoscale) { +// for (double& x : sizes) { +// x /= max; +// } +// } +// +// return sizes; +// } } // namespace polyscope diff --git a/src/curve_network_scalar_quantity.cpp b/src/curve_network_scalar_quantity.cpp index 84d0d224..71b9784d 100644 --- a/src/curve_network_scalar_quantity.cpp +++ b/src/curve_network_scalar_quantity.cpp @@ -79,8 +79,8 @@ void CurveNetworkNodeScalarQuantity::createProgram() { "RAYCAST_CYLINDER", addScalarRules(parent.addCurveNetworkEdgeRules({"CYLINDER_PROPAGATE_BLEND_VALUE"}))); // Fill geometry buffers - parent.fillEdgeGeometryBuffers(*edgeProgram); parent.fillNodeGeometryBuffers(*nodeProgram); + parent.fillEdgeGeometryBuffers(*edgeProgram); { // Fill node color buffers nodeProgram->setAttribute("a_value", values); From a22386bb899e97ff7080210a612be28d19f1521a Mon Sep 17 00:00:00 2001 From: xG5 Date: Tue, 26 Jul 2022 10:23:31 +0200 Subject: [PATCH 2/6] small cleanup. --- include/polyscope/curve_network.h | 9 --------- src/curve_network.cpp | 16 ---------------- 2 files changed, 25 deletions(-) diff --git a/include/polyscope/curve_network.h b/include/polyscope/curve_network.h index de81dc20..75e4aa2f 100644 --- a/include/polyscope/curve_network.h +++ b/include/polyscope/curve_network.h @@ -132,9 +132,6 @@ class CurveNetwork : public QuantityStructure { void setNodeRadiusQuantity(CurveNetworkNodeScalarQuantity* quantity, bool autoScale = true); void setNodeRadiusQuantity(std::string name, bool autoScale = true); void clearNodeRadiusQuantity(); - // void setNodeRadiusQuantity(CurveNetworkNodeScalarQuantity* quantity, bool autoScale = true); - // void setNodeRadiusQuantity(std::string name, bool autoScale = true); - // void clearNodeRadiusQuantity(); // void setEdgeRadiusQuantity(CurveNetworkEdgeScalarQuantity* quantity, bool autoScale = true); // void setEdgeRadiusQuantity(std::string name, bool autoScale = true); @@ -144,12 +141,6 @@ class CurveNetwork : public QuantityStructure { CurveNetwork* setRadius(float newVal, bool isRelative = true); float getRadius(); - // CurveNetwork* setNodeRadius(float newVal, bool isRelative = true); - // float getNodeRadius(); - - // CurveNetwork* setEdgeRadius(float newVal, bool isRelative = true); - // float getEdgeRadius(); - // Material CurveNetwork* setMaterial(std::string name); std::string getMaterial(); diff --git a/src/curve_network.cpp b/src/curve_network.cpp index 7519542a..ffd87689 100644 --- a/src/curve_network.cpp +++ b/src/curve_network.cpp @@ -420,27 +420,11 @@ void CurveNetwork::clearNodeRadiusQuantity() { CurveNetwork* CurveNetwork::setRadius(float newVal, bool isRelative) { radius = ScaledValue(newVal, isRelative); - // nodeRadius = ScaledValue(newVal, isRelative); - // edgeRadius = ScaledValue(newVal, isRelative); polyscope::requestRedraw(); return this; } float CurveNetwork::getRadius() { return radius.get().asAbsolute(); } // TODO: what should we return? -// CurveNetwork* CurveNetwork::setNodeRadius(float newVal, bool isRelative) { -// nodeRadius = ScaledValue(newVal, isRelative); -// polyscope::requestRedraw(); -// return this; -// } -// float CurveNetwork::getNodeRadius() { return nodeRadius.get().asAbsolute(); } -// -// CurveNetwork* CurveNetwork::setEdgeRadius(float newVal, bool isRelative) { -// edgeRadius = ScaledValue(newVal, isRelative); -// polyscope::requestRedraw(); -// return this; -// } -// float CurveNetwork::getEdgeRadius() { return edgeRadius.get().asAbsolute(); } - CurveNetwork* CurveNetwork::setMaterial(std::string m) { material = m; refresh(); // (serves the purpose of re-initializing everything, though this is a bit overkill) From 7f424ce5dfed5fe9f5897d881fa2f911daa2070d Mon Sep 17 00:00:00 2001 From: xG5 Date: Fri, 29 Jul 2022 14:19:40 +0200 Subject: [PATCH 3/6] register shaderReplacementRule, modify cylinderShader, etc. --- .../render/opengl/shaders/cylinder_shaders.h | 1 + src/curve_network.cpp | 37 +++++++- src/render/mock_opengl/mock_gl_engine.cpp | 1 + src/render/opengl/gl_engine.cpp | 1 + src/render/opengl/shaders/common.cpp | 8 +- .../opengl/shaders/cylinder_shaders.cpp | 85 ++++++++++++++++--- 6 files changed, 112 insertions(+), 21 deletions(-) diff --git a/include/polyscope/render/opengl/shaders/cylinder_shaders.h b/include/polyscope/render/opengl/shaders/cylinder_shaders.h index 3a632377..80c95ea5 100644 --- a/include/polyscope/render/opengl/shaders/cylinder_shaders.h +++ b/include/polyscope/render/opengl/shaders/cylinder_shaders.h @@ -18,6 +18,7 @@ extern const ShaderReplacementRule CYLINDER_PROPAGATE_COLOR; extern const ShaderReplacementRule CYLINDER_PROPAGATE_BLEND_COLOR; extern const ShaderReplacementRule CYLINDER_PROPAGATE_PICK; extern const ShaderReplacementRule CYLINDER_CULLPOS_FROM_MID; +extern const ShaderReplacementRule CYLINDER_VARIABLE_SIZE; } // namespace backend_openGL3_glfw diff --git a/src/curve_network.cpp b/src/curve_network.cpp index ffd87689..5a0a4975 100644 --- a/src/curve_network.cpp +++ b/src/curve_network.cpp @@ -69,7 +69,9 @@ void CurveNetwork::setCurveNetworkEdgeUniforms(render::ShaderProgram& p) { glm::mat4 Pinv = glm::inverse(P); p.setUniform("u_invProjMatrix", glm::value_ptr(Pinv)); p.setUniform("u_viewport", render::engine->getCurrentViewport()); - p.setUniform("u_radius", getRadius()); // u_radius in cylinder shader + p.setUniform("u_radius", getRadius()); + // p.setUniform("u_tipRadius", getRadius()); + // p.setUniform("u_tailRadius", getRadius()); } void CurveNetwork::draw() { @@ -129,6 +131,7 @@ void CurveNetwork::drawPick() { std::vector CurveNetwork::addCurveNetworkNodeRules(std::vector initRules) { initRules = addStructureRules(initRules); + if (nodeRadiusQuantityName != "") { initRules.push_back("SPHERE_VARIABLE_SIZE"); } @@ -139,6 +142,12 @@ std::vector CurveNetwork::addCurveNetworkNodeRules(std::vector CurveNetwork::addCurveNetworkEdgeRules(std::vector initRules) { initRules = addStructureRules(initRules); + + // use node radius to blend cylinder radius + if (nodeRadiusQuantityName != "") { + initRules.push_back("CYLINDER_VARIABLE_SIZE"); + } + if (wantsCullPosition()) { initRules.push_back("CYLINDER_CULLPOS_FROM_MID"); } @@ -253,6 +262,26 @@ void CurveNetwork::fillEdgeGeometryBuffers(render::ShaderProgram& program) { } program.setAttribute("a_position_tail", posTail); program.setAttribute("a_position_tip", posTip); + + + // blend the cylinder's tip/tail radii from the node radii + if (nodeRadiusQuantityName != "") { + // Resolve the quantity + std::vector nodeRadiusQuantityVals = resolveNodeRadiusQuantity(); + std::vector cylinderTipRadiusQuantityVals(nEdges()); + std::vector cylinderTailRadiusQuantityVals(nEdges()); + + for (size_t iE = 0; iE < nEdges(); iE++) { + auto& edge = edges[iE]; + size_t eTip = std::get<0>(edge); + size_t eTail = std::get<1>(edge); + cylinderTipRadiusQuantityVals[iE] = nodeRadiusQuantityVals[eTip]; + cylinderTailRadiusQuantityVals[iE] = nodeRadiusQuantityVals[eTail]; + } + + program.setAttribute("a_tipRadius", cylinderTipRadiusQuantityVals); + program.setAttribute("a_tailRadius", cylinderTailRadiusQuantityVals); + } } void CurveNetwork::refresh() { @@ -336,7 +365,6 @@ void CurveNetwork::buildEdgePickUI(size_t edgeInd) { ImGui::Indent(-20.); } - void CurveNetwork::buildCustomUI() { ImGui::Text("nodes: %lld edges: %lld", static_cast(nNodes()), static_cast(nEdges())); if (ImGui::ColorEdit3("Color", &color.get()[0], ImGuiColorEditFlags_NoInputs)) { @@ -388,6 +416,7 @@ glm::vec3 CurveNetwork::getColor() { return color.get(); } void CurveNetwork::setNodeRadiusQuantity(CurveNetworkNodeScalarQuantity* quantity, bool autoScale) { setNodeRadiusQuantity(quantity->name, autoScale); } + void CurveNetwork::setNodeRadiusQuantity(std::string name, bool autoScale) { nodeRadiusQuantityName = name; nodeRadiusQuantityAutoscale = autoScale; @@ -396,10 +425,12 @@ void CurveNetwork::setNodeRadiusQuantity(std::string name, bool autoScale) { refresh(); // TODO this is a bit overkill } + void CurveNetwork::clearNodeRadiusQuantity() { nodeRadiusQuantityName = ""; refresh(); }; + // void CurveNetwork::setEdgeRadiusQuantity(CurveNetworkEdgeScalarQuantity* quantity, bool autoScale) { // setEdgeRadiusQuantity(quantity->name, autoScale); // } @@ -423,7 +454,7 @@ CurveNetwork* CurveNetwork::setRadius(float newVal, bool isRelative) { polyscope::requestRedraw(); return this; } -float CurveNetwork::getRadius() { return radius.get().asAbsolute(); } // TODO: what should we return? +float CurveNetwork::getRadius() { return radius.get().asAbsolute(); } CurveNetwork* CurveNetwork::setMaterial(std::string m) { material = m; diff --git a/src/render/mock_opengl/mock_gl_engine.cpp b/src/render/mock_opengl/mock_gl_engine.cpp index 384f6077..2e7e4245 100644 --- a/src/render/mock_opengl/mock_gl_engine.cpp +++ b/src/render/mock_opengl/mock_gl_engine.cpp @@ -1456,6 +1456,7 @@ void MockGLEngine::populateDefaultShadersAndRules() { registeredShaderRules.insert({"CYLINDER_PROPAGATE_BLEND_COLOR", CYLINDER_PROPAGATE_BLEND_COLOR}); registeredShaderRules.insert({"CYLINDER_PROPAGATE_PICK", CYLINDER_PROPAGATE_PICK}); registeredShaderRules.insert({"CYLINDER_CULLPOS_FROM_MID", CYLINDER_CULLPOS_FROM_MID}); + registeredShaderRules.insert({"CYLINDER_VARIABLE_SIZE", CYLINDER_VARIABLE_SIZE}); // marching tets things registeredShaderRules.insert({"SLICE_TETS_BASECOLOR_SHADE", SLICE_TETS_BASECOLOR_SHADE}); diff --git a/src/render/opengl/gl_engine.cpp b/src/render/opengl/gl_engine.cpp index ec21d712..cf9b0a1b 100644 --- a/src/render/opengl/gl_engine.cpp +++ b/src/render/opengl/gl_engine.cpp @@ -2144,6 +2144,7 @@ void GLEngine::populateDefaultShadersAndRules() { registeredShaderRules.insert({"CYLINDER_PROPAGATE_BLEND_COLOR", CYLINDER_PROPAGATE_BLEND_COLOR}); registeredShaderRules.insert({"CYLINDER_PROPAGATE_PICK", CYLINDER_PROPAGATE_PICK}); registeredShaderRules.insert({"CYLINDER_CULLPOS_FROM_MID", CYLINDER_CULLPOS_FROM_MID}); + registeredShaderRules.insert({"CYLINDER_VARIABLE_SIZE", CYLINDER_VARIABLE_SIZE}); // marching tets things registeredShaderRules.insert({"SLICE_TETS_BASECOLOR_SHADE", SLICE_TETS_BASECOLOR_SHADE}); diff --git a/src/render/opengl/shaders/common.cpp b/src/render/opengl/shaders/common.cpp index 8e2fecc9..e26723d2 100644 --- a/src/render/opengl/shaders/common.cpp +++ b/src/render/opengl/shaders/common.cpp @@ -197,7 +197,7 @@ bool rayDiskIntersection(vec3 rayStart, vec3 rayDir, vec3 planePos, vec3 planeDi return true; } -bool rayCylinderIntersection(vec3 rayStart, vec3 rayDir, vec3 cylTail, vec3 cylTip, float cylRad, out float tHit, out vec3 pHit, out vec3 nHit) { +bool rayCylinderIntersection(vec3 rayStart, vec3 rayDir, vec3 cylTail, vec3 cylTip, float cylTipRad, float cylTailRad, out float tHit, out vec3 pHit, out vec3 nHit) { rayDir = normalize(rayDir); float cylLen = max(length(cylTip - cylTail), 1e-6); @@ -209,7 +209,7 @@ bool rayCylinderIntersection(vec3 rayStart, vec3 rayDir, vec3 cylTail, vec3 cylT vec3 pVec = o - dot(o, cylDir)*cylDir; float a = length2(qVec); float b = 2.0 * dot(qVec, pVec); - float c = length2(pVec) - cylRad*cylRad; + float c = length2(pVec) - cylTipRad*cylTailRad; // not sure about here. What are we doing in this section? Need comment for the root-solving. float disc = b*b - 4*a*c; if(disc < 0){ tHit = LARGE_FLOAT(); @@ -240,7 +240,7 @@ bool rayCylinderIntersection(vec3 rayStart, vec3 rayDir, vec3 cylTail, vec3 cylT float tHitTail; vec3 pHitTail; vec3 nHitTail; - rayDiskIntersection(rayStart, rayDir, cylTail, -cylDir, cylRad, tHitTail, pHitTail, nHitTail); + rayDiskIntersection(rayStart, rayDir, cylTail, -cylDir, cylTipRad, tHitTail, pHitTail, nHitTail); if(tHitTail < tHit) { tHit = tHitTail; pHit = pHitTail; @@ -251,7 +251,7 @@ bool rayCylinderIntersection(vec3 rayStart, vec3 rayDir, vec3 cylTail, vec3 cylT float tHitTip; vec3 pHitTip; vec3 nHitTip; - rayDiskIntersection(rayStart, rayDir, cylTip, cylDir, cylRad, tHitTip, pHitTip, nHitTip); + rayDiskIntersection(rayStart, rayDir, cylTip, cylDir, cylTailRad, tHitTip, pHitTip, nHitTip); if(tHitTip < tHit) { tHit = tHitTip; pHit = pHitTip; diff --git a/src/render/opengl/shaders/cylinder_shaders.cpp b/src/render/opengl/shaders/cylinder_shaders.cpp index 663a8b6c..b85719d3 100644 --- a/src/render/opengl/shaders/cylinder_shaders.cpp +++ b/src/render/opengl/shaders/cylinder_shaders.cpp @@ -4,7 +4,7 @@ namespace polyscope { namespace render { -namespace backend_openGL3_glfw { +namespace backend_openGL3_glfw { // clang-format off @@ -71,6 +71,8 @@ R"( in vec4 position_tip[]; uniform mat4 u_projMatrix; uniform float u_radius; + //uniform float u_tipRadius; + //uniform float u_tailRadius; out vec3 tipView; out vec3 tailView; @@ -79,6 +81,9 @@ R"( void buildTangentBasis(vec3 unitNormal, out vec3 basisX, out vec3 basisY); void main() { + float tipRadius = u_radius; + float tailRadius = u_radius; + ${ CYLINDER_SET_RADIUS_GEOM }$ // Build an orthogonal basis vec3 tailViewVal = gl_in[0].gl_Position.xyz / gl_in[0].gl_Position.w; @@ -89,17 +94,19 @@ R"( // Compute corners of cube vec4 tailProj = u_projMatrix * gl_in[0].gl_Position; vec4 tipProj = u_projMatrix * position_tip[0]; - vec4 dx = u_projMatrix * vec4(basisX * u_radius, 0.); - vec4 dy = u_projMatrix * vec4(basisY * u_radius, 0.); - - vec4 p1 = tailProj - dx - dy; - vec4 p2 = tailProj + dx - dy; - vec4 p3 = tailProj - dx + dy; - vec4 p4 = tailProj + dx + dy; - vec4 p5 = tipProj - dx - dy; - vec4 p6 = tipProj + dx - dy; - vec4 p7 = tipProj - dx + dy; - vec4 p8 = tipProj + dx + dy; + vec4 dxTip = u_projMatrix * vec4(basisX * tipRadius, 0.); + vec4 dyTip = u_projMatrix * vec4(basisY * tipRadius, 0.); + vec4 dxTail = u_projMatrix * vec4(basisX * tailRadius, 0.); + vec4 dyTail = u_projMatrix * vec4(basisY * tailRadius, 0.); + + vec4 p1 = tailProj - dxTail - dyTail; + vec4 p2 = tailProj + dxTail - dyTail; + vec4 p3 = tailProj - dxTail + dyTail; + vec4 p4 = tailProj + dxTail + dyTail; + vec4 p5 = tipProj - dxTip - dyTip; + vec4 p6 = tipProj + dxTip - dyTip; + vec4 p7 = tipProj - dxTip + dyTip; + vec4 p8 = tipProj + dxTip + dyTip; // Other data to emit @@ -152,13 +159,15 @@ R"( uniform mat4 u_invProjMatrix; uniform vec4 u_viewport; uniform float u_radius; + //uniform float u_tipRadius; + //uniform float u_tailRadius; in vec3 tailView; in vec3 tipView; layout(location = 0) out vec4 outputF; float LARGE_FLOAT(); vec3 fragmentViewPosition(vec4 viewport, vec2 depthRange, mat4 invProjMat, vec4 fragCoord); - bool rayCylinderIntersection(vec3 rayStart, vec3 rayDir, vec3 cylTail, vec3 cylTip, float cylRad, out float tHit, out vec3 pHit, out vec3 nHit); + bool rayCylinderIntersection(vec3 rayStart, vec3 rayDir, vec3 cylTail, vec3 cylTip, float cylTipRad, float cylTailRad, out float tHit, out vec3 pHit, out vec3 nHit); float fragDepthFromView(mat4 projMat, vec2 depthRange, vec3 viewPoint); ${ FRAG_DECLARATIONS }$ @@ -169,11 +178,16 @@ R"( vec2 depthRange = vec2(gl_DepthRange.near, gl_DepthRange.far); vec3 viewRay = fragmentViewPosition(u_viewport, depthRange, u_invProjMatrix, gl_FragCoord); + + float tipRadius = u_radius; + float tailRadius = u_radius; + ${ CYLINDER_SET_RADIUS_FRAG }$ + // Raycast to the cylinder float tHit; vec3 pHit; vec3 nHit; - rayCylinderIntersection(vec3(0., 0., 0), viewRay, tailView, tipView, u_radius, tHit, pHit, nHit); + rayCylinderIntersection(vec3(0., 0., 0), viewRay, tailView, tipView, tipRadius, tailRadius, tHit, pHit, nHit); if(tHit >= LARGE_FLOAT()) { discard; } @@ -421,6 +435,49 @@ const ShaderReplacementRule CYLINDER_PROPAGATE_PICK ( /* textures */ {} ); +const ShaderReplacementRule CYLINDER_VARIABLE_SIZE ( + /* rule name */ "CYLINDER_VARIABLE_SIZE", + { /* replacement sources */ + {"VERT_DECLARATIONS", R"( + in float a_tipRadius; + in float a_tailRadius; + out float a_tipRadiusToGeom; + out float a_tailRadiusToGeom; + )"}, + {"VERT_ASSIGNMENTS", R"( + a_tipRadiusToGeom = a_tipRadius; + a_tailRadiusToGeom = a_tailRadius; + )"}, + {"GEOM_DECLARATIONS", R"( + in float a_tipRadiusToGeom[]; + in float a_tailRadiusToGeom[]; + out float a_tipRadiusToFrag; + out float a_tailRadiusToFrag; + )"}, + {"GEOM_PER_EMIT", R"( + a_tipRadiusToFrag = a_tipRadiusToGeom[0]; + a_tailRadiusToFrag = a_tailRadiusToGeom[0]; + )"}, + {"FRAG_DECLARATIONS", R"( + in float a_tipRadiusToFrag; + in float a_tailRadiusToFrag; + )"}, + {"CYLINDER_SET_RADIUS_GEOM", R"( + tipRadius *= a_tipRadiusToGeom[0]; + tailRadius *= a_tailRadiusToGeom[0]; + )"}, + {"CYLINDER_SET_RADIUS_FRAG", R"( + tipRadius *= a_tipRadiusToFrag; + tailRadius *= a_tailRadiusToFrag; + )"}, + }, + /* uniforms */ {}, + /* attributes */ { + {"a_tipRadius", DataType::Float}, + {"a_tailRadius", DataType::Float}, + }, + /* textures */ {} +); // clang-format on From 290f377622391bd5feb0bd73b41ffee912677d93 Mon Sep 17 00:00:00 2001 From: xG5 Date: Fri, 29 Jul 2022 14:21:05 +0200 Subject: [PATCH 4/6] cleanup. --- include/polyscope/curve_network.h | 6 ---- src/curve_network.cpp | 59 ------------------------------- 2 files changed, 65 deletions(-) diff --git a/include/polyscope/curve_network.h b/include/polyscope/curve_network.h index 75e4aa2f..8e63fae5 100644 --- a/include/polyscope/curve_network.h +++ b/include/polyscope/curve_network.h @@ -133,10 +133,6 @@ class CurveNetwork : public QuantityStructure { void setNodeRadiusQuantity(std::string name, bool autoScale = true); void clearNodeRadiusQuantity(); - // void setEdgeRadiusQuantity(CurveNetworkEdgeScalarQuantity* quantity, bool autoScale = true); - // void setEdgeRadiusQuantity(std::string name, bool autoScale = true); - // void clearEdgeRadiusQuantity(); - // set the radius of the points CurveNetwork* setRadius(float newVal, bool isRelative = true); float getRadius(); @@ -150,8 +146,6 @@ class CurveNetwork : public QuantityStructure { // === Visualization parameters PersistentValue color; PersistentValue> radius; - // PersistentValue> nodeRadius; - // PersistentValue> edgeRadius; PersistentValue material; diff --git a/src/curve_network.cpp b/src/curve_network.cpp index 5a0a4975..97c90271 100644 --- a/src/curve_network.cpp +++ b/src/curve_network.cpp @@ -61,7 +61,6 @@ void CurveNetwork::setCurveNetworkNodeUniforms(render::ShaderProgram& p) { } else { p.setUniform("u_pointRadius", getRadius()); } - // p.setUniform("u_pointRadius", getRadius()); } void CurveNetwork::setCurveNetworkEdgeUniforms(render::ShaderProgram& p) { @@ -70,8 +69,6 @@ void CurveNetwork::setCurveNetworkEdgeUniforms(render::ShaderProgram& p) { p.setUniform("u_invProjMatrix", glm::value_ptr(Pinv)); p.setUniform("u_viewport", render::engine->getCurrentViewport()); p.setUniform("u_radius", getRadius()); - // p.setUniform("u_tipRadius", getRadius()); - // p.setUniform("u_tailRadius", getRadius()); } void CurveNetwork::draw() { @@ -431,24 +428,6 @@ void CurveNetwork::clearNodeRadiusQuantity() { refresh(); }; -// void CurveNetwork::setEdgeRadiusQuantity(CurveNetworkEdgeScalarQuantity* quantity, bool autoScale) { -// setEdgeRadiusQuantity(quantity->name, autoScale); -// } -// -// void CurveNetwork::setEdgeRadiusQuantity(std::string name, bool autoScale) { -// edgeRadiusQuantityName = name; -// edgeRadiusQuantityAutoscale = autoScale; -// -// resolveEdgeRadiusQuantity(); // do it once, just so we fail fast if it doesn't exist -// -// refresh(); // TODO this is a bit overkill -// } -// -// void CurveNetwork::clearEdgeRadiusQuantity() { -// edgeRadiusQuantityName = ""; -// refresh(); -// } - CurveNetwork* CurveNetwork::setRadius(float newVal, bool isRelative) { radius = ScaledValue(newVal, isRelative); polyscope::requestRedraw(); @@ -561,42 +540,4 @@ std::vector CurveNetwork::resolveNodeRadiusQuantity() { return sizes; } -// std::vector CurveNetwork::resolveEdgeRadiusQuantity() { -// CurveNetworkScalarQuantity* sizeScalarQ = nullptr; -// CurveNetworkQuantity* sizeQ = getQuantity(nodeRadiusQuantityName); -// if (sizeQ != nullptr) { -// sizeScalarQ = dynamic_cast(sizeQ); -// if (sizeScalarQ == nullptr) { -// polyscope::error("Cannot populate point size from quantity [" + name + "], it is not a scalar quantity"); -// } -// } else { -// polyscope::error("Cannot populate point size from quantity [" + name + "], it does not exist"); -// } -// -// std::vector sizes; -// if (sizeScalarQ == nullptr || sizeScalarQ->values.size() != nEdges()) { -// // we failed to resolve above; populate with dummy data so we can continue processing -// std::vector ones(nEdges(), 1.); -// sizes = ones; -// polyscope::error("quantity # != edge #"); -// } else { -// sizes = sizeScalarQ->values; -// } -// -// // clamp to nonnegative and autoscale (if requested) -// double max = 0; -// for (double& x : sizes) { -// if (!(x > 0)) x = 0; // ensure all nonnegative -// max = std::fmax(max, x); -// } -// if (max == 0) max = 1e-6; -// if (nodeRadiusQuantityAutoscale) { -// for (double& x : sizes) { -// x /= max; -// } -// } -// -// return sizes; -// } - } // namespace polyscope From f8bc6485fe6d6cb4060a92972c8100786353fc5c Mon Sep 17 00:00:00 2001 From: xG5 Date: Fri, 29 Jul 2022 14:30:27 +0200 Subject: [PATCH 5/6] cleanup. --- include/polyscope/curve_network.h | 4 ---- src/render/opengl/shaders/cylinder_shaders.cpp | 4 ---- 2 files changed, 8 deletions(-) diff --git a/include/polyscope/curve_network.h b/include/polyscope/curve_network.h index 8e63fae5..21d859c4 100644 --- a/include/polyscope/curve_network.h +++ b/include/polyscope/curve_network.h @@ -182,10 +182,6 @@ class CurveNetwork : public QuantityStructure { std::string nodeRadiusQuantityName = ""; // e empty string means none bool nodeRadiusQuantityAutoscale = true; std::vector resolveNodeRadiusQuantity(); // helper - - // std::string edgeRadiusQuantityName = ""; // e empty string means none - // bool edgeRadiusQuantityAutoscale = true; - // std::vector resolveEdgeRadiusQuantity(); // helper }; diff --git a/src/render/opengl/shaders/cylinder_shaders.cpp b/src/render/opengl/shaders/cylinder_shaders.cpp index b85719d3..a6a29e53 100644 --- a/src/render/opengl/shaders/cylinder_shaders.cpp +++ b/src/render/opengl/shaders/cylinder_shaders.cpp @@ -71,8 +71,6 @@ R"( in vec4 position_tip[]; uniform mat4 u_projMatrix; uniform float u_radius; - //uniform float u_tipRadius; - //uniform float u_tailRadius; out vec3 tipView; out vec3 tailView; @@ -159,8 +157,6 @@ R"( uniform mat4 u_invProjMatrix; uniform vec4 u_viewport; uniform float u_radius; - //uniform float u_tipRadius; - //uniform float u_tailRadius; in vec3 tailView; in vec3 tipView; layout(location = 0) out vec4 outputF; From 9955f34ddac5f51348e05d65e159ecdeeae82719 Mon Sep 17 00:00:00 2001 From: ZhaoMA Date: Wed, 15 Mar 2023 15:42:28 +0100 Subject: [PATCH 6/6] add test for varied node radius for curve Network. --- test/src/basics_test.cpp | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/test/src/basics_test.cpp b/test/src/basics_test.cpp index c92f65f3..765561dc 100644 --- a/test/src/basics_test.cpp +++ b/test/src/basics_test.cpp @@ -679,6 +679,37 @@ TEST_F(PolyscopeTest, CurveNetworkScalarEdge) { polyscope::removeAllStructures(); } +TEST_F(PolyscopeTest, CurveNetworkScalarRadius) { + auto psCurve = registerCurveNetwork(); + + std::random_device rd; + std::mt19937 gen(rd()); + std::uniform_int_distribution<> dis(0.1, 10); + + std::vector vScalar(psCurve->nNodes(), 0.1); + std::vector vScalar2(psCurve->nNodes(), 0.1); + std::generate(vScalar.begin(), vScalar.end(), [&]() { return dis(gen); }); + std::generate(vScalar2.begin(), vScalar2.end(), [&]() { return dis(gen); }); + + auto q1 = psCurve->addNodeScalarQuantity("vScalar", vScalar); + auto q2 = psCurve->addNodeScalarQuantity("vScalar2", vScalar2); + q1->setEnabled(true); + + psCurve->setNodeRadiusQuantity(q1); + polyscope::show(3); + + psCurve->setNodeRadiusQuantity("vScalar2"); + polyscope::show(3); + + psCurve->setNodeRadiusQuantity("vScalar2", false); // no autoscaling + polyscope::show(3); + + psCurve->clearNodeRadiusQuantity(); + polyscope::show(3); + + polyscope::removeAllStructures(); +} + TEST_F(PolyscopeTest, CurveNetworkVertexVector) { auto psCurve = registerCurveNetwork(); std::vector vals(psCurve->nNodes(), {1., 2., 3.}); @@ -1078,7 +1109,7 @@ TEST_F(PolyscopeTest, SlicePlaneTest) { polyscope::show(3); psPoints->setCullWholeElements(false); polyscope::show(3); - + polyscope::show(3); // add another and rotate it