Skip to content

Commit c573b9a

Browse files
committed
cleanup to options and some bugfixes
1 parent 851d20d commit c573b9a

6 files changed

Lines changed: 56 additions & 41 deletions

File tree

src/cpp/gaussian_particles.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ void bind_gaussian_particles(nb::module_& m) {
3333
// internal
3434
.def("get_render_dims", &ps::GaussianParticles::getRenderDims)
3535
.def("set_extents", &ps::GaussianParticles::setExtents)
36+
.def("set_num_particles", &ps::GaussianParticles::setNumParticles)
3637
.def("update_object_space_bounds", &ps::GaussianParticles::updateObjectSpaceBounds)
3738

3839
;

src/cpp/gaussian_particles_structure.cpp

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,24 @@ const std::string GaussianParticles::structureTypeName = "Gaussian Particles";
2121
GaussianParticles::GaussianParticles(std::string name_, std::function<void()>& drawCallback_,
2222
std::function<void()>& extentsCallback_, std::function<void()>& deletionCallback_)
2323
: Structure(name_, structureTypeName), drawCallback(drawCallback_), extentsCallback(extentsCallback_),
24-
deletionCallback(deletionCallback_) {
24+
deletionCallback(deletionCallback_), subsampleFactor(uniquePrefix() + "subsampleFactor", 1) {
2525

26-
// note: unlike other structures this does not call updateObjectSpaceBounds() here, to avoid a circular problem with
27-
// the external class. we call it manually right after creation there.
26+
// Note: unlike other structures this does not call updateObjectSpaceBounds() here, to avoid a circular problem with
27+
// the external class. We call it manually right after creation there.
2828
}
2929

3030
GaussianParticles::~GaussianParticles() { deletionCallback(); }
3131

3232
void GaussianParticles::buildCustomUI() {
3333
ensureImagebuffersAllocated(); // doing this here ensures we re-render after resizing
3434

35-
ImGui::Text("# particles: -1");
35+
ImGui::Text("%d Gaussians", numParticles);
36+
37+
ImGui::PushItemWidth(100);
38+
if (ImGui::InputInt("render subsample", &(subsampleFactor.get()), 1, 10)) {
39+
setSubsampleFactor(subsampleFactor.get());
40+
}
41+
ImGui::PopItemWidth();
3642
}
3743
void GaussianParticles::buildCustomOptionsUI() {}
3844
void GaussianParticles::buildPickUI(const PickResult& result) {}
@@ -45,7 +51,10 @@ void GaussianParticles::drawDelayed() {
4551

4652
ensureImagebuffersAllocated();
4753

48-
drawCallback();
54+
if (!internal::renderPassIsRedraw) {
55+
// if doing multiple passes from the same view, no need to do this multiple times
56+
drawCallback();
57+
}
4958

5059
if (!imageToScreenProgram) {
5160
prepareImageToScreenProgram();
@@ -58,13 +67,23 @@ void GaussianParticles::drawPick() {}
5867
void GaussianParticles::drawPickDelayed() {}
5968
void GaussianParticles::updateObjectSpaceBounds() { extentsCallback(); }
6069

70+
void GaussianParticles::setSubsampleFactor(int32_t newVal) {
71+
newVal = std::max(1, newVal);
72+
subsampleFactor = newVal;
73+
ensureImagebuffersAllocated();
74+
}
75+
76+
int32_t GaussianParticles::getSubsampleFactor() { return subsampleFactor.get(); }
77+
6178
void GaussianParticles::setExtents(glm::vec3 bbox_min, glm::vec3 bbox_max) {
6279
std::get<0>(objectSpaceBoundingBox) = bbox_min;
6380
std::get<1>(objectSpaceBoundingBox) = bbox_max;
6481
objectSpaceLengthScale = glm::length(bbox_max - bbox_min);
6582
requestRedraw();
6683
}
6784

85+
void GaussianParticles::setNumParticles(int32_t numParticles_) { numParticles = numParticles_; }
86+
6887
std::string GaussianParticles::typeName() { return structureTypeName; }
6988
void GaussianParticles::refresh() {}
7089

@@ -74,8 +93,8 @@ std::tuple<int32_t, int32_t> GaussianParticles::getRenderDims() {
7493
}
7594

7695
void GaussianParticles::ensureImagebuffersAllocated() {
77-
int32_t newImageWidth = view::bufferWidth / subsampleFactor;
78-
int32_t newImageHeight = view::bufferHeight / subsampleFactor;
96+
int32_t newImageWidth = view::bufferWidth / subsampleFactor.get();
97+
int32_t newImageHeight = view::bufferHeight / subsampleFactor.get();
7998

8099
if (newImageHeight == currImageHeight && newImageWidth == currImageWidth) {
81100
return;
@@ -100,6 +119,12 @@ void GaussianParticles::ensureImagebuffersAllocated() {
100119
colors->data = std::vector<glm::vec4>(currImageWidth * currImageHeight, glm::vec4(0.0f));
101120
colors->markHostBufferUpdated();
102121

122+
if (imageToScreenProgram) {
123+
imageToScreenProgram->setTextureFromBuffer("t_depth", depths->getRenderTextureBuffer().get());
124+
imageToScreenProgram->setTextureFromBuffer("t_color", colors->getRenderTextureBuffer().get());
125+
}
126+
127+
103128
requestRedraw();
104129
}
105130

src/cpp/gaussian_particles_structure.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ class GaussianParticles : public Structure {
6161
// Manually set the extents of the structure (note: does _not_ automatically update the scene, call refresh() after if
6262
// you need that.)
6363
void setExtents(glm::vec3 bbox_min, glm::vec3 bbox_max);
64+
void setNumParticles(int32_t numParticles);
6465

6566

6667
private:
@@ -70,7 +71,10 @@ class GaussianParticles : public Structure {
7071

7172
int32_t currImageWidth = -1;
7273
int32_t currImageHeight = -1;
73-
int32_t subsampleFactor = 1;
74+
int32_t currSubsampleFactor = -1;
75+
int32_t numParticles = -1;
76+
77+
PersistentValue<int32_t> subsampleFactor;
7478

7579
// === Render data
7680
std::vector<float> depthsData;

src/polyscope/gaussian_particles.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ def structure_extents_callback(self):
9393
max_bound = np.percentile(centers, 75, axis=0)
9494

9595
self.bound_instance.set_extents(glm3(min_bound), glm3(max_bound))
96+
self.bound_instance.set_num_particles(centers.shape[0])
9697

9798
def structure_deletion_callback(self):
9899
"""
@@ -106,9 +107,8 @@ def n_particles(self) -> int:
106107
return self.bound_instance.n_particles()
107108

108109
def draw(self):
109-
import gsplat, torch
110-
111-
# print("drawing gaussian particles!")
110+
import torch
111+
import gsplat
112112

113113
color_buffer = self.get_buffer("colors")
114114
depth_buffer = self.get_buffer("depths")
@@ -118,6 +118,7 @@ def draw(self):
118118

119119
with torch.no_grad():
120120

121+
# prep camera matrices for the current Polyscope view
121122
render_w, render_h = self.bound_instance.get_render_dims()
122123
view_params = get_view_camera_parameters()
123124
T_camera_convent = np.array([
@@ -126,7 +127,6 @@ def draw(self):
126127
[0., 0., -1., 0.],
127128
[0., 0., 0., 1.],
128129
], dtype=np.float32)
129-
130130
view_mat = torch.tensor(T_camera_convent @ view_params.get_view_mat(), device=self.device)
131131
fov_height = np.deg2rad(view_params.get_fov_vertical_deg())
132132
fov_width = 2.0 * np.arctan(np.tan(fov_height / 2.0) * view_params.get_aspect())
@@ -145,7 +145,6 @@ def draw(self):
145145
width=render_w,
146146
height=render_h,
147147
render_mode="RGB+ED",
148-
sh_degree=0
149148
)
150149

151150
# unbatchify

test/scripts/gaussians_demo.py

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,7 @@
2121
import argparse
2222
import numpy as np
2323
from plyfile import PlyData
24-
from arrgh import arrgh
2524

26-
'''
27-
Download the mipnerf360 dataset:
28-
29-
mkdir -p data/mipnerf360
30-
cd data/mipnerf360
31-
wget http://storage.googleapis.com/gresearch/refraw360/360_v2.zip
32-
unzip 360_v2.zip
33-
'''
3425

3526
def load_gaussians_from_ply(path_ply, device='cuda'):
3627

@@ -91,33 +82,28 @@ def main():
9182
args = parser.parse_args()
9283

9384

94-
ps.init()
95-
ps.set_ground_plane_mode("shadow_only")
85+
ps.init()
86+
ps.set_ground_plane_mode("none")
9687

97-
def callback():
98-
pass
99-
ps.set_user_callback(callback)
100-
101-
10288
# Load the file
10389
centers, features_dc, opacity, scaling, rotation = load_gaussians_from_ply(args.gaussian_ply)
10490
print(f"Loaded {centers.shape[0]} gaussian particles")
10591

106-
107-
arrgh(centers, features_dc, opacity, scaling, rotation)
108-
109-
ps.register_gaussian_particles("gaussians",
110-
means=centers.unsqueeze(0),
111-
colors=features_dc.unsqueeze(0),
112-
opacities=opacity.unsqueeze(0),
113-
scales=scaling.unsqueeze(0),
114-
quats=rotation.unsqueeze(0)
92+
# Register Gaussians
93+
ps.register_gaussian_particles("gaussians",
94+
# the arguments below are passed directly
95+
# to gsplat.rasterization(...). See the docs there for the meaning
96+
# and other parameters you can pass.
97+
means=centers.unsqueeze(0),
98+
colors=features_dc.unsqueeze(0),
99+
opacities=opacity.unsqueeze(0),
100+
scales=scaling.unsqueeze(0),
101+
quats=rotation.unsqueeze(0),
102+
sh_degree=0,
115103
)
116104

117105
ps.show()
118106

119-
# ps.remove_gaussian_particles("gaussians")
120-
121107

122108
if __name__ == '__main__':
123109
main()

0 commit comments

Comments
 (0)