@@ -185,6 +185,10 @@ void PointCloud::setPointProgramGeometryAttributes(render::ShaderProgram& p) {
185185 PointCloudScalarQuantity& radQ = resolvePointRadiusQuantity ();
186186 p.setAttribute (" a_pointRadius" , radQ.values .getRenderAttributeBuffer ());
187187 }
188+ if (transparencyQuantityName != " " ) {
189+ PointCloudScalarQuantity& transparencyQ = resolveTransparencyQuantity ();
190+ p.setAttribute (" a_valueAlpha" , transparencyQ.values .getRenderAttributeBuffer ());
191+ }
188192}
189193
190194std::string PointCloud::getShaderNameForRenderMode () {
@@ -212,6 +216,9 @@ std::vector<std::string> PointCloud::addPointCloudRules(std::vector<std::string>
212216 else if (getPointRenderMode () == PointRenderMode::Quad)
213217 initRules.push_back (" SPHERE_CULLPOS_FROM_CENTER_QUAD" );
214218 }
219+ if (transparencyQuantityName != " " ) {
220+ initRules.push_back (" SPHERE_PROPAGATE_VALUEALPHA" );
221+ }
215222 }
216223 return initRules;
217224}
@@ -268,6 +275,11 @@ void PointCloud::buildCustomUI() {
268275}
269276
270277void PointCloud::buildCustomOptionsUI () {
278+ if (render::buildMaterialOptionsGui (material.get ())) {
279+ material.manuallyChanged ();
280+ setMaterial (material.get ()); // trigger the other updates that happen on set()
281+ }
282+
271283 if (ImGui::BeginMenu (" Point Render Mode" )) {
272284
273285 for (const PointRenderMode& m : {PointRenderMode::Sphere, PointRenderMode::Quad}) {
@@ -305,9 +317,21 @@ void PointCloud::buildCustomOptionsUI() {
305317 ImGui::EndMenu ();
306318 }
307319
308- if (render::buildMaterialOptionsGui (material.get ())) {
309- material.manuallyChanged ();
310- setMaterial (material.get ()); // trigger the other updates that happen on set()
320+ // transparency quantity
321+ if (ImGui::BeginMenu (" Per-Point Transparency" )) {
322+
323+ if (ImGui::MenuItem (" none" , nullptr , transparencyQuantityName == " " )) clearTransparencyQuantity ();
324+ ImGui::Separator ();
325+
326+ for (auto & q : quantities) {
327+ PointCloudScalarQuantity* scalarQ = dynamic_cast <PointCloudScalarQuantity*>(q.second .get ());
328+ if (scalarQ != nullptr ) {
329+ if (ImGui::MenuItem (scalarQ->name .c_str (), nullptr , transparencyQuantityName == scalarQ->name ))
330+ setTransparencyQuantity (scalarQ);
331+ }
332+ }
333+
334+ ImGui::EndMenu ();
311335 }
312336}
313337
@@ -362,6 +386,42 @@ void PointCloud::clearPointRadiusQuantity() {
362386 refresh ();
363387}
364388
389+ void PointCloud::setTransparencyQuantity (PointCloudScalarQuantity* quantity) {
390+ setTransparencyQuantity (quantity->name );
391+ }
392+
393+ void PointCloud::setTransparencyQuantity (std::string name) {
394+ transparencyQuantityName = name;
395+ resolveTransparencyQuantity (); // do it once, just so we fail fast if it doesn't exist
396+
397+ // if transparency is disabled, enable it
398+ if (options::transparencyMode == TransparencyMode::None) {
399+ options::transparencyMode = TransparencyMode::Pretty;
400+ }
401+
402+ refresh ();
403+ }
404+
405+ void PointCloud::clearTransparencyQuantity () {
406+ transparencyQuantityName = " " ;
407+ refresh ();
408+ }
409+
410+ PointCloudScalarQuantity& PointCloud::resolveTransparencyQuantity () {
411+ PointCloudScalarQuantity* transparencyScalarQ = nullptr ;
412+ PointCloudQuantity* anyQ = getQuantity (transparencyQuantityName);
413+ if (anyQ != nullptr ) {
414+ transparencyScalarQ = dynamic_cast <PointCloudScalarQuantity*>(anyQ);
415+ if (transparencyScalarQ == nullptr ) {
416+ exception (" Cannot populate per-element transparency from quantity [" + name + " ], it is not a scalar quantity" );
417+ }
418+ } else {
419+ exception (" Cannot populate per-element transparency from quantity [" + name + " ], it does not exist" );
420+ }
421+
422+ return *transparencyScalarQ;
423+ }
424+
365425// === Quantities
366426
367427// Quantity default methods
0 commit comments