jkulhanek / tetra-nerf

Official implementation for Tetra-NeRF paper - NeRF represented as triangulation of input point cloud.
https://jkulhanek.com/tetra-nerf
MIT License
278 stars 14 forks source link

Question about barycentric coordinates #30

Closed lizhiqi49 closed 2 months ago

lizhiqi49 commented 2 months ago

Hi, thanks for your nice work!

I'm running your code according to your instructions. I find that the barycentric coords are of dimension 3 rather than 4 in the output of TetrahedraTracer.find_visited_cells(). And I notice that those barycentric coordinates were of dimension 4 in your previous versions, as mentioned by #16 .

I'm confused about this change. Could you please explain it for me? Sorry for bothering you and thanks for your time in advance!

jkulhanek commented 2 months ago

Hi, it was removed as it isn't needed. The last coord is just 1-sum of other coords (or the first one, I don't remember which one it was, but I think the last one).

lizhiqi49 commented 2 months ago

Hi, I found the cuda code for barycentric interpolation as below:

template <uint32_t interpolation_dim>
__global__ void interpolate_values_kernel(const uint32_t num_vertices,
                                          const uint32_t num_values,
                                          const uint32_t field_dim,
                                          const uint32_t *vertex_indices,
                                          const float *barycentric_coordinates,
                                          const float *field,
                                          float *result) {
    constexpr unsigned int empty = ~((unsigned int)0u);
    unsigned int i = blockIdx.x * blockDim.x + threadIdx.x;
    if (i >= num_values) return;
    unsigned int j = blockIdx.y * blockDim.y + threadIdx.y;

    float out = 0;
    float weight = 0;
#pragma unroll
    for (uint32_t k = 0; k < interpolation_dim - 1; ++k) {
        const float &w = barycentric_coordinates[i * (interpolation_dim - 1) + k];
        const auto &vi = vertex_indices[i * interpolation_dim + k + 1];
        if (vi != empty)
            out += w * field[j * num_vertices + vi];
        weight += w;
    }
    if (vertex_indices[i * interpolation_dim] != empty)
        out += (1.0f - weight) * field[j * num_vertices + vertex_indices[i * interpolation_dim]];
    result[j * num_values + i] = out;
}

It seems that the one missing barycentric coord is corresponding to the first vertex in the 4-dim vertex_indices. But I'm not sure since I'm not skillful on C++ and CUDA programming. Could you have a look on this?

jkulhanek commented 2 months ago

Yes, you are correct, sorry for the confusion! So in order to get full barycentrics, just do torch.cat((b.sum(-1, keepdim=True).mul(-1).add(1), b), -1) or something like this.

lizhiqi49 commented 2 months ago

I got it! Thanks for your nice reply!