Cycles: Use Blender headers to access geometry data, avoid copy #112306
|
@ -41,6 +41,7 @@ set(SRC
|
|||
viewport.cpp
|
||||
volume.cpp
|
||||
|
||||
attribute_convert.h
|
||||
CCL_api.h
|
||||
device.h
|
||||
display_driver.h
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/* SPDX-FileCopyrightText: 2023 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#ifndef __BLENDER_ATTRIBUTE_CONVERT_H__
|
||||
|
||||
#define __BLENDER_ATTRIBUTE_CONVERT_H__
|
||||
|
||||
#include "util/array.h"
|
||||
#include "util/color.h"
|
||||
#include "util/param.h"
|
||||
#include "util/types.h"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BLI_math_color.hh"
|
||||
#include "BLI_math_quaternion_types.hh"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
template<typename BlenderT> struct AttributeConverter {
|
||||
using CyclesT = void;
|
||||
};
|
||||
|
||||
template<> struct AttributeConverter<float> {
|
||||
using CyclesT = float;
|
||||
static constexpr auto type_desc = TypeFloat;
|
||||
static CyclesT convert(const float &value)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<int> {
|
||||
using CyclesT = float;
|
||||
static constexpr auto type_desc = TypeFloat;
|
||||
static CyclesT convert(const int &value)
|
||||
{
|
||||
return float(value);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<blender::float3> {
|
||||
using CyclesT = float3;
|
||||
static constexpr auto type_desc = TypeVector;
|
||||
static CyclesT convert(const blender::float3 &value)
|
||||
{
|
||||
return make_float3(value[0], value[1], value[2]);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<blender::ColorGeometry4f> {
|
||||
using CyclesT = float4;
|
||||
static constexpr auto type_desc = TypeRGBA;
|
||||
static CyclesT convert(const blender::ColorGeometry4f &value)
|
||||
{
|
||||
return make_float4(value[0], value[1], value[2], value[3]);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<blender::ColorGeometry4b> {
|
||||
using CyclesT = float4;
|
||||
static constexpr auto type_desc = TypeRGBA;
|
||||
static CyclesT convert(const blender::ColorGeometry4b &value)
|
||||
{
|
||||
return color_srgb_to_linear(make_float4(byte_to_float(value[0]),
|
||||
byte_to_float(value[1]),
|
||||
byte_to_float(value[2]),
|
||||
byte_to_float(value[3])));
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<bool> {
|
||||
using CyclesT = float;
|
||||
static constexpr auto type_desc = TypeFloat;
|
||||
static CyclesT convert(const bool &value)
|
||||
{
|
||||
return float(value);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<int8_t> {
|
||||
using CyclesT = float;
|
||||
static constexpr auto type_desc = TypeFloat;
|
||||
static CyclesT convert(const int8_t &value)
|
||||
{
|
||||
return float(value);
|
||||
}
|
||||
};
|
||||
template<> struct AttributeConverter<blender::math::Quaternion> {
|
||||
using CyclesT = float4;
|
||||
static constexpr auto type_desc = TypeFloat4;
|
||||
static CyclesT convert(const blender::math::Quaternion &value)
|
||||
{
|
||||
return make_float4(value.w, value.x, value.y, value.z);
|
||||
}
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
#endif /* __BLENDER_ATTRIBUTE_CONVERT_H__ */
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
#include <optional>
|
||||
|
||||
#include "BKE_curves.hh"
|
||||
#include "blender/attribute_convert.h"
|
||||
#include "blender/sync.h"
|
||||
#include "blender/util.h"
|
||||
|
||||
|
@ -20,6 +20,8 @@
|
|||
#include "util/hash.h"
|
||||
#include "util/log.h"
|
||||
|
||||
#include "BKE_curves.hh"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
ParticleCurveData::ParticleCurveData() {}
|
||||
|
@ -560,7 +562,7 @@ void BlenderSync::sync_particle_hair(
|
|||
if (!motion) {
|
||||
if (hair->need_attribute(scene, ATTR_STD_GENERATED)) {
|
||||
float3 loc, size;
|
||||
mesh_texture_space(b_mesh, loc, size);
|
||||
mesh_texture_space(*static_cast<const ::Mesh *>(b_mesh.ptr.data), loc, size);
|
||||
|
||||
Attribute *attr_generated = hair->attributes.add(ATTR_STD_GENERATED);
|
||||
float3 *generated = attr_generated->data_float3();
|
||||
|
@ -634,44 +636,6 @@ void BlenderSync::sync_particle_hair(
|
|||
}
|
||||
}
|
||||
|
||||
static const float *find_radius_attribute(BL::Curves b_curves)
|
||||
{
|
||||
for (BL::Attribute &b_attribute : b_curves.attributes) {
|
||||
if (b_attribute.name() != "radius") {
|
||||
continue;
|
||||
}
|
||||
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) {
|
||||
continue;
|
||||
}
|
||||
BL::FloatAttribute b_float_attribute{b_attribute};
|
||||
if (b_float_attribute.data.length() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<const float *>(b_float_attribute.data[0].ptr.data);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static const float (*find_position_attribute(BL::Curves b_curves))[3]
|
||||
{
|
||||
for (BL::Attribute &b_attribute : b_curves.attributes) {
|
||||
if (b_attribute.name() != "position") {
|
||||
continue;
|
||||
}
|
||||
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT_VECTOR) {
|
||||
continue;
|
||||
}
|
||||
BL::FloatVectorAttribute b_float3_attribute{b_attribute};
|
||||
if (b_float3_attribute.data.length() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<const float(*)[3]>(b_float3_attribute.data[0].ptr.data);
|
||||
}
|
||||
/* The position attribute must exist. */
|
||||
assert(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename TypeInCycles, typename GetValueAtIndex>
|
||||
static void fill_generic_attribute(const int num_curves,
|
||||
const int num_points,
|
||||
|
@ -699,16 +663,10 @@ static void fill_generic_attribute(const int num_curves,
|
|||
}
|
||||
}
|
||||
|
||||
static void attr_create_motion(Hair *hair, BL::Attribute &b_attribute, const float motion_scale)
|
||||
static void attr_create_motion(Hair *hair,
|
||||
const blender::Span<blender::float3> src,
|
||||
const float motion_scale)
|
||||
{
|
||||
if (!(b_attribute.domain() == BL::Attribute::domain_POINT) &&
|
||||
(b_attribute.data_type() == BL::Attribute::data_type_FLOAT_VECTOR))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BL::FloatVectorAttribute b_vector_attribute(b_attribute);
|
||||
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
|
||||
const int num_curve_keys = hair->get_curve_keys().size();
|
||||
|
||||
/* Find or add attribute */
|
||||
|
@ -731,177 +689,97 @@ static void attr_create_motion(Hair *hair, BL::Attribute &b_attribute, const flo
|
|||
}
|
||||
}
|
||||
|
||||
static void attr_create_uv(AttributeSet &attributes,
|
||||
const int num_curves,
|
||||
const int num_points,
|
||||
BL::Attribute &b_attribute,
|
||||
const ustring name)
|
||||
{
|
||||
BL::Float2Attribute b_float2_attribute{b_attribute};
|
||||
const float(*src)[2] = static_cast<const float(*)[2]>(b_float2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(ATTR_STD_UV, name);
|
||||
|
||||
float2 *data = attr->data_float2();
|
||||
fill_generic_attribute(num_curves, num_points, data, ATTR_ELEMENT_CURVE, [&](int i) {
|
||||
return make_float2(src[i][0], src[i][1]);
|
||||
});
|
||||
}
|
||||
|
||||
static void attr_create_generic(Scene *scene,
|
||||
Hair *hair,
|
||||
BL::Curves &b_curves,
|
||||
const blender::bke::CurvesGeometry &b_curves,
|
||||
const bool need_motion,
|
||||
const float motion_scale)
|
||||
{
|
||||
const int num_keys = b_curves.points.length();
|
||||
const int num_curves = b_curves.curves.length();
|
||||
const blender::bke::AttributeAccessor b_attributes = b_curves.attributes();
|
||||
|
||||
AttributeSet &attributes = hair->attributes;
|
||||
static const ustring u_velocity("velocity");
|
||||
const bool need_uv = hair->need_attribute(scene, ATTR_STD_UV);
|
||||
bool have_uv = false;
|
||||
|
||||
for (BL::Attribute &b_attribute : b_curves.attributes) {
|
||||
const ustring name{b_attribute.name().c_str()};
|
||||
b_attributes.for_all([&](const blender::bke::AttributeIDRef &id,
|
||||
const blender::bke::AttributeMetaData meta_data) {
|
||||
const ustring name{std::string_view(id.name())};
|
||||
|
||||
const BL::Attribute::domain_enum b_domain = b_attribute.domain();
|
||||
const BL::Attribute::data_type_enum b_data_type = b_attribute.data_type();
|
||||
const eAttrDomain b_domain = meta_data.domain;
|
||||
const eCustomDataType b_data_type = meta_data.data_type;
|
||||
|
||||
if (need_motion && name == u_velocity) {
|
||||
attr_create_motion(hair, b_attribute, motion_scale);
|
||||
continue;
|
||||
const blender::VArraySpan b_attr = *b_attributes.lookup<blender::float3>(id,
|
||||
ATTR_DOMAIN_POINT);
|
||||
attr_create_motion(hair, b_attr, motion_scale);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Weak, use first float2 attribute as standard UV. */
|
||||
if (need_uv && !have_uv && b_data_type == BL::Attribute::data_type_FLOAT2 &&
|
||||
b_domain == BL::Attribute::domain_CURVE)
|
||||
{
|
||||
attr_create_uv(attributes, num_curves, num_keys, b_attribute, name);
|
||||
if (need_uv && !have_uv && b_data_type == CD_PROP_FLOAT2 && b_domain == ATTR_DOMAIN_CURVE) {
|
||||
Attribute *attr = attributes.add(ATTR_STD_UV, name);
|
||||
|
||||
const blender::VArraySpan b_attr = *b_attributes.lookup<blender::float2>(id);
|
||||
|
||||
static_assert(sizeof(blender::float2) == sizeof(float2));
|
||||
const blender::Span src = b_attr.cast<float2>();
|
||||
std::copy(src.begin(), src.end(), attr->data_float2());
|
||||
have_uv = true;
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!hair->need_attribute(scene, name)) {
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
if (attributes.find(name)) {
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
const blender::bke::GAttributeReader b_attr = b_attributes.lookup(id);
|
||||
|
||||
AttributeElement element = ATTR_ELEMENT_NONE;
|
||||
switch (b_domain) {
|
||||
case BL::Attribute::domain_POINT:
|
||||
switch (b_attr.domain) {
|
||||
case ATTR_DOMAIN_POINT:
|
||||
element = ATTR_ELEMENT_CURVE_KEY;
|
||||
break;
|
||||
case BL::Attribute::domain_CURVE:
|
||||
case ATTR_DOMAIN_CURVE:
|
||||
element = ATTR_ELEMENT_CURVE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
if (element == ATTR_ELEMENT_NONE) {
|
||||
/* Not supported. */
|
||||
continue;
|
||||
}
|
||||
switch (b_data_type) {
|
||||
case BL::Attribute::data_type_FLOAT: {
|
||||
BL::FloatAttribute b_float_attribute{b_attribute};
|
||||
const float *src = static_cast<const float *>(b_float_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
||||
float *data = attr->data_float();
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) { return src[i]; });
|
||||
break;
|
||||
|
||||
blender::bke::attribute_math::convert_to_static_type(b_attr.varray.type(), [&](auto dummy) {
|
||||
using BlenderT = decltype(dummy);
|
||||
using Converter = typename ccl::AttributeConverter<BlenderT>;
|
||||
using CyclesT = typename Converter::CyclesT;
|
||||
if constexpr (!std::is_void_v<CyclesT>) {
|
||||
Attribute *attr = attributes.add(name, Converter::type_desc, element);
|
||||
CyclesT *data = reinterpret_cast<CyclesT *>(attr->data());
|
||||
|
||||
const blender::VArraySpan src = b_attr.varray.typed<BlenderT>();
|
||||
for (const int i : src.index_range()) {
|
||||
data[i] = Converter::convert(src[i]);
|
||||
}
|
||||
}
|
||||
case BL::Attribute::data_type_BOOLEAN: {
|
||||
BL::BoolAttribute b_bool_attribute{b_attribute};
|
||||
const bool *src = static_cast<const bool *>(b_bool_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
||||
float *data = attr->data_float();
|
||||
fill_generic_attribute(
|
||||
num_curves, num_keys, data, element, [&](int i) { return float(src[i]); });
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_INT: {
|
||||
BL::IntAttribute b_int_attribute{b_attribute};
|
||||
const int *src = static_cast<const int *>(b_int_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
||||
float *data = attr->data_float();
|
||||
fill_generic_attribute(
|
||||
num_curves, num_keys, data, element, [&](int i) { return float(src[i]); });
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_INT32_2D: {
|
||||
BL::Int2Attribute b_int2_attribute{b_attribute};
|
||||
const int2 *src = static_cast<const int2 *>(b_int2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
||||
float2 *data = attr->data_float2();
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
|
||||
return make_float2(float(src[i][0]), float(src[i][1]));
|
||||
});
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT_VECTOR: {
|
||||
BL::FloatVectorAttribute b_vector_attribute{b_attribute};
|
||||
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeVector, element);
|
||||
float3 *data = attr->data_float3();
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
|
||||
return make_float3(src[i][0], src[i][1], src[i][2]);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_BYTE_COLOR: {
|
||||
BL::ByteColorAttribute b_color_attribute{b_attribute};
|
||||
const uchar(*src)[4] = static_cast<const uchar(*)[4]>(b_color_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeRGBA, element);
|
||||
float4 *data = attr->data_float4();
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
|
||||
return make_float4(color_srgb_to_linear(byte_to_float(src[i][0])),
|
||||
color_srgb_to_linear(byte_to_float(src[i][1])),
|
||||
color_srgb_to_linear(byte_to_float(src[i][2])),
|
||||
color_srgb_to_linear(byte_to_float(src[i][3])));
|
||||
});
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT_COLOR: {
|
||||
BL::FloatColorAttribute b_color_attribute{b_attribute};
|
||||
const float(*src)[4] = static_cast<const float(*)[4]>(b_color_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeRGBA, element);
|
||||
float4 *data = attr->data_float4();
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
|
||||
return make_float4(src[i][0], src[i][1], src[i][2], src[i][3]);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT2: {
|
||||
BL::Float2Attribute b_float2_attribute{b_attribute};
|
||||
const float(*src)[2] = static_cast<const float(*)[2]>(b_float2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
||||
float2 *data = attr->data_float2();
|
||||
fill_generic_attribute(num_curves, num_keys, data, element, [&](int i) {
|
||||
return make_float2(src[i][0], src[i][1]);
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Not supported. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
static float4 curve_point_as_float4(const float (*b_attr_position)[3],
|
||||
const float *b_attr_radius,
|
||||
static float4 curve_point_as_float4(const blender::Span<blender::float3> b_positions,
|
||||
const blender::Span<float> b_radius,
|
||||
const int index)
|
||||
{
|
||||
float4 mP = make_float4(
|
||||
b_attr_position[index][0], b_attr_position[index][1], b_attr_position[index][2], 0.0f);
|
||||
mP.w = b_attr_radius ? b_attr_radius[index] : 0.005f;
|
||||
b_positions[index][0], b_positions[index][1], b_positions[index][2], 0.0f);
|
||||
mP.w = b_radius.is_empty() ? 0.005f : b_radius[index];
|
||||
return mP;
|
||||
}
|
||||
|
||||
static float4 interpolate_curve_points(const float (*b_attr_position)[3],
|
||||
const float *b_attr_radius,
|
||||
static float4 interpolate_curve_points(const blender::Span<blender::float3> b_positions,
|
||||
const blender::Span<float> b_radius,
|
||||
const int first_point_index,
|
||||
const int num_points,
|
||||
const float step)
|
||||
|
@ -910,21 +788,21 @@ static float4 interpolate_curve_points(const float (*b_attr_position)[3],
|
|||
const int point_a = clamp((int)curve_t, 0, num_points - 1);
|
||||
const int point_b = min(point_a + 1, num_points - 1);
|
||||
const float t = curve_t - (float)point_a;
|
||||
return mix(curve_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_a),
|
||||
curve_point_as_float4(b_attr_position, b_attr_radius, first_point_index + point_b),
|
||||
return mix(curve_point_as_float4(b_positions, b_radius, first_point_index + point_a),
|
||||
curve_point_as_float4(b_positions, b_radius, first_point_index + point_b),
|
||||
t);
|
||||
}
|
||||
|
||||
static void export_hair_curves(Scene *scene,
|
||||
Hair *hair,
|
||||
BL::Curves b_curves,
|
||||
const blender::bke::CurvesGeometry &b_curves,
|
||||
const bool need_motion,
|
||||
const float motion_scale)
|
||||
{
|
||||
const int num_keys = b_curves.points.length();
|
||||
const int num_curves = b_curves.curves.length();
|
||||
const blender::Span<blender::float3> positions = b_curves.positions();
|
||||
const blender::OffsetIndices points_by_curve = b_curves.points_by_curve();
|
||||
|
||||
hair->resize_curves(num_curves, num_keys);
|
||||
hair->resize_curves(points_by_curve.size(), positions.size());
|
||||
|
||||
float3 *curve_keys = hair->get_curve_keys().data();
|
||||
float *curve_radius = hair->get_curve_radius().data();
|
||||
|
@ -938,11 +816,14 @@ static void export_hair_curves(Scene *scene,
|
|||
if (hair->need_attribute(scene, ATTR_STD_VERTEX_NORMAL)) {
|
||||
/* Get geometry normals. */
|
||||
float3 *attr_normal = hair->attributes.add(ATTR_STD_VERTEX_NORMAL)->data_float3();
|
||||
int i = 0;
|
||||
for (BL::FloatVectorValueReadOnly &normal : b_curves.normals) {
|
||||
attr_normal[i++] = get_float3(normal.vector());
|
||||
vector<blender::float3> point_normals(positions.size());
|
||||
blender::bke::curves_normals_point_domain_calc(
|
||||
b_curves, {point_normals.data(), int64_t(point_normals.size())});
|
||||
for (const int i : positions.index_range()) {
|
||||
attr_normal[i] = make_float3(point_normals[i][0], point_normals[i][1], point_normals[i][2]);
|
||||
}
|
||||
}
|
||||
|
||||
if (hair->need_attribute(scene, ATTR_STD_CURVE_INTERCEPT)) {
|
||||
attr_intercept = hair->attributes.add(ATTR_STD_CURVE_INTERCEPT)->data_float();
|
||||
}
|
||||
|
@ -951,42 +832,40 @@ static void export_hair_curves(Scene *scene,
|
|||
}
|
||||
if (hair->need_attribute(scene, ATTR_STD_CURVE_RANDOM)) {
|
||||
float *attr_random = hair->attributes.add(ATTR_STD_CURVE_RANDOM)->data_float();
|
||||
for (int i = 0; i < num_curves; i++) {
|
||||
for (const int i : points_by_curve.index_range()) {
|
||||
attr_random[i] = hash_uint2_to_float(i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
const int *point_offsets = static_cast<const int *>(b_curves.curve_offset_data[0].ptr.data);
|
||||
const float(*b_attr_position)[3] = find_position_attribute(b_curves);
|
||||
const float *b_attr_radius = find_radius_attribute(b_curves);
|
||||
const blender::VArraySpan b_radius = *b_curves.attributes().lookup<float>("radius",
|
||||
ATTR_DOMAIN_POINT);
|
||||
|
||||
std::copy(point_offsets, point_offsets + num_curves, curve_first_key);
|
||||
std::fill(curve_shader, curve_shader + num_curves, 0);
|
||||
if (b_attr_radius) {
|
||||
std::copy(b_attr_radius, b_attr_radius + num_keys, curve_radius);
|
||||
std::copy(points_by_curve.data().data(),
|
||||
points_by_curve.data().data() + points_by_curve.size(),
|
||||
curve_first_key);
|
||||
std::fill(curve_shader, curve_shader + points_by_curve.size(), 0);
|
||||
if (!b_radius.is_empty()) {
|
||||
std::copy(b_radius.data(), b_radius.data() + positions.size(), curve_radius);
|
||||
}
|
||||
else {
|
||||
std::fill(curve_radius, curve_radius + num_keys, 0.005f);
|
||||
std::fill(curve_radius, curve_radius + positions.size(), 0.005f);
|
||||
}
|
||||
|
||||
/* Export curves and points. */
|
||||
for (int i = 0; i < num_curves; i++) {
|
||||
const int first_point_index = point_offsets[i];
|
||||
const int num_points = point_offsets[i + 1] - first_point_index;
|
||||
for (const int curve : points_by_curve.index_range()) {
|
||||
const blender::IndexRange points = points_by_curve[curve];
|
||||
|
||||
float3 prev_co = zero_float3();
|
||||
float length = 0.0f;
|
||||
|
||||
/* Position and radius. */
|
||||
for (int j = 0; j < num_points; j++) {
|
||||
const int point = first_point_index + j;
|
||||
const float3 co = make_float3(
|
||||
b_attr_position[point][0], b_attr_position[point][1], b_attr_position[point][2]);
|
||||
for (const int point : points) {
|
||||
const float3 co = make_float3(positions[point][0], positions[point][1], positions[point][2]);
|
||||
|
||||
curve_keys[point] = co;
|
||||
|
||||
if (attr_length || attr_intercept) {
|
||||
if (j > 0) {
|
||||
if (point != points.first()) {
|
||||
length += len(co - prev_co);
|
||||
}
|
||||
prev_co = co;
|
||||
|
@ -999,22 +878,23 @@ static void export_hair_curves(Scene *scene,
|
|||
|
||||
/* Normalized 0..1 attribute along curve. */
|
||||
if (attr_intercept && length > 0.0f) {
|
||||
for (int j = 1; j < num_points; j++) {
|
||||
const int point = first_point_index + j;
|
||||
for (const int point : points.drop_front(1)) {
|
||||
attr_intercept[point] /= length;
|
||||
}
|
||||
}
|
||||
|
||||
/* Curve length. */
|
||||
if (attr_length) {
|
||||
attr_length[i] = length;
|
||||
attr_length[curve] = length;
|
||||
}
|
||||
}
|
||||
|
||||
attr_create_generic(scene, hair, b_curves, need_motion, motion_scale);
|
||||
}
|
||||
|
||||
static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motion_step)
|
||||
static void export_hair_curves_motion(Hair *hair,
|
||||
const blender::bke::CurvesGeometry &b_curves,
|
||||
int motion_step)
|
||||
{
|
||||
/* Find or add attribute. */
|
||||
Attribute *attr_mP = hair->attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
|
@ -1027,30 +907,29 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio
|
|||
|
||||
/* Export motion keys. */
|
||||
const int num_keys = hair->get_curve_keys().size();
|
||||
const int num_curves = b_curves.curves.length();
|
||||
float4 *mP = attr_mP->data_float4() + motion_step * num_keys;
|
||||
bool have_motion = false;
|
||||
int num_motion_keys = 0;
|
||||
int curve_index = 0;
|
||||
|
||||
const int *point_offsets = static_cast<const int *>(b_curves.curve_offset_data[0].ptr.data);
|
||||
const float(*b_attr_position)[3] = find_position_attribute(b_curves);
|
||||
const float *b_attr_radius = find_radius_attribute(b_curves);
|
||||
const blender::Span<blender::float3> b_positions = b_curves.positions();
|
||||
const blender::OffsetIndices points_by_curve = b_curves.points_by_curve();
|
||||
const blender::VArraySpan b_radius = *b_curves.attributes().lookup<float>("radius",
|
||||
ATTR_DOMAIN_POINT);
|
||||
|
||||
for (int i = 0; i < num_curves; i++) {
|
||||
const int first_point_index = point_offsets[i];
|
||||
const int num_points = point_offsets[i + 1] - first_point_index;
|
||||
for (const int i : points_by_curve.index_range()) {
|
||||
const blender::IndexRange points = points_by_curve[i];
|
||||
|
||||
Hair::Curve curve = hair->get_curve(curve_index);
|
||||
curve_index++;
|
||||
|
||||
if (num_points == curve.num_keys) {
|
||||
if (points.size() == curve.num_keys) {
|
||||
/* Number of keys matches. */
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
int point = first_point_index + i;
|
||||
for (const int i : points.index_range()) {
|
||||
int point = points[i];
|
||||
|
||||
if (point < num_keys) {
|
||||
mP[num_motion_keys] = curve_point_as_float4(b_attr_position, b_attr_radius, point);
|
||||
mP[num_motion_keys] = curve_point_as_float4(b_positions, b_radius, point);
|
||||
num_motion_keys++;
|
||||
|
||||
if (!have_motion) {
|
||||
|
@ -1070,7 +949,7 @@ static void export_hair_curves_motion(Hair *hair, BL::Curves b_curves, int motio
|
|||
for (int i = 0; i < curve.num_keys; i++) {
|
||||
const float step = i * step_size;
|
||||
mP[num_motion_keys] = interpolate_curve_points(
|
||||
b_attr_position, b_attr_radius, first_point_index, num_points, step);
|
||||
b_positions, b_radius, points.start(), points.size(), step);
|
||||
num_motion_keys++;
|
||||
}
|
||||
have_motion = true;
|
||||
|
@ -1094,7 +973,8 @@ void BlenderSync::sync_hair(Hair *hair, BObjectInfo &b_ob_info, bool motion, int
|
|||
0.0f;
|
||||
|
||||
/* Convert Blender hair to Cycles curves. */
|
||||
BL::Curves b_curves(b_ob_info.object_data);
|
||||
const blender::bke::CurvesGeometry &b_curves(
|
||||
static_cast<const ::Curves *>(b_ob_info.object_data.ptr.data)->geometry.wrap());
|
||||
if (motion) {
|
||||
export_hair_curves_motion(hair, b_curves, motion_step);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -8,6 +8,7 @@
|
|||
#include "scene/pointcloud.h"
|
||||
#include "scene/scene.h"
|
||||
|
||||
#include "blender/attribute_convert.h"
|
||||
#include "blender/sync.h"
|
||||
#include "blender/util.h"
|
||||
|
||||
|
@ -15,19 +16,16 @@
|
|||
#include "util/foreach.h"
|
||||
#include "util/hash.h"
|
||||
|
||||
#include "BKE_attribute.hh"
|
||||
#include "BKE_attribute_math.hh"
|
||||
#include "BKE_pointcloud.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
static void attr_create_motion(PointCloud *pointcloud,
|
||||
BL::Attribute &b_attribute,
|
||||
const blender::Span<blender::float3> b_attribute,
|
||||
const float motion_scale)
|
||||
{
|
||||
if (!(b_attribute.domain() == BL::Attribute::domain_POINT) &&
|
||||
(b_attribute.data_type() == BL::Attribute::data_type_FLOAT_VECTOR))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BL::FloatVectorAttribute b_vector_attribute(b_attribute);
|
||||
const int num_points = pointcloud->get_points().size();
|
||||
|
||||
/* Find or add attribute */
|
||||
|
@ -46,196 +44,91 @@ static void attr_create_motion(PointCloud *pointcloud,
|
|||
float4 *mP = attr_mP->data_float4() + step * num_points;
|
||||
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
float3 Pi = P[i] + get_float3(b_vector_attribute.data[i].vector()) * relative_time;
|
||||
float3 Pi = P[i] + make_float3(b_attribute[i][0], b_attribute[i][1], b_attribute[i][2]) *
|
||||
relative_time;
|
||||
mP[i] = make_float4(Pi.x, Pi.y, Pi.z, radius[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void copy_attributes(PointCloud *pointcloud,
|
||||
BL::PointCloud b_pointcloud,
|
||||
const ::PointCloud &b_pointcloud,
|
||||
const bool need_motion,
|
||||
const float motion_scale)
|
||||
{
|
||||
const int num_points = b_pointcloud.points.length();
|
||||
if (num_points == 0) {
|
||||
const blender::bke::AttributeAccessor b_attributes = b_pointcloud.attributes();
|
||||
if (b_attributes.domain_size(ATTR_DOMAIN_POINT) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
AttributeSet &attributes = pointcloud->attributes;
|
||||
static const ustring u_velocity("velocity");
|
||||
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
|
||||
const ustring name{b_attribute.name().c_str()};
|
||||
b_attributes.for_all([&](const blender::bke::AttributeIDRef &id,
|
||||
const blender::bke::AttributeMetaData /*meta_data*/) {
|
||||
const ustring name{std::string_view(id.name())};
|
||||
|
||||
if (need_motion && name == u_velocity) {
|
||||
attr_create_motion(pointcloud, b_attribute, motion_scale);
|
||||
const blender::VArraySpan b_attr = *b_attributes.lookup<blender::float3>(id);
|
||||
attr_create_motion(pointcloud, b_attr, motion_scale);
|
||||
}
|
||||
|
||||
if (attributes.find(name)) {
|
||||
continue;
|
||||
return true;
|
||||
}
|
||||
|
||||
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};
|
||||
const float *src = static_cast<const float *>(b_float_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
||||
float *data = attr->data_float();
|
||||
std::copy(src, src + num_points, data);
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_BOOLEAN: {
|
||||
BL::BoolAttribute b_bool_attribute{b_attribute};
|
||||
const bool *src = static_cast<const bool *>(b_bool_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
||||
float *data = attr->data_float();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = float(src[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_INT: {
|
||||
BL::IntAttribute b_int_attribute{b_attribute};
|
||||
const int *src = static_cast<const int *>(b_int_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat, element);
|
||||
float *data = attr->data_float();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = float(src[i]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_INT32_2D: {
|
||||
BL::Int2Attribute b_int2_attribute{b_attribute};
|
||||
const int2 *src = static_cast<const int2 *>(b_int2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
||||
float2 *data = attr->data_float2();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = make_float2(float(src[i][0]), float(src[i][1]));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT_VECTOR: {
|
||||
BL::FloatVectorAttribute b_vector_attribute{b_attribute};
|
||||
const float(*src)[3] = static_cast<const float(*)[3]>(b_vector_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeVector, element);
|
||||
float3 *data = attr->data_float3();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = make_float3(src[i][0], src[i][1], src[i][2]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_BYTE_COLOR: {
|
||||
BL::ByteColorAttribute b_color_attribute{b_attribute};
|
||||
const uchar(*src)[4] = static_cast<const uchar(*)[4]>(b_color_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeRGBA, element);
|
||||
float4 *data = attr->data_float4();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = make_float4(color_srgb_to_linear(byte_to_float(src[i][0])),
|
||||
color_srgb_to_linear(byte_to_float(src[i][1])),
|
||||
color_srgb_to_linear(byte_to_float(src[i][2])),
|
||||
color_srgb_to_linear(byte_to_float(src[i][3])));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT_COLOR: {
|
||||
BL::FloatColorAttribute b_color_attribute{b_attribute};
|
||||
const float(*src)[4] = static_cast<const float(*)[4]>(b_color_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeRGBA, element);
|
||||
float4 *data = attr->data_float4();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = make_float4(src[i][0], src[i][1], src[i][2], src[i][3]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case BL::Attribute::data_type_FLOAT2: {
|
||||
BL::Float2Attribute b_float2_attribute{b_attribute};
|
||||
const float(*src)[2] = static_cast<const float(*)[2]>(b_float2_attribute.data[0].ptr.data);
|
||||
Attribute *attr = attributes.add(name, TypeFloat2, element);
|
||||
float2 *data = attr->data_float2();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
data[i] = make_float2(src[i][0], src[i][1]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
/* Not supported. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const blender::bke::GAttributeReader b_attr = b_attributes.lookup(id);
|
||||
blender::bke::attribute_math::convert_to_static_type(b_attr.varray.type(), [&](auto dummy) {
|
||||
using BlenderT = decltype(dummy);
|
||||
using Converter = typename ccl::AttributeConverter<BlenderT>;
|
||||
using CyclesT = typename Converter::CyclesT;
|
||||
if constexpr (!std::is_void_v<CyclesT>) {
|
||||
Attribute *attr = attributes.add(name, Converter::type_desc, ATTR_ELEMENT_VERTEX);
|
||||
CyclesT *data = reinterpret_cast<CyclesT *>(attr->data());
|
||||
|
||||
static const float *find_radius_attribute(BL::PointCloud b_pointcloud)
|
||||
{
|
||||
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
|
||||
if (b_attribute.name() != "radius") {
|
||||
continue;
|
||||
}
|
||||
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT) {
|
||||
continue;
|
||||
}
|
||||
BL::FloatAttribute b_float_attribute{b_attribute};
|
||||
if (b_float_attribute.data.length() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<const float *>(b_float_attribute.data[0].ptr.data);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
const blender::VArraySpan src = b_attr.varray.typed<BlenderT>();
|
||||
for (const int i : src.index_range()) {
|
||||
data[i] = Converter::convert(src[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
static const float (*find_position_attribute(BL::PointCloud b_pointcloud))[3]
|
||||
{
|
||||
for (BL::Attribute &b_attribute : b_pointcloud.attributes) {
|
||||
if (b_attribute.name() != "position") {
|
||||
continue;
|
||||
}
|
||||
if (b_attribute.data_type() != BL::Attribute::data_type_FLOAT_VECTOR) {
|
||||
continue;
|
||||
}
|
||||
BL::FloatVectorAttribute b_float3_attribute{b_attribute};
|
||||
if (b_float3_attribute.data.length() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<const float(*)[3]>(b_float3_attribute.data[0].ptr.data);
|
||||
}
|
||||
/* The position attribute must exist. */
|
||||
assert(false);
|
||||
return nullptr;
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
static void export_pointcloud(Scene *scene,
|
||||
PointCloud *pointcloud,
|
||||
BL::PointCloud b_pointcloud,
|
||||
const ::PointCloud &b_pointcloud,
|
||||
const bool need_motion,
|
||||
const float motion_scale)
|
||||
{
|
||||
const int num_points = b_pointcloud.points.length();
|
||||
pointcloud->resize(num_points);
|
||||
const blender::Span<blender::float3> b_positions = b_pointcloud.positions();
|
||||
const blender::VArraySpan b_radius = *b_pointcloud.attributes().lookup<float>("radius",
|
||||
ATTR_DOMAIN_POINT);
|
||||
|
||||
pointcloud->resize(b_positions.size());
|
||||
|
||||
const float(*b_attr_position)[3] = find_position_attribute(b_pointcloud);
|
||||
float3 *points = pointcloud->get_points().data();
|
||||
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
points[i] = make_float3(b_attr_position[i][0], b_attr_position[i][1], b_attr_position[i][2]);
|
||||
for (const int i : b_positions.index_range()) {
|
||||
points[i] = make_float3(b_positions[i][0], b_positions[i][1], b_positions[i][2]);
|
||||
}
|
||||
|
||||
const float *b_attr_radius = find_radius_attribute(b_pointcloud);
|
||||
float *radius = pointcloud->get_radius().data();
|
||||
if (b_attr_radius) {
|
||||
std::copy(b_attr_radius, b_attr_radius + num_points, radius);
|
||||
if (!b_radius.is_empty()) {
|
||||
std::copy(b_radius.data(), b_radius.data() + b_positions.size(), radius);
|
||||
}
|
||||
else {
|
||||
std::fill(radius, radius + num_points, 0.01f);
|
||||
std::fill(radius, radius + b_positions.size(), 0.01f);
|
||||
}
|
||||
|
||||
int *shader = pointcloud->get_shader().data();
|
||||
std::fill(shader, shader + num_points, 0);
|
||||
std::fill(shader, shader + b_positions.size(), 0);
|
||||
|
||||
if (pointcloud->need_attribute(scene, ATTR_STD_POINT_RANDOM)) {
|
||||
Attribute *attr_random = pointcloud->attributes.add(ATTR_STD_POINT_RANDOM);
|
||||
float *data = attr_random->data_float();
|
||||
for (int i = 0; i < num_points; i++) {
|
||||
for (const int i : b_positions.index_range()) {
|
||||
data[i] = hash_uint2_to_float(i, 0);
|
||||
}
|
||||
}
|
||||
|
@ -244,7 +137,7 @@ static void export_pointcloud(Scene *scene,
|
|||
}
|
||||
|
||||
static void export_pointcloud_motion(PointCloud *pointcloud,
|
||||
BL::PointCloud b_pointcloud,
|
||||
const ::PointCloud &b_pointcloud,
|
||||
int motion_step)
|
||||
{
|
||||
/* Find or add attribute. */
|
||||
|
@ -264,21 +157,20 @@ static void export_pointcloud_motion(PointCloud *pointcloud,
|
|||
bool have_motion = false;
|
||||
const array<float3> &pointcloud_points = pointcloud->get_points();
|
||||
|
||||
const int b_points_num = b_pointcloud.points.length();
|
||||
const float(*b_attr_position)[3] = find_position_attribute(b_pointcloud);
|
||||
const float *b_attr_radius = find_radius_attribute(b_pointcloud);
|
||||
const blender::Span<blender::float3> b_positions = b_pointcloud.positions();
|
||||
const blender::VArraySpan b_radius = *b_pointcloud.attributes().lookup<float>("radius",
|
||||
ATTR_DOMAIN_POINT);
|
||||
|
||||
for (int i = 0; i < std::min(num_points, b_points_num); i++) {
|
||||
const float3 P = make_float3(
|
||||
b_attr_position[i][0], b_attr_position[i][1], b_attr_position[i][2]);
|
||||
const float radius = b_attr_radius ? b_attr_radius[i] : 0.01f;
|
||||
for (int i = 0; i < std::min<int>(num_points, b_positions.size()); i++) {
|
||||
const float3 P = make_float3(b_positions[i][0], b_positions[i][1], b_positions[i][2]);
|
||||
const float radius = b_radius.is_empty() ? 0.01f : b_radius[i];
|
||||
mP[i] = make_float4(P.x, P.y, P.z, radius);
|
||||
have_motion = have_motion || (P != pointcloud_points[i]);
|
||||
}
|
||||
|
||||
/* In case of new attribute, we verify if there really was any motion. */
|
||||
if (new_attribute) {
|
||||
if (b_points_num != num_points || !have_motion) {
|
||||
if (b_positions.size() != num_points || !have_motion) {
|
||||
pointcloud->attributes.remove(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
}
|
||||
else if (motion_step > 0) {
|
||||
|
@ -311,7 +203,11 @@ void BlenderSync::sync_pointcloud(PointCloud *pointcloud, BObjectInfo &b_ob_info
|
|||
scene->motion_shutter_time() /
|
||||
(b_scene.render().fps() / b_scene.render().fps_base()) :
|
||||
0.0f;
|
||||
export_pointcloud(scene, &new_pointcloud, b_pointcloud, need_motion, motion_scale);
|
||||
export_pointcloud(scene,
|
||||
&new_pointcloud,
|
||||
*static_cast<const ::PointCloud *>(b_pointcloud.ptr.data),
|
||||
need_motion,
|
||||
motion_scale);
|
||||
|
||||
/* Update original sockets. */
|
||||
for (const SocketType &socket : new_pointcloud.type->inputs) {
|
||||
|
@ -347,7 +243,8 @@ void BlenderSync::sync_pointcloud_motion(PointCloud *pointcloud,
|
|||
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);
|
||||
export_pointcloud_motion(
|
||||
pointcloud, *static_cast<const ::PointCloud *>(b_pointcloud.ptr.data), motion_step);
|
||||
}
|
||||
else {
|
||||
/* No deformation on this frame, copy coordinates if other frames did have it. */
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include "util/types.h"
|
||||
#include "util/vector.h"
|
||||
|
||||
#include "BKE_mesh.hh"
|
||||
|
||||
/* Hacks to hook into Blender API
|
||||
* todo: clean this up ... */
|
||||
|
||||
|
@ -524,10 +526,13 @@ static inline string get_text_datablock_content(const PointerRNA &ptr)
|
|||
|
||||
/* Texture Space */
|
||||
|
||||
static inline void mesh_texture_space(BL::Mesh &b_mesh, float3 &loc, float3 &size)
|
||||
static inline void mesh_texture_space(const ::Mesh &b_mesh, float3 &loc, float3 &size)
|
||||
{
|
||||
loc = get_float3(b_mesh.texspace_location());
|
||||
size = get_float3(b_mesh.texspace_size());
|
||||
float texspace_location[3], texspace_size[3];
|
||||
BKE_mesh_texspace_get(const_cast<::Mesh *>(&b_mesh), texspace_location, texspace_size);
|
||||
|
||||
loc = make_float3(texspace_location[0], texspace_location[1], texspace_location[2]);
|
||||
size = make_float3(texspace_size[0], texspace_size[1], texspace_size[2]);
|
||||
|
||||
if (size.x != 0.0f)
|
||||
size.x = 0.5f / size.x;
|
||||
|
|
|
@ -25,8 +25,8 @@ class BlenderSmokeLoader : public ImageLoader {
|
|||
BlenderSmokeLoader(BL::Object &b_ob, AttributeStandard attribute)
|
||||
: b_domain(object_fluid_gas_domain_find(b_ob)), attribute(attribute)
|
||||
{
|
||||
BL::Mesh b_mesh(b_ob.data());
|
||||
mesh_texture_space(b_mesh, texspace_loc, texspace_size);
|
||||
mesh_texture_space(
|
||||
*static_cast<const ::Mesh *>(b_ob.data().ptr.data), texspace_loc, texspace_size);
|
||||
}
|
||||
|
||||
bool load_metadata(const ImageDeviceFeatures &, ImageMetaData &metadata) override
|
||||
|
|
|
@ -443,6 +443,8 @@ class CurvesEditHints {
|
|||
bool is_valid() const;
|
||||
};
|
||||
|
||||
void curves_normals_point_domain_calc(const CurvesGeometry &curves, MutableSpan<float3> normals);
|
||||
|
||||
namespace curves {
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include "BKE_anim_data.h"
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_customdata.h"
|
||||
#include "BKE_geometry_fields.hh"
|
||||
#include "BKE_geometry_set.hh"
|
||||
#include "BKE_global.h"
|
||||
#include "BKE_idtype.h"
|
||||
|
@ -367,4 +368,13 @@ bool CurvesEditHints::is_valid() const
|
|||
return true;
|
||||
}
|
||||
|
||||
void curves_normals_point_domain_calc(const CurvesGeometry &curves, MutableSpan<float3> normals)
|
||||
{
|
||||
const bke::CurvesFieldContext context(curves, ATTR_DOMAIN_POINT);
|
||||
fn::FieldEvaluator evaluator(context, curves.points_num());
|
||||
fn::Field<float3> field(std::make_shared<bke::NormalFieldInput>());
|
||||
evaluator.add_with_destination(std::move(field), normals);
|
||||
evaluator.evaluate();
|
||||
}
|
||||
|
||||
} // namespace blender::bke
|
||||
|
|
|
@ -3,9 +3,6 @@
|
|||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "BKE_curves.hh"
|
||||
#include "BKE_geometry_fields.hh"
|
||||
|
||||
#include "BLI_task.hh"
|
||||
|
||||
#include "DNA_object_types.h"
|
||||
|
||||
|
@ -39,14 +36,7 @@ float (*ED_curves_point_normals_array_create(const Curves *curves_id))[3]
|
|||
using namespace blender;
|
||||
const bke::CurvesGeometry &curves = curves_id->geometry.wrap();
|
||||
const int size = curves.points_num();
|
||||
|
||||
float3 *data = static_cast<float3 *>(MEM_malloc_arrayN(size, sizeof(float3), __func__));
|
||||
|
||||
const bke::CurvesFieldContext context(curves, ATTR_DOMAIN_POINT);
|
||||
fn::FieldEvaluator evaluator(context, size);
|
||||
fn::Field<float3> field(std::make_shared<bke::NormalFieldInput>());
|
||||
evaluator.add_with_destination(std::move(field), {data, size});
|
||||
evaluator.evaluate();
|
||||
|
||||
bke::curves_normals_point_domain_calc(curves, {data, size});
|
||||
return reinterpret_cast<float(*)[3]>(data);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
In the new code we use
#pragma once
.Perhaps we should just go ahead and convert the header guards to uniform case, similar to what we did in Blender.