Commit: 35b1e9fc3acd6db565e7e54252a4a4152d8343d9 Author: Brecht Van Lommel Date: Wed Dec 1 17:30:46 2021 +0100 Branches: master https://developer.blender.org/rB35b1e9fc3acd6db565e7e54252a4a4152d8343d9
Cycles: pointcloud rendering This add support for rendering of the point cloud object in Blender, as a native geometry type in Cycles that is more memory and time efficient than instancing sphere meshes. This can be useful for rendering sand, water splashes, particles, motion graphics, etc. Points are currently always rendered as spheres, with backface culling. More shapes are likely to be added later, but this is the most important one and can be customized with shaders. For CPU rendering the Embree primitive is used, for GPU there is our own intersection code. Motion blur is suppored. Volumes inside points are not currently supported. Implemented with help from: * Kévin Dietrich: Alembic procedural integration * Patrick Mourse: OptiX integration * Josh Whelchel: update for cycles-x changes Ref T92573 Differential Revision: https://developer.blender.org/D9887 =================================================================== M intern/cycles/blender/CMakeLists.txt M intern/cycles/blender/addon/ui.py M intern/cycles/blender/geometry.cpp M intern/cycles/blender/object.cpp A intern/cycles/blender/pointcloud.cpp M intern/cycles/blender/sync.h M intern/cycles/bvh/build.cpp M intern/cycles/bvh/build.h M intern/cycles/bvh/bvh2.cpp M intern/cycles/bvh/embree.cpp M intern/cycles/bvh/embree.h M intern/cycles/bvh/params.h M intern/cycles/bvh/split.cpp M intern/cycles/bvh/split.h M intern/cycles/device/optix/device_impl.cpp M intern/cycles/device/optix/device_impl.h M intern/cycles/kernel/CMakeLists.txt M intern/cycles/kernel/bvh/bvh.h M intern/cycles/kernel/bvh/shadow_all.h M intern/cycles/kernel/bvh/traversal.h M intern/cycles/kernel/bvh/types.h M intern/cycles/kernel/bvh/util.h M intern/cycles/kernel/device/optix/kernel.cu M intern/cycles/kernel/geom/geom.h A intern/cycles/kernel/geom/motion_point.h A intern/cycles/kernel/geom/point.h A intern/cycles/kernel/geom/point_intersect.h M intern/cycles/kernel/geom/primitive.h M intern/cycles/kernel/geom/shader_data.h M intern/cycles/kernel/osl/services.cpp M intern/cycles/kernel/osl/services.h M intern/cycles/kernel/svm/wireframe.h M intern/cycles/kernel/textures.h M intern/cycles/kernel/types.h M intern/cycles/scene/CMakeLists.txt M intern/cycles/scene/alembic.cpp M intern/cycles/scene/alembic.h M intern/cycles/scene/alembic_read.cpp M intern/cycles/scene/alembic_read.h M intern/cycles/scene/attribute.cpp M intern/cycles/scene/geometry.cpp M intern/cycles/scene/geometry.h M intern/cycles/scene/object.cpp A intern/cycles/scene/pointcloud.cpp A intern/cycles/scene/pointcloud.h M intern/cycles/scene/scene.cpp M intern/cycles/scene/scene.h M tests/python/CMakeLists.txt =================================================================== diff --git a/intern/cycles/blender/CMakeLists.txt b/intern/cycles/blender/CMakeLists.txt index 1f05b1aa234..fe7d0b89bb0 100644 --- a/intern/cycles/blender/CMakeLists.txt +++ b/intern/cycles/blender/CMakeLists.txt @@ -40,6 +40,7 @@ set(SRC object_cull.cpp output_driver.cpp particles.cpp + pointcloud.cpp curves.cpp logging.cpp python.cpp diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index fd86d75a301..e4fbc898070 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -1020,7 +1020,7 @@ class CYCLES_OBJECT_PT_motion_blur(CyclesButtonsPanel, Panel): def poll(cls, context): ob = context.object if CyclesButtonsPanel.poll(context) and ob: - if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA'}: + if ob.type in {'MESH', 'CURVE', 'CURVE', 'SURFACE', 'FONT', 'META', 'CAMERA', 'HAIR', 'POINTCLOUD'}: return True if ob.instance_type == 'COLLECTION' and ob.instance_collection: return True diff --git a/intern/cycles/blender/geometry.cpp b/intern/cycles/blender/geometry.cpp index a5f36a3a17d..78c803b7adb 100644 --- a/intern/cycles/blender/geometry.cpp +++ b/intern/cycles/blender/geometry.cpp @@ -19,6 +19,7 @@ #include "scene/hair.h" #include "scene/mesh.h" #include "scene/object.h" +#include "scene/pointcloud.h" #include "scene/volume.h" #include "blender/sync.h" @@ -39,6 +40,10 @@ static Geometry::Type determine_geom_type(BObjectInfo &b_ob_info, bool use_parti return Geometry::HAIR; } + if (b_ob_info.object_data.is_a(&RNA_PointCloud)) { + return Geometry::POINTCLOUD; + } + if (b_ob_info.object_data.is_a(&RNA_Volume) || (b_ob_info.object_data == b_ob_info.real_object.data() && object_fluid_gas_domain_find(b_ob_info.real_object))) { @@ -111,6 +116,9 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, else if (geom_type == Geometry::VOLUME) { geom = scene->create_node<Volume>(); } + else if (geom_type == Geometry::POINTCLOUD) { + geom = scene->create_node<PointCloud>(); + } else { geom = scene->create_node<Mesh>(); } @@ -170,6 +178,10 @@ Geometry *BlenderSync::sync_geometry(BL::Depsgraph &b_depsgraph, Volume *volume = static_cast<Volume *>(geom); sync_volume(b_ob_info, volume); } + else if (geom_type == Geometry::POINTCLOUD) { + PointCloud *pointcloud = static_cast<PointCloud *>(geom); + sync_pointcloud(pointcloud, b_ob_info); + } else { Mesh *mesh = static_cast<Mesh *>(geom); sync_mesh(b_depsgraph, b_ob_info, mesh); @@ -231,6 +243,10 @@ void BlenderSync::sync_geometry_motion(BL::Depsgraph &b_depsgraph, object_fluid_gas_domain_find(b_ob_info.real_object)) { /* No volume motion blur support yet. */ } + else if (b_ob_info.object_data.is_a(&RNA_PointCloud)) { + PointCloud *pointcloud = static_cast<PointCloud *>(geom); + sync_pointcloud_motion(pointcloud, b_ob_info, motion_step); + } else { Mesh *mesh = static_cast<Mesh *>(geom); sync_mesh_motion(b_depsgraph, b_ob_info, mesh, motion_step); diff --git a/intern/cycles/blender/object.cpp b/intern/cycles/blender/object.cpp index d6c52f7faf9..86314d3b196 100644 --- a/intern/cycles/blender/object.cpp +++ b/intern/cycles/blender/object.cpp @@ -72,7 +72,8 @@ bool BlenderSync::object_is_geometry(BObjectInfo &b_ob_info) BL::Object::type_enum type = b_ob_info.iter_object.type(); - if (type == BL::Object::type_VOLUME || type == BL::Object::type_HAIR) { + if (type == BL::Object::type_VOLUME || type == BL::Object::type_HAIR || + type == BL::Object::type_POINTCLOUD) { /* Will be exported attached to mesh. */ return true; } @@ -206,7 +207,7 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph, return NULL; } - /* only interested in object that we can create meshes from */ + /* only interested in object that we can create geometry from */ if (!object_is_geometry(b_ob_info)) { return NULL; } diff --git a/intern/cycles/blender/pointcloud.cpp b/intern/cycles/blender/pointcloud.cpp new file mode 100644 index 00000000000..a9e616a468f --- /dev/null +++ b/intern/cycles/blender/pointcloud.cpp @@ -0,0 +1,253 @@ +/* + * Copyright 2011-2013 Blender Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "scene/pointcloud.h" +#include "scene/attribute.h" +#include "scene/scene.h" + +#include "blender/sync.h" +#include "blender/util.h" + +#include "util/foreach.h" +#include "util/hash.h" + +CCL_NAMESPACE_BEGIN + +template<typename TypeInCycles, typename GetValueAtIndex> +static void fill_generic_attribute(BL::PointCloud &b_pointcloud, + TypeInCycles *data, + const GetValueAtIndex &get_value_at_index) +{ + const int num_points = b_pointcloud.points.length(); + for (int i = 0; i < num_points; i++) { + data[i] = get_value_at_index(i); + } +} + +static void copy_attributes(PointCloud *pointcloud, BL::PointCloud b_pointcloud) +{ + AttributeSet &attributes = pointcloud->attributes; + for (BL::Attribute &b_attribute : b_pointcloud.attributes) { + const ustring name{b_attribute.name().c_str()}; + + if (attributes.find(name)) { + continue; + } + + const AttributeElement element = ATTR_ELEMENT_VERTEX; + const BL::Attribute::data_type_enum b_data_type = b_attribute.data_type(); + switch (b_data_type) { + case BL::Attribute::data_type_FLOAT: { + BL::FloatAttribute b_float_attribute{b_attribute}; + Attribute *attr = attributes.add(name, TypeFloat, element); + float *data = attr->data_float(); + fill_generic_attribute( + b_pointcloud, data, [&](int i) { return b_float_attribute.data[i].value(); }); + break; + } + case BL::Attribute::data_type_BOOLEAN: { + BL::BoolAttribute b_bool_attribute{b_attribute}; + Attribute *attr = attributes.add(name, TypeFloat, element); + float *data = attr->data_float(); + fill_generic_attribute( + b_pointcloud, data, [&](int i) { return (float)b_bool_attribute.data[i].value(); }); + break; + } + case BL::Attribute::data_type_INT: { + BL::IntAttribute b_int_attribute{b_attribute}; + Attribute *attr = attributes.add(name, TypeFloat, element); + float *data = attr->data_float(); + fill_generic_attribute( + b_pointcloud, data, [&](int i) { return (float)b_int_attribute.data[i].value(); }); + break; + } + case BL::Attribute::data_type_FLOAT_VECTOR: { + BL::FloatVectorAttribute b_vector_attribute{b_attribute}; + Attribute *attr = attributes.add(name, TypeVector, element); + float3 *data = attr->data_float3(); + fill_generic_attribute(b_pointcloud, data, [&](int i) { + BL::Array<float, 3> v = b_vector_attribute.data[i].vector(); + return make_float3(v[0], v[1], v[2]); + }); + break; + } + case BL::Attribute::data_type_FLOAT_COLOR: { + BL::FloatColorAttribute b_color_attribute{b_attribute}; + Attribute *attr = attributes.add(name, TypeRGBA, element); + float4 *data = attr->data_float4(); + fill_generic_attribute(b_pointcloud, data, [&](int i) { + BL::Array<float, 4> v = b_color_attribute.data[i].color(); + return make_float4(v[0], v[1], v[2], v[3]); + }); + break; + } + case BL::Attribute::data_type_FLOAT2: { + BL::Float2Attribute b_float2_attribute{b_attribute}; + Attribute *attr = attributes.add(name, TypeFloat2, element); + float2 *data = attr->data_float2(); + fill_generic_attribute(b_pointcloud, data, [&](int i) { + BL::Array<float, 2> v = b_float2_attribute.data[i].vector(); + return make_float2(v[0], v[1]); + }); + break; + } + default: + /* Not supported. */ + break; + } + } +} + +static void export_pointcloud(Scene *scene, PointCloud *pointcloud, BL::PointCloud b_pointcloud) +{ + /* TODO: optimize so we can straight memcpy arrays from Blender? */ + + /* Add requested attributes. */ + Attribute *attr_random = NULL; + if (pointcloud->need_attribute(scene, ATTR_STD_POINT_RANDOM)) { + attr_random = pointcloud->attributes.add(ATTR_STD_POINT_RANDOM); + } + + /* Reserve memory. */ + const int num_points = b_pointcloud.points.length(); + pointcloud->reserve(num_points); + + /* Export points. */ + BL::PointCloud::points_iterator b_point_iter; + for (b_pointcloud.points.begin(b_point_iter); b_point_iter != b_pointcloud.points.end(); + ++b_point_iter) { + BL::Point b_point = *b_point_iter; + const float3 co = get_float3(b_point.co()); + const float radius = b_point.radius(); + pointcloud->add_point(co, radius); + + /* Random number per point. */ + if (attr_random != NULL) { + attr_random->add(hash_uint2_to_float(b_point.index(), 0)); + } + } + + /* Export attributes */ + copy_attributes(pointcloud, b_pointcloud); +} + +static void export_pointcloud_motion(PointCloud *pointcloud, + BL::PointCloud b_pointcloud, + int motion_step) +{ + /* Find or add attribute. */ + Attribute *attr_mP = pointcloud->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION); + bool new_attribute = false; + + if (!attr_mP) { + attr_mP = pointcloud->attributes.add(ATTR_STD_MOTION_VERTEX_POSITION); + new_attribute = true; + } + + /* Export motion poin @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list [email protected] List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs
