Skip to content
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
aef98a6
Add GaussianProjectionUT for 3D to 2D Gaussian projection
fwilliams Jan 20, 2026
1938d8a
Add rotation matrix to quaternion conversion function
fwilliams Jan 20, 2026
f96a05d
Add pose interpolation functionality and related tests
fwilliams Jan 20, 2026
39a1cac
Remove unused Tensor.h include from GaussianProjectionUTTest.cpp
fwilliams Jan 20, 2026
a9baa6f
comments
fwilliams Jan 20, 2026
37a879d
why not more functions?
fwilliams Jan 20, 2026
3930fd4
checkpoint
fwilliams Jan 26, 2026
7a31ae3
checkpoint
fwilliams Jan 26, 2026
35ee440
enum
fwilliams Jan 27, 2026
6c00b10
rm enum
fwilliams Jan 27, 2026
1e262ad
clang format
fwilliams Jan 27, 2026
c5d4e00
clang format
fwilliams Jan 27, 2026
64904bf
clang format
fwilliams Jan 27, 2026
e78a670
format
fwilliams Jan 27, 2026
b022698
fix bug
fwilliams Jan 27, 2026
9936c0d
fix clang format
fwilliams Jan 27, 2026
61d1352
logscales
fwilliams Jan 27, 2026
b2cad81
address copilot comments
fwilliams Jan 27, 2026
4813306
clang format
fwilliams Jan 27, 2026
b40d20d
Update src/fvdb/detail/ops/gsplat/GaussianProjectionUT.h
fwilliams Jan 27, 2026
d6e8739
Update src/fvdb/detail/ops/gsplat/GaussianProjectionUT.h
fwilliams Jan 27, 2026
b1f981b
Update src/fvdb/detail/ops/gsplat/GaussianUtils.cuh
fwilliams Jan 27, 2026
c9bd1a2
rm
fwilliams Jan 27, 2026
ff11d66
fix copilot
fwilliams Jan 27, 2026
ec68cc5
clang format
fwilliams Jan 27, 2026
97828b1
rolling shutter issue
fwilliams Jan 27, 2026
c8a3bae
clang format
fwilliams Jan 27, 2026
1a236c0
remove (void)
fwilliams Jan 27, 2026
b5c981e
tests use accessors
fwilliams Jan 28, 2026
e77db1f
Update src/CMakeLists.txt
fwilliams Jan 28, 2026
c9a3b2b
fix segfault
fwilliams Jan 28, 2026
7eada65
Merge branch 'fw/ut2' of github.com:fwilliams/fvdb-core into fw/ut2
fwilliams Jan 28, 2026
9e8e1bf
fixed
fwilliams Jan 28, 2026
2fcf679
host side check for num sigma points
fwilliams Jan 28, 2026
c09877f
robustness
fwilliams Jan 28, 2026
7215540
no sync
fwilliams Jan 28, 2026
c79b88f
docstring
fwilliams Jan 29, 2026
ff5c7aa
move a lot of code into a camera model
fwilliams Jan 29, 2026
e44bd79
opencv camera model
fwilliams Jan 29, 2026
f7e5498
clean up pose stuff
fwilliams Jan 29, 2026
f3eb963
refactor
fwilliams Jan 29, 2026
d49655b
refactor
fwilliams Jan 29, 2026
6856d68
rename
fwilliams Jan 29, 2026
bb44edc
cleanup
fwilliams Jan 29, 2026
84050f6
more refactoring
fwilliams Jan 29, 2026
f8359b7
revert accessor helper changes
fwilliams Jan 29, 2026
ba96359
camera model
fwilliams Jan 30, 2026
7e85a0e
orthographic
fwilliams Jan 30, 2026
5c15eee
comments
fwilliams Jan 30, 2026
c325096
docstrings
fwilliams Jan 30, 2026
f8f65ce
accessorhelpers
fwilliams Jan 30, 2026
30d5a5c
fix UB
fwilliams Jan 30, 2026
352ee00
format
fwilliams Jan 30, 2026
44d3864
cache R
fwilliams Jan 30, 2026
b2a3465
fix copilot comments
fwilliams Jan 30, 2026
0862255
std exp
fwilliams Jan 30, 2026
6a8afb0
fix
fwilliams Jan 30, 2026
2678db1
Enhance documentation for rotationMatrixToQuaternion function with de…
fwilliams Jan 30, 2026
ec6fb21
clang format
fwilliams Feb 2, 2026
d211647
remove raw pointers where applicable
fwilliams Feb 3, 2026
1715910
format
fwilliams Feb 3, 2026
fb51967
fix copilot issue
fwilliams Feb 3, 2026
c68e34d
clang format
fwilliams Feb 3, 2026
5bdcbd3
rerun CI
fwilliams Feb 4, 2026
2b2acae
rerun CI?
fwilliams Feb 4, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ set(FVDB_CU_FILES
fvdb/detail/ops/gsplat/GaussianMCMCRelocation.cu
fvdb/detail/ops/gsplat/GaussianProjectionBackward.cu
fvdb/detail/ops/gsplat/GaussianProjectionForward.cu
fvdb/detail/ops/gsplat/GaussianProjectionUT.cu
fvdb/detail/ops/gsplat/GaussianProjectionJaggedBackward.cu
fvdb/detail/ops/gsplat/GaussianProjectionJaggedForward.cu
fvdb/detail/ops/gsplat/GaussianRasterizeBackward.cu
Expand Down Expand Up @@ -171,7 +172,7 @@ set_target_properties(
CXX_STANDARD 20
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS ON
CUDA_STANDARD 20
CUDA_STANDARD 20
CUDA_STANDARD_REQUIRED ON
POSITION_INDEPENDENT_CODE ON
INTERFACE_POSITION_INDEPENDENT_CODE ON)
Expand Down
6 changes: 3 additions & 3 deletions src/fvdb/detail/GridBatchImpl.cu
Original file line number Diff line number Diff line change
Expand Up @@ -1307,7 +1307,7 @@ GridBatchImpl::deserializeV0(const torch::Tensor &serialized) {
};

TORCH_CHECK(serialized.scalar_type() == torch::kInt8, "Serialized data must be of type int8");
TORCH_CHECK(serialized.numel() >= sizeof(V01Header),
TORCH_CHECK(serialized.numel() >= static_cast<int64_t>(sizeof(V01Header)),
"Serialized data is too small to be a valid grid handle");

const int8_t *serializedPtr = serialized.data_ptr<int8_t>();
Expand All @@ -1316,7 +1316,7 @@ GridBatchImpl::deserializeV0(const torch::Tensor &serialized) {
TORCH_CHECK(header->magic == 0x0F0F0F0F0F0F0F0F,
"Serialized data is not a valid grid handle. Bad magic.");
TORCH_CHECK(header->version == 0, "Serialized data is not a valid grid handle. Bad version.");
TORCH_CHECK(serialized.numel() == header->totalBytes,
TORCH_CHECK(static_cast<uint64_t>(serialized.numel()) == header->totalBytes,
"Serialized data is not a valid grid handle. Bad total bytes.");

const uint64_t numGrids = header->numGrids;
Expand Down Expand Up @@ -1752,7 +1752,7 @@ GridBatchImpl::dilate(const int64_t dilationAmount) {
c10::intrusive_ptr<GridBatchImpl>
GridBatchImpl::dilate(const std::vector<int64_t> dilationAmount) {
c10::DeviceGuard guard(device());
TORCH_CHECK_VALUE(dilationAmount.size() == batchSize(),
TORCH_CHECK_VALUE(static_cast<int64_t>(dilationAmount.size()) == batchSize(),
"dilationAmount should have same size as batch size, got ",
dilationAmount.size(),
" != ",
Expand Down
10 changes: 1 addition & 9 deletions src/fvdb/detail/ops/gsplat/GaussianProjectionForward.cu
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,7 @@ template <typename T, bool Ortho> struct ProjectionForward {
mOutDepthsAcc(outDepths.packed_accessor64<T, 2, torch::RestrictPtrTraits>()),
mOutConicsAcc(outConics.packed_accessor64<T, 3, torch::RestrictPtrTraits>()),
mOutCompensationsAcc(outCompensations.defined() ? outCompensations.data_ptr<T>()
: nullptr) {
mMeansAcc = means.packed_accessor64<T, 2, torch::RestrictPtrTraits>();
mQuatsAcc = quats.packed_accessor64<T, 2, torch::RestrictPtrTraits>();
mLogScalesAcc = logScales.packed_accessor64<T, 2, torch::RestrictPtrTraits>();
mWorldToCamMatricesAcc =
worldToCamMatrices.packed_accessor32<T, 3, torch::RestrictPtrTraits>();
mProjectionMatricesAcc =
projectionMatrices.packed_accessor32<T, 3, torch::RestrictPtrTraits>();
}
: nullptr) {}

inline __device__ Mat3
computeCovarianceMatrix(int64_t gid) const {
Expand Down
890 changes: 890 additions & 0 deletions src/fvdb/detail/ops/gsplat/GaussianProjectionUT.cu

Large diffs are not rendered by default.

121 changes: 121 additions & 0 deletions src/fvdb/detail/ops/gsplat/GaussianProjectionUT.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
// Copyright Contributors to the OpenVDB Project
// SPDX-License-Identifier: Apache-2.0
//
#ifndef FVDB_DETAIL_OPS_GSPLAT_GAUSSIANPROJECTIONUT_H
#define FVDB_DETAIL_OPS_GSPLAT_GAUSSIANPROJECTIONUT_H

#include <ATen/core/TensorBody.h>
#include <torch/types.h>

#include <tuple>

namespace fvdb {
namespace detail {
namespace ops {

enum class RollingShutterType { NONE = 0, VERTICAL = 1, HORIZONTAL = 2 };

// Distortion model for camera projection in the UT kernel.
//
// Distortion coefficients are supplied as a single tensor `distortionCoeffs` and interpreted
// according to this enum.
enum class DistortionModel : int32_t {
NONE = 0,

// OpenCV variants (all use the same [C,12] coefficient layout):
// [k1,k2,k3,k4,k5,k6,p1,p2,s1,s2,s3,s4]
//
// The enum exists mostly for clarity + runtime validation of coefficient usage.
OPENCV_RADTAN_5 = 1, // polynomial radial (k1,k2,k3) + tangential (p1,p2)
OPENCV_RATIONAL_8 = 2, // rational radial (k1..k6) + tangential (p1,p2)
OPENCV_RADTAN_THIN_PRISM_9 = 3, // polynomial radial + tangential + thin-prism (s1..s4)
OPENCV_THIN_PRISM_12 = 4, // rational radial + tangential + thin-prism (s1..s4)
};

struct UTParams {
float alpha = 0.1f; // Blending parameter for UT
float beta = 2.0f; // Scaling parameter for UT
float kappa = 0.0f; // Additional scaling parameter for UT
// For a 3D Unscented Transform with the standard \(2D+1\) formulation, D=3 => 7 points.
// This implementation currently supports only this 3D case.
int numSigmaPoints = 7;
float inImageMargin = 0.1f; // Margin for in-image check
bool requireAllSigmaPointsInImage =
true; // Require all sigma points to be in image to consider a Gaussian valid
};

/// @brief Project 3D Gaussians to 2D screen space pixel coordinates for rendering
///
/// This function transforms 3D Gaussians to 2D screen space by applying camera projections.
/// It computes the 2D means, depths, 2D covariance matrices (conics), and potentially compensation
/// factors to accurately represent the 3D Gaussians in 2D for later rasterization.
///
/// The origin of the 2D pixel coordinates is the top-left corner of the image, with positive x-axis
/// pointing to the right and positive y-axis pointing downwards.
///
/// @attention The output radii of 3D Gaussians that are discarded (due to clipping or projection
/// too small) are set to zero, but the other output values of discarded Gaussians are uninitialized
/// (undefined).
///
/// @tparam DeviceType Device type template parameter (torch::kCUDA or torch::kCPU)
///
/// @param[in] means 3D positions of Gaussians [N, 3] where N is number of Gaussians
/// @param[in] quats Quaternion rotations of Gaussians [N, 4] in format (w, x, y, z)
/// @param[in] logScales Log-scale factors of Gaussians [N, 3] (natural log), representing extent in
/// each dimension
/// @param[in] worldToCamMatricesStart Camera view matrices at the start of the frame. Shape [C, 4,
/// 4] where C is number of cameras
/// @param[in] worldToCamMatricesEnd Camera view matrices at the end of the frame. Shape [C, 4, 4]
/// where C is number of cameras
/// @param[in] projectionMatrices Camera intrinsic matrices [C, 3, 3]
/// @param[in] rollingShutterType Type of rolling shutter effect to apply
/// @param[in] utParams Unscented Transform parameters
/// @param[in] distortionModel Distortion model used to interpret `distortionCoeffs`.
/// @param[in] distortionCoeffs Distortion coefficients for each camera.
/// - DistortionModel::NONE: ignored (use [C,0] or [C,K] tensor).
/// - DistortionModel::OPENCV_*: expects [C,12] coefficients in the following order:
/// [k1,k2,k3,k4,k5,k6,p1,p2,s1,s2,s3,s4]
/// where k1..k6 are radial (rational), p1,p2 are tangential, and s1..s4 are thin-prism.
/// @param[in] imageWidth Width of the output image in pixels
/// @param[in] imageHeight Height of the output image in pixels
/// @param[in] eps2d 2D projection epsilon for numerical stability
/// @param[in] nearPlane Near clipping plane distance
/// @param[in] farPlane Far clipping plane distance
/// @param[in] minRadius2d Minimum 2D radius threshold; Gaussians with projected radius <= this
/// value are clipped/discarded
/// @param[in] calcCompensations Whether to calculate view-dependent compensation factors
/// @param[in] ortho Whether to use orthographic projection instead of perspective
///
/// @return std::tuple containing:
/// - Radii of 2D Gaussians [C, N]
/// - 2D projected Gaussian centers [C, N, 2]
/// - Depths of Gaussians [C, N]
/// - Covariance matrices in conic form [C, N, 3] representing (a, b, c) in ax² + 2bxy + cy²
/// - Compensation factors [C, N] (if calc_compensations is true, otherwise empty tensor)
template <torch::DeviceType>
std::tuple<torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor, torch::Tensor>
dispatchGaussianProjectionForwardUT(
const torch::Tensor &means, // [N, 3]
const torch::Tensor &quats, // [N, 4]
const torch::Tensor &logScales, // [N, 3]
const torch::Tensor &worldToCamMatricesStart, // [C, 4, 4]
const torch::Tensor &worldToCamMatricesEnd, // [C, 4, 4]
const torch::Tensor &projectionMatrices, // [C, 3, 3]
const RollingShutterType rollingShutterType,
const UTParams &utParams,
const DistortionModel distortionModel,
const torch::Tensor &distortionCoeffs, // [C, 12] for OPENCV_*, or [C, 0] for NONE
const int64_t imageWidth,
const int64_t imageHeight,
const float eps2d,
const float nearPlane,
const float farPlane,
const float minRadius2d,
const bool calcCompensations,
const bool ortho);

} // namespace ops
} // namespace detail
} // namespace fvdb

#endif // FVDB_DETAIL_OPS_GSPLAT_GAUSSIANPROJECTIONUT_H
Loading
Loading