/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation * * SPDX-License-Identifier: Apache-2.0 */ #include "bvh/bvh.h" #include "device/device.h" #include "scene/attribute.h" #include "scene/camera.h" #include "scene/geometry.h" #include "scene/hair.h" #include "scene/light.h" #include "scene/mesh.h" #include "scene/object.h" #include "scene/osl.h" #include "scene/pointcloud.h" #include "scene/scene.h" #include "scene/shader.h" #include "scene/shader_nodes.h" #include "subd/patch_table.h" #include "subd/split.h" #include "util/progress.h" CCL_NAMESPACE_BEGIN void GeometryManager::device_update_mesh(Device * /*unused*/, DeviceScene *dscene, Scene *scene, Progress &progress) { /* Count. */ size_t vert_size = 0; size_t tri_size = 0; size_t curve_key_size = 0; size_t curve_size = 0; size_t curve_segment_size = 0; size_t point_size = 0; size_t patch_size = 0; for (Geometry *geom : scene->geometry) { if (geom->is_mesh() || geom->is_volume()) { Mesh *mesh = static_cast(geom); vert_size += mesh->verts.size(); tri_size += mesh->num_triangles(); if (mesh->get_num_subd_faces()) { Mesh::SubdFace last = mesh->get_subd_face(mesh->get_num_subd_faces() - 1); patch_size += (last.ptex_offset + last.num_ptex_faces()) * 8; /* patch tables are stored in same array so include them in patch_size */ if (mesh->patch_table) { mesh->patch_table_offset = patch_size; patch_size += mesh->patch_table->total_size(); } } } else if (geom->is_hair()) { Hair *hair = static_cast(geom); curve_key_size += hair->get_curve_keys().size(); curve_size += hair->num_curves(); curve_segment_size += hair->num_segments(); } else if (geom->is_pointcloud()) { PointCloud *pointcloud = static_cast(geom); point_size += pointcloud->num_points(); } } /* Fill in all the arrays. */ if (tri_size != 0) { /* normals */ progress.set_status("Updating Mesh", "Computing normals"); packed_float3 *tri_verts = dscene->tri_verts.alloc(vert_size); uint *tri_shader = dscene->tri_shader.alloc(tri_size); packed_float3 *vnormal = dscene->tri_vnormal.alloc(vert_size); packed_uint3 *tri_vindex = dscene->tri_vindex.alloc(tri_size); uint *tri_patch = dscene->tri_patch.alloc(tri_size); float2 *tri_patch_uv = dscene->tri_patch_uv.alloc(vert_size); const bool copy_all_data = dscene->tri_shader.need_realloc() || dscene->tri_vindex.need_realloc() || dscene->tri_vnormal.need_realloc() || dscene->tri_patch.need_realloc() || dscene->tri_patch_uv.need_realloc(); for (Geometry *geom : scene->geometry) { if (geom->is_mesh() || geom->is_volume()) { Mesh *mesh = static_cast(geom); if (mesh->shader_is_modified() || mesh->smooth_is_modified() || mesh->triangles_is_modified() || copy_all_data) { mesh->pack_shaders(scene, &tri_shader[mesh->prim_offset]); } if (mesh->verts_is_modified() || copy_all_data) { mesh->pack_normals(&vnormal[mesh->vert_offset]); } if (mesh->verts_is_modified() || mesh->triangles_is_modified() || mesh->vert_patch_uv_is_modified() || copy_all_data) { mesh->pack_verts(&tri_verts[mesh->vert_offset], &tri_vindex[mesh->prim_offset], &tri_patch[mesh->prim_offset], &tri_patch_uv[mesh->vert_offset]); } if (progress.get_cancel()) { return; } } } /* vertex coordinates */ progress.set_status("Updating Mesh", "Copying Mesh to device"); dscene->tri_verts.copy_to_device_if_modified(); dscene->tri_shader.copy_to_device_if_modified(); dscene->tri_vnormal.copy_to_device_if_modified(); dscene->tri_vindex.copy_to_device_if_modified(); dscene->tri_patch.copy_to_device_if_modified(); dscene->tri_patch_uv.copy_to_device_if_modified(); } if (curve_segment_size != 0) { progress.set_status("Updating Mesh", "Copying Curves to device"); float4 *curve_keys = dscene->curve_keys.alloc(curve_key_size); KernelCurve *curves = dscene->curves.alloc(curve_size); KernelCurveSegment *curve_segments = dscene->curve_segments.alloc(curve_segment_size); const bool copy_all_data = dscene->curve_keys.need_realloc() || dscene->curves.need_realloc() || dscene->curve_segments.need_realloc(); for (Geometry *geom : scene->geometry) { if (geom->is_hair()) { Hair *hair = static_cast(geom); bool curve_keys_co_modified = hair->curve_radius_is_modified() || hair->curve_keys_is_modified(); bool curve_data_modified = hair->curve_shader_is_modified() || hair->curve_first_key_is_modified(); if (!curve_keys_co_modified && !curve_data_modified && !copy_all_data) { continue; } hair->pack_curves(scene, &curve_keys[hair->curve_key_offset], &curves[hair->prim_offset], &curve_segments[hair->curve_segment_offset]); if (progress.get_cancel()) { return; } } } dscene->curve_keys.copy_to_device_if_modified(); dscene->curves.copy_to_device_if_modified(); dscene->curve_segments.copy_to_device_if_modified(); } if (point_size != 0) { progress.set_status("Updating Mesh", "Copying Point clouds to device"); float4 *points = dscene->points.alloc(point_size); uint *points_shader = dscene->points_shader.alloc(point_size); for (Geometry *geom : scene->geometry) { if (geom->is_pointcloud()) { PointCloud *pointcloud = static_cast(geom); pointcloud->pack( scene, &points[pointcloud->prim_offset], &points_shader[pointcloud->prim_offset]); if (progress.get_cancel()) { return; } } } dscene->points.copy_to_device(); dscene->points_shader.copy_to_device(); } if (patch_size != 0 && dscene->patches.need_realloc()) { progress.set_status("Updating Mesh", "Copying Patches to device"); uint *patch_data = dscene->patches.alloc(patch_size); for (Geometry *geom : scene->geometry) { if (geom->is_mesh()) { Mesh *mesh = static_cast(geom); mesh->pack_patches(&patch_data[mesh->patch_offset]); if (mesh->patch_table) { mesh->patch_table->copy_adjusting_offsets(&patch_data[mesh->patch_table_offset], mesh->patch_table_offset); } if (progress.get_cancel()) { return; } } } dscene->patches.copy_to_device(); } } CCL_NAMESPACE_END