/** Copyright (c) 2022 NVIDIA CORPORATION. All rights reserved. * NVIDIA CORPORATION and its licensors retain all intellectual property * and proprietary rights in and to this software, related documentation * and any modifications thereto. Any use, reproduction, disclosure or * distribution of this software and related documentation without an express * license agreement from NVIDIA CORPORATION is strictly prohibited. */ #include "mesh.h" #include "bvh.h" #include "warp.h" #include "cuda_util.h" using namespace wp; #include namespace { // host-side copy of mesh descriptors, maps GPU mesh address (id) to a CPU desc std::map g_mesh_descriptors; } // anonymous namespace namespace wp { bool mesh_get_descriptor(uint64_t id, Mesh& mesh) { const auto& iter = g_mesh_descriptors.find(id); if (iter == g_mesh_descriptors.end()) return false; else mesh = iter->second; return true; } void mesh_add_descriptor(uint64_t id, const Mesh& mesh) { g_mesh_descriptors[id] = mesh; } void mesh_rem_descriptor(uint64_t id) { g_mesh_descriptors.erase(id); } } // namespace wp void bvh_refit_with_solid_angle_recursive_host(BVH& bvh, int index, Mesh& mesh) { BVHPackedNodeHalf& lower = bvh.node_lowers[index]; BVHPackedNodeHalf& upper = bvh.node_uppers[index]; if (lower.b) { // Leaf, compute properties const int leaf_index = lower.i; precompute_triangle_solid_angle_props(mesh.points[mesh.indices[leaf_index*3+0]], mesh.points[mesh.indices[leaf_index*3+1]], mesh.points[mesh.indices[leaf_index*3+2]], mesh.solid_angle_props[index]); (vec3&)lower = mesh.solid_angle_props[index].box.lower; (vec3&)upper = mesh.solid_angle_props[index].box.upper; } else { int left_index = lower.i; int right_index = upper.i; bvh_refit_with_solid_angle_recursive_host(bvh, left_index, mesh); bvh_refit_with_solid_angle_recursive_host(bvh, right_index, mesh); // combine SolidAngleProps* left_child_data = &mesh.solid_angle_props[left_index]; SolidAngleProps* right_child_data = (left_index != right_index) ? &mesh.solid_angle_props[right_index] : NULL; combine_precomputed_solid_angle_props(mesh.solid_angle_props[index], left_child_data, right_child_data); // compute union of children const vec3& left_lower = (vec3&)bvh.node_lowers[left_index]; const vec3& left_upper = (vec3&)bvh.node_uppers[left_index]; const vec3& right_lower = (vec3&)bvh.node_lowers[right_index]; const vec3& right_upper = (vec3&)bvh.node_uppers[right_index]; // union of child bounds vec3 new_lower = min(left_lower, right_lower); vec3 new_upper = max(left_upper, right_upper); // write new BVH nodes (vec3&)lower = new_lower; (vec3&)upper = new_upper; } } void bvh_refit_with_solid_angle_host(BVH& bvh, Mesh& mesh) { bvh_refit_with_solid_angle_recursive_host(bvh, 0, mesh); } uint64_t mesh_create_host(array_t points, array_t velocities, array_t indices, int num_points, int num_tris, int support_winding_number) { Mesh* m = new Mesh(points, velocities, indices, num_points, num_tris); m->lowers = new vec3[num_tris]; m->uppers = new vec3[num_tris]; float sum = 0.0; for (int i=0; i < num_tris; ++i) { wp::vec3& p0 = points[indices[i*3+0]]; wp::vec3& p1 = points[indices[i*3+1]]; wp::vec3& p2 = points[indices[i*3+2]]; // compute triangle bounds bounds3 b; b.add_point(p0); b.add_point(p1); b.add_point(p2); m->lowers[i] = b.lower; m->uppers[i] = b.upper; // compute edge lengths sum += length(p0-p1) + length(p0-p2) + length(p2-p1); } m->average_edge_length = sum / (num_tris*3); m->bvh = *(wp::BVH*)bvh_create_host(m->lowers, m->uppers, num_tris); if (support_winding_number) { // Let's first compute the sold int num_bvh_nodes = 2*num_tris-1; m->solid_angle_props = new SolidAngleProps[num_bvh_nodes]; bvh_refit_with_solid_angle_host(m->bvh, *m); } return (uint64_t)m; } void mesh_destroy_host(uint64_t id) { Mesh* m = (Mesh*)(id); delete[] m->lowers; delete[] m->uppers; if (m->solid_angle_props) { delete [] m->solid_angle_props; } bvh_destroy_host(m->bvh); delete m; } void mesh_refit_host(uint64_t id) { Mesh* m = (Mesh*)(id); float sum = 0.0; for (int i=0; i < m->num_tris; ++i) { wp::vec3 p0 = m->points.data[m->indices.data[i*3+0]]; wp::vec3 p1 = m->points.data[m->indices.data[i*3+1]]; wp::vec3 p2 = m->points.data[m->indices.data[i*3+2]]; // compute triangle bounds bounds3 b; b.add_point(p0); b.add_point(p1); b.add_point(p2); m->lowers[i] = b.lower; m->uppers[i] = b.upper; sum += length(p0-p1) + length(p0-p2) + length(p2-p1); } m->average_edge_length = sum / (m->num_tris*3); if (m->solid_angle_props) { // If solid angle were used, use refit solid angle bvh_refit_with_solid_angle_host(m->bvh, *m); } else { bvh_refit_host(m->bvh); } } // stubs for non-CUDA platforms #if !WP_ENABLE_CUDA WP_API uint64_t mesh_create_device(void* context, wp::array_t points, wp::array_t velocities, wp::array_t tris, int num_points, int num_tris, int support_winding_number) { return 0; } WP_API void mesh_destroy_device(uint64_t id) {} WP_API void mesh_refit_device(uint64_t id) {} #endif // !WP_ENABLE_CUDA