Skip to content

Refactor NSS and DNSS implementations for improved readability and modularity#1

Closed
eclipse0922 wants to merge 1 commit intomasterfrom
refactor_2
Closed

Refactor NSS and DNSS implementations for improved readability and modularity#1
eclipse0922 wants to merge 1 commit intomasterfrom
refactor_2

Conversation

@eclipse0922
Copy link
Owner

  • Rewrote legacy code into clean C++17 style.
  • Added missing method implementations and input validation.
  • Introduced options struct for configurable parameters in NSS and DNSS.
  • Implemented CUDA support for DNSS rotational feature computation.
  • Added new CMake configuration for building with or without CUDA.
  • Updated README to reflect changes and provide build instructions.
  • Added .gitignore to exclude build directories.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b5a099582a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +502 to +505
const int t_bucket = point_to_t_bucket[static_cast<std::size_t>(point_index)];
const int r_bucket = point_to_r_bucket[static_cast<std::size_t>(point_index)];
t_constraints[static_cast<std::size_t>(t_bucket)] += 1.0f;
r_constraints[static_cast<std::size_t>(r_bucket)] += rotational_returns[static_cast<std::size_t>(point_index)];

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Only update constraints for the selected bucket type

The refactor now increments both translational and rotational constraints whenever any point is selected. In the original DNSS logic, only the constraint for the bucket type that was actually selected was incremented. With the new behavior, selecting from a rotational bucket also penalizes its translational bucket (and vice versa), which changes the bucket ordering and can under-sample translation buckets whenever rotational selections dominate. This alters the DNSS sampling distribution relative to the intended algorithm.

Useful? React with 👍 / 👎.

…dularity

- Rewrote legacy code into clean C++17 style.
- Added missing method implementations and input validation.
- Introduced options struct for configurable parameters in NSS and DNSS.
- Implemented CUDA support for DNSS rotational feature computation.
- Added new CMake configuration for building with or without CUDA.
- Updated README to reflect changes and provide build instructions.
- Added .gitignore to exclude build directories.
Repository owner deleted a comment from github-actions bot Feb 8, 2026
Repository owner deleted a comment from github-actions bot Feb 8, 2026
Repository owner deleted a comment from github-actions bot Feb 8, 2026
Repository owner deleted a comment from github-actions bot Feb 8, 2026
@github-actions
Copy link

github-actions bot commented Feb 8, 2026

PR Reviewer Guide 🔍

(Review updated until commit 2d4f452)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Missing Input Validation

The DNSSComputeRotationalFeaturesCuda function validates input pointers and size consistency, but the CPU fallback path in dualNormalSpaceSampling does not perform the same validation before calling crossProduct and computeRotationalReturnValue. This could lead to undefined behavior if invalid inputs are passed.

if (!cuda_used)
{
	for (std::size_t i = 0; i < normalized_vertices.size(); ++i)
	{
		rotational_normals[i] = crossProduct(normalized_vertices[i], m_normals_original[i]);
		rotational_returns[i] = computeRotationalReturnValue(
			normalized_vertices[i],
			m_normals_original[i],
			m_options.theta_for_return_radians);
	}
}
CUDA Error Handling

The CUDA implementation uses isfinite and isfinitef inconsistently. In the CPU code (computeRotationalReturnValue), std::isfinite is used, but in the CUDA kernel, isfinite is used without the std:: prefix. This may cause portability issues or compilation errors depending on the CUDA version and compiler flags.

const float point_norm = sqrtf(px * px + py * py + pz * pz);
if (!(isfinite(point_norm)) || point_norm <= kEpsilon)
{
	rotational_returns[index] = 0.0f;
	return;
}

float normal_norm = sqrtf(nx * nx + ny * ny + nz * nz);
if (!(isfinite(normal_norm)) || normal_norm <= kEpsilon)
{
	normal_norm = 1.0f;
}

const float pdx = px / point_norm;
const float pdy = py / point_norm;
const float pdz = pz / point_norm;
const float ndx = nx / normal_norm;
const float ndy = ny / normal_norm;
const float ndz = nz / normal_norm;

const float dot_pn = clampFloat(pdx * ndx + pdy * ndy + pdz * ndz, -1.0f, 1.0f);
const float beta = acosf(dot_pn);
const float pp = 2.0f * point_norm * sinf(theta * 0.5f);
const float sin_beta = sinf(beta);
const float cos_beta = cosf(beta);

const float pq_positive = pp * cosf(beta - theta * 0.5f);
const float pq_negative = pp * cosf(-beta - theta * 0.5f);

const float denominator_positive = fmaxf(kEpsilon, point_norm - pq_positive * cos_beta);
const float denominator_negative = fmaxf(kEpsilon, point_norm - pq_negative * cos_beta);

const float atan_positive = atanf((pq_positive * sin_beta) / denominator_positive);
const float atan_negative = atanf((pq_negative * (-sin_beta)) / denominator_negative);

const float gamma_positive = theta - atan_positive;
const float gamma_negative = theta - atan_negative;

const float rr_positive = point_norm * gamma_positive / theta;
const float rr_negative = point_norm * gamma_negative / theta;

const float rr = fmaxf(rr_positive, rr_negative);
if (!isfinite(rr) || rr < 0.0f)
Memory Leak Risk

In DNSSComputeRotationalFeaturesCuda, if cudaMemcpy from device to host fails after successful host-to-device copies, the function frees all allocated memory but returns false without ensuring the output vectors are cleared. This could leave the caller with partially populated vectors or inconsistent state.

if (!isCudaSuccess(cudaMemcpy(rot_normals_flat.data(), d_rot_normals, vector_bytes, cudaMemcpyDeviceToHost)) ||
	!isCudaSuccess(cudaMemcpy(rot_returns_flat.data(), d_rot_returns, return_bytes, cudaMemcpyDeviceToHost)))
{
	cudaFree(d_vertices);
	cudaFree(d_normals);
	cudaFree(d_rot_normals);
	cudaFree(d_rot_returns);
	return false;
}

@github-actions
Copy link

github-actions bot commented Feb 8, 2026

Persistent review updated to latest commit b70e666

@github-actions
Copy link

github-actions bot commented Feb 8, 2026

Persistent review updated to latest commit 2d4f452

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant