Skip to content

Commit 55c4e59

Browse files
committed
geometry-io: Gaussian splat PointCloud model, PLY/SPLAT IO, geometric transforms
- t::PointCloud: IsGaussianSplat(), Rotate/Scale/Translate/Transform for GS attributes (positions, quaternion rotations, linear scales, DC/SH coefficients) - Ivanic-Ruedenberg SH rotation algorithm for f_rest attributes (degrees 1-3) - Point inversion parity handling for odd-degree SH blocks - PLY IO (legacy + tensor): read/write GS attributes (pos, rot, scale, opacity, f_dc, f_rest); exponentiate log-scales from PLY files at load time - SPLAT file IO: linear scales, packed quaternions, rgb8 DC color - FileFormatIO: register .splat extension - MaterialRecord: add GS-specific render flags (sh_degree, antialias, etc.) - Renderer/View: virtual interface additions for GS output queries
1 parent 4a9f584 commit 55c4e59

11 files changed

Lines changed: 547 additions & 190 deletions

File tree

cpp/open3d/io/FileFormatIO.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,18 @@ static std::map<std::string, FileGeometry (*)(const std::string&)> gExt2Func = {
2222
{"off", ReadFileGeometryTypeOFF},
2323
{"pcd", ReadFileGeometryTypePCD},
2424
{"ply", ReadFileGeometryTypePLY},
25+
{"splat", ReadFileGeometryTypeSPLAT},
2526
{"pts", ReadFileGeometryTypePTS},
2627
{"stl", ReadFileGeometryTypeSTL},
2728
{"xyz", ReadFileGeometryTypeXYZ},
2829
{"xyzn", ReadFileGeometryTypeXYZN},
2930
{"xyzrgb", ReadFileGeometryTypeXYZRGB},
3031
};
3132

33+
FileGeometry ReadFileGeometryTypeSPLAT(const std::string&) {
34+
return FileGeometry(CONTAINS_POINTS | CONTAINS_GAUSSIAN_SPLATS);
35+
}
36+
3237
FileGeometry ReadFileGeometryType(const std::string& path) {
3338
auto ext = utility::filesystem::GetFileExtensionInLowerCase(path);
3439
auto it = gExt2Func.find(ext);

cpp/open3d/io/FileFormatIO.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ enum FileGeometry {
1717
CONTAINS_POINTS = (1 << 0),
1818
CONTAINS_LINES = (1 << 1),
1919
CONTAINS_TRIANGLES = (1 << 2),
20+
CONTAINS_GAUSSIAN_SPLATS = (1 << 3),
2021
};
2122

2223
/// Returns the kind of geometry that the file contains. This is a quick
@@ -30,6 +31,7 @@ FileGeometry ReadFileGeometryTypeFBX(const std::string& path);
3031
FileGeometry ReadFileGeometryTypeOFF(const std::string& path);
3132
FileGeometry ReadFileGeometryTypePCD(const std::string& path);
3233
FileGeometry ReadFileGeometryTypePLY(const std::string& path);
34+
FileGeometry ReadFileGeometryTypeSPLAT(const std::string& path);
3335
FileGeometry ReadFileGeometryTypePTS(const std::string& path);
3436
FileGeometry ReadFileGeometryTypeSTL(const std::string& path);
3537
FileGeometry ReadFileGeometryTypeXYZ(const std::string& path);

cpp/open3d/io/file_format/FilePLY.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@
77

88
#include <rply.h>
99

10+
#include <algorithm>
11+
#include <cctype>
12+
#include <set>
13+
1014
#include "open3d/io/FileFormatIO.h"
1115
#include "open3d/io/LineSetIO.h"
1216
#include "open3d/io/PointCloudIO.h"
@@ -23,6 +27,67 @@ namespace io {
2327
/// @cond
2428
namespace {
2529

30+
std::string ToLowerString(std::string value) {
31+
std::transform(value.begin(), value.end(), value.begin(),
32+
[](unsigned char character) {
33+
return static_cast<char>(std::tolower(character));
34+
});
35+
return value;
36+
}
37+
38+
bool HasGaussianSplatProperties(p_ply ply_file) {
39+
std::set<std::string> vertex_property_names;
40+
41+
p_ply_element element = ply_get_next_element(ply_file, nullptr);
42+
while (element) {
43+
const char *element_name = nullptr;
44+
long element_size = 0;
45+
ply_get_element_info(element, &element_name, &element_size);
46+
if (element_name != nullptr &&
47+
ToLowerString(element_name) == "vertex" && element_size > 0) {
48+
p_ply_property property = ply_get_next_property(element, nullptr);
49+
while (property) {
50+
const char *property_name = nullptr;
51+
e_ply_type type;
52+
ply_get_property_info(property, &property_name, &type, NULL,
53+
NULL);
54+
if (property_name != nullptr) {
55+
vertex_property_names.insert(ToLowerString(property_name));
56+
}
57+
property = ply_get_next_property(element, property);
58+
}
59+
break;
60+
}
61+
element = ply_get_next_element(ply_file, element);
62+
}
63+
64+
const std::vector<std::string> required_properties = {"x", "y", "z",
65+
"opacity"};
66+
const bool has_required_properties =
67+
std::all_of(required_properties.begin(), required_properties.end(),
68+
[&vertex_property_names](const std::string &name) {
69+
return vertex_property_names.count(name) > 0;
70+
});
71+
const int scale_count = static_cast<int>(std::count_if(
72+
vertex_property_names.begin(), vertex_property_names.end(),
73+
[](const std::string &name) {
74+
return name.rfind("scale_", 0) == 0;
75+
}));
76+
const int rot_count = static_cast<int>(std::count_if(
77+
vertex_property_names.begin(), vertex_property_names.end(),
78+
[](const std::string &name) {
79+
return name.rfind("rot_", 0) == 0;
80+
}));
81+
const int f_dc_count = static_cast<int>(std::count_if(
82+
vertex_property_names.begin(), vertex_property_names.end(),
83+
[](const std::string &name) {
84+
return name.rfind("f_dc_", 0) == 0;
85+
}));
86+
87+
return has_required_properties && scale_count >= 3 && rot_count >= 4 &&
88+
f_dc_count >= 3;
89+
}
90+
2691
namespace ply_pointcloud_reader {
2792

2893
struct PLYReaderState {
@@ -361,6 +426,7 @@ FileGeometry ReadFileGeometryTypePLY(const std::string &path) {
361426
ply_close(ply_file);
362427
return CONTENTS_UNKNOWN;
363428
}
429+
const bool is_gaussian_splat = HasGaussianSplatProperties(ply_file);
364430

365431
auto nVertices =
366432
ply_set_read_cb(ply_file, "vertex", "x", nullptr, nullptr, 0);
@@ -382,6 +448,10 @@ FileGeometry ReadFileGeometryTypePLY(const std::string &path) {
382448
} else if (nVertices > 0) {
383449
contents |= CONTAINS_POINTS;
384450
}
451+
if (is_gaussian_splat) {
452+
contents |= CONTAINS_GAUSSIAN_SPLATS;
453+
contents |= CONTAINS_POINTS;
454+
}
385455
return FileGeometry(contents);
386456
}
387457

0 commit comments

Comments
 (0)