Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'intern/cycles/blender/pointcloud.cpp')
-rw-r--r--intern/cycles/blender/pointcloud.cpp253
1 files changed, 253 insertions, 0 deletions
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 points. */
+ const int num_points = pointcloud->num_points();
+ float3 *mP = attr_mP->data_float3() + motion_step * num_points;
+ bool have_motion = false;
+ int num_motion_points = 0;
+ const array<float3> &pointcloud_points = pointcloud->get_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;
+
+ if (num_motion_points < num_points) {
+ float3 P = get_float3(b_point.co());
+ P.w = b_point.radius();
+ mP[num_motion_points] = P;
+ have_motion = have_motion || (P != pointcloud_points[num_motion_points]);
+ num_motion_points++;
+ }
+ }
+
+ /* In case of new attribute, we verify if there really was any motion. */
+ if (new_attribute) {
+ if (num_motion_points != num_points || !have_motion) {
+ pointcloud->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
+ }
+ else if (motion_step > 0) {
+ /* Motion, fill up previous steps that we might have skipped because
+ * they had no motion, but we need them anyway now. */
+ for (int step = 0; step < motion_step; step++) {
+ pointcloud->copy_center_to_motion_step(step);
+ }
+ }
+ }
+
+ /* Export attributes */
+ copy_attributes(pointcloud, b_pointcloud);
+}
+
+void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info)
+{
+ size_t old_numpoints = pointcloud->num_points();
+
+ array<Node *> used_shaders = pointcloud->get_used_shaders();
+
+ PointCloud new_pointcloud;
+ new_pointcloud.set_used_shaders(used_shaders);
+
+ /* TODO: add option to filter out points in the view layer. */
+ BL::PointCloud b_pointcloud(b_ob_info.object_data);
+ export_pointcloud(scene, &new_pointcloud, b_pointcloud);
+
+ /* update original sockets */
+ for (const SocketType &socket : new_pointcloud.type->inputs) {
+ /* Those sockets are updated in sync_object, so do not modify them. */
+ if (socket.name == "use_motion_blur" || socket.name == "motion_steps" ||
+ socket.name == "used_shaders") {
+ continue;
+ }
+ pointcloud->set_value(socket, new_pointcloud, socket);
+ }
+
+ pointcloud->attributes.clear();
+ foreach (Attribute &attr, new_pointcloud.attributes.attributes) {
+ pointcloud->attributes.attributes.push_back(std::move(attr));
+ }
+
+ /* tag update */
+ const bool rebuild = (pointcloud && old_numpoints != pointcloud->num_points());
+ pointcloud->tag_update(scene, rebuild);
+}
+
+void BlenderSync::sync_pointcloud_motion(PointCloud *pointcloud,
+ BObjectInfo &b_ob_info,
+ int motion_step)
+{
+ /* Skip if nothing exported. */
+ if (pointcloud->num_points() == 0) {
+ return;
+ }
+
+ /* Export deformed coordinates. */
+ if (ccl::BKE_object_is_deform_modified(b_ob_info, b_scene, preview)) {
+ /* PointCloud object. */
+ BL::PointCloud b_pointcloud(b_ob_info.object_data);
+ export_pointcloud_motion(pointcloud, b_pointcloud, motion_step);
+ }
+ else {
+ /* No deformation on this frame, copy coordinates if other frames did have it. */
+ pointcloud->copy_center_to_motion_step(motion_step);
+ }
+}
+
+CCL_NAMESPACE_END