mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Refactor: Cycles: Store hair curve key positions and radii as attributes
This will enable implicit sharing with Blender data. Pull Request: https://projects.blender.org/blender/blender/pulls/158728
This commit is contained in:
parent
edafe4f5ee
commit
e9c36249f7
8 changed files with 66 additions and 67 deletions
|
|
@ -1380,7 +1380,7 @@ void OptiXDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
|
|||
++curve_index)
|
||||
{
|
||||
const Hair::Curve curve = hair->get_curve(curve_index);
|
||||
const array<float> &curve_radius = hair->get_curve_radius();
|
||||
const float *curve_radius = hair->get_radius();
|
||||
|
||||
if (hair->curve_shape == CURVE_THICK_LINEAR) {
|
||||
const int first_key_index = curve.first_key;
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
#include "hydra/geometry.inl"
|
||||
#include "hydra/util.h"
|
||||
#include "scene/hair.h"
|
||||
#include "util/types_float3.h"
|
||||
|
||||
#include <pxr/imaging/hd/basisCurvesSchema.h>
|
||||
#include <pxr/imaging/hd/basisCurvesTopologySchema.h>
|
||||
|
|
@ -70,14 +71,13 @@ void HdCyclesCurves::PopulatePoints(HdSceneDelegate *sceneDelegate)
|
|||
|
||||
const auto &points = value.UncheckedGet<VtVec3fArray>();
|
||||
|
||||
array<packed_float3> pointsDataCycles;
|
||||
pointsDataCycles.reserve(points.size());
|
||||
TF_VERIFY(points.size() >= _geom->num_keys());
|
||||
|
||||
for (const GfVec3f &point : points) {
|
||||
pointsDataCycles.push_back_reserved(make_float3(point[0], point[1], point[2]));
|
||||
}
|
||||
static_assert(sizeof(GfVec3f) == sizeof(packed_float3));
|
||||
|
||||
_geom->set_curve_keys(pointsDataCycles);
|
||||
std::copy_n(reinterpret_cast<const packed_float3 *>(points.data()),
|
||||
std::min(points.size(), _geom->num_keys()),
|
||||
_geom->get_position_for_write());
|
||||
}
|
||||
|
||||
void HdCyclesCurves::PopulateWidths(HdSceneDelegate *sceneDelegate)
|
||||
|
|
@ -93,9 +93,7 @@ void HdCyclesCurves::PopulateWidths(HdSceneDelegate *sceneDelegate)
|
|||
}
|
||||
|
||||
const auto &widths = value.UncheckedGet<VtFloatArray>();
|
||||
|
||||
array<float> radiusDataCycles;
|
||||
radiusDataCycles.reserve(widths.size());
|
||||
float *radius = _geom->get_radius_for_write();
|
||||
|
||||
if (interpolation == HdInterpolationConstant) {
|
||||
TF_VERIFY(widths.size() == 1);
|
||||
|
|
@ -103,18 +101,16 @@ void HdCyclesCurves::PopulateWidths(HdSceneDelegate *sceneDelegate)
|
|||
const float constantRadius = widths[0] * 0.5f;
|
||||
|
||||
for (size_t i = 0; i < _geom->num_keys(); ++i) {
|
||||
radiusDataCycles.push_back_reserved(constantRadius);
|
||||
radius[i] = constantRadius;
|
||||
}
|
||||
}
|
||||
else if (interpolation == HdInterpolationVertex) {
|
||||
TF_VERIFY(widths.size() == _geom->num_keys());
|
||||
|
||||
for (size_t i = 0; i < _geom->num_keys(); ++i) {
|
||||
radiusDataCycles.push_back_reserved(widths[i] * 0.5f);
|
||||
radius[i] = widths[i] * 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
_geom->set_curve_radius(radiusDataCycles);
|
||||
}
|
||||
|
||||
void HdCyclesCurves::PopulatePrimvars(HdSceneDelegate *sceneDelegate)
|
||||
|
|
|
|||
|
|
@ -768,6 +768,7 @@ enum AttributeElement {
|
|||
enum AttributeStandard : int {
|
||||
ATTR_STD_NONE = 0,
|
||||
ATTR_STD_POSITION,
|
||||
ATTR_STD_RADIUS,
|
||||
ATTR_STD_VERTEX_NORMAL,
|
||||
ATTR_STD_CORNER_NORMAL,
|
||||
ATTR_STD_UV,
|
||||
|
|
|
|||
|
|
@ -463,6 +463,8 @@ const char *Attribute::standard_name(AttributeStandard std)
|
|||
switch (std) {
|
||||
case ATTR_STD_POSITION:
|
||||
return "P";
|
||||
case ATTR_STD_RADIUS:
|
||||
return "radius";
|
||||
case ATTR_STD_VERTEX_NORMAL:
|
||||
case ATTR_STD_CORNER_NORMAL:
|
||||
return "N";
|
||||
|
|
@ -801,6 +803,8 @@ static TypeDesc find_type_from_geometry_std(Geometry *geometry, AttributeStandar
|
|||
switch (std) {
|
||||
case ATTR_STD_POSITION:
|
||||
return TypePoint;
|
||||
case ATTR_STD_RADIUS:
|
||||
return TypeFloat;
|
||||
case ATTR_STD_VERTEX_NORMAL:
|
||||
return TypeNormal;
|
||||
case ATTR_STD_MOTION_VERTEX_NORMAL:
|
||||
|
|
@ -931,6 +935,8 @@ static AttributeElement find_element_from_geometry_std(Geometry *geometry, Attri
|
|||
switch (std) {
|
||||
case ATTR_STD_POSITION:
|
||||
return ATTR_ELEMENT_CURVE_KEY;
|
||||
case ATTR_STD_RADIUS:
|
||||
return ATTR_ELEMENT_CURVE_KEY;
|
||||
case ATTR_STD_VERTEX_NORMAL:
|
||||
return ATTR_ELEMENT_CURVE_KEY_NORMAL;
|
||||
case ATTR_STD_MOTION_VERTEX_NORMAL:
|
||||
|
|
|
|||
|
|
@ -107,6 +107,19 @@ bool Geometry::position_is_modified() const
|
|||
return position_modified;
|
||||
}
|
||||
|
||||
const float *Geometry::get_radius() const
|
||||
{
|
||||
const Attribute *attr = attributes.find(ATTR_STD_RADIUS);
|
||||
return attr ? attr->data<float>() : nullptr;
|
||||
}
|
||||
|
||||
float *Geometry::get_radius_for_write()
|
||||
{
|
||||
Attribute *attr = attributes.add(ATTR_STD_RADIUS);
|
||||
tag_radius_modified();
|
||||
return attr->data_for_write<float>();
|
||||
}
|
||||
|
||||
void Geometry::tag_radius_modified()
|
||||
{
|
||||
radius_modified = true;
|
||||
|
|
|
|||
|
|
@ -121,6 +121,8 @@ class Geometry : public Node {
|
|||
bool position_is_modified() const;
|
||||
|
||||
/* Radius attribute. */
|
||||
const float *get_radius() const;
|
||||
float *get_radius_for_write();
|
||||
void tag_radius_modified();
|
||||
bool radius_is_modified() const;
|
||||
|
||||
|
|
|
|||
|
|
@ -318,8 +318,6 @@ NODE_DEFINE(Hair)
|
|||
{
|
||||
NodeType *type = NodeType::add("hair", create, NodeType::NONE, Geometry::get_node_base_type());
|
||||
|
||||
SOCKET_POINT_ARRAY(curve_keys, "Curve Keys", array<packed_float3>());
|
||||
SOCKET_FLOAT_ARRAY(curve_radius, "Curve Radius", array<float>());
|
||||
SOCKET_INT_ARRAY(curve_first_key, "Curve First Key", array<int>());
|
||||
SOCKET_INT_ARRAY(curve_shader, "Curve Shader", array<int>());
|
||||
|
||||
|
|
@ -331,36 +329,28 @@ Hair::Hair() : Geometry(get_node_type(), Geometry::HAIR)
|
|||
curve_key_offset = 0;
|
||||
curve_segment_offset = 0;
|
||||
curve_shape = CURVE_RIBBON;
|
||||
|
||||
add_builtin_attributes();
|
||||
}
|
||||
|
||||
Hair::~Hair() = default;
|
||||
|
||||
const packed_float3 *Hair::get_position() const
|
||||
size_t Hair::num_keys() const
|
||||
{
|
||||
return curve_keys.data();
|
||||
const Attribute *attr = attributes.find(ATTR_STD_POSITION);
|
||||
return attr ? attr->size : 0;
|
||||
}
|
||||
|
||||
packed_float3 *Hair::get_position_for_write()
|
||||
void Hair::add_builtin_attributes()
|
||||
{
|
||||
tag_position_modified();
|
||||
return curve_keys.data();
|
||||
}
|
||||
|
||||
const float *Hair::get_radius() const
|
||||
{
|
||||
return curve_radius.data();
|
||||
}
|
||||
|
||||
float *Hair::get_radius_for_write()
|
||||
{
|
||||
tag_radius_modified();
|
||||
return curve_radius.data();
|
||||
attributes.add(ATTR_STD_POSITION);
|
||||
attributes.add(ATTR_STD_RADIUS);
|
||||
}
|
||||
|
||||
void Hair::resize_curves(const int numcurves, const int numkeys)
|
||||
{
|
||||
curve_keys.resize(numkeys);
|
||||
curve_radius.resize(numkeys);
|
||||
attributes.add(ATTR_STD_POSITION)->resize(numkeys);
|
||||
attributes.add(ATTR_STD_RADIUS)->resize(numkeys);
|
||||
curve_first_key.resize(numcurves);
|
||||
curve_shader.resize(numcurves);
|
||||
|
||||
|
|
@ -371,20 +361,19 @@ void Hair::clear(bool preserve_shaders)
|
|||
{
|
||||
Geometry::clear(preserve_shaders);
|
||||
|
||||
curve_keys.clear();
|
||||
curve_radius.clear();
|
||||
curve_first_key.clear();
|
||||
curve_shader.clear();
|
||||
|
||||
attributes.clear();
|
||||
add_builtin_attributes();
|
||||
}
|
||||
|
||||
void Hair::copy_center_to_motion_step(const int motion_step)
|
||||
{
|
||||
Attribute *attr_mP = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
if (attr_mP) {
|
||||
packed_float3 *keys = curve_keys.data();
|
||||
const size_t numkeys = curve_keys.size();
|
||||
const packed_float3 *keys = get_position();
|
||||
const size_t numkeys = num_keys();
|
||||
std::copy_n(keys, numkeys, attr_mP->data_for_write<packed_float3>() + motion_step * numkeys);
|
||||
}
|
||||
|
||||
|
|
@ -392,7 +381,7 @@ void Hair::copy_center_to_motion_step(const int motion_step)
|
|||
Attribute *attr_vN = attributes.find(ATTR_STD_VERTEX_NORMAL);
|
||||
if (attr_mvN && attr_vN) {
|
||||
const packed_normal *vN = attr_vN->data<packed_normal>();
|
||||
const size_t numkeys = curve_keys.size();
|
||||
const size_t numkeys = num_keys();
|
||||
std::copy_n(vN, numkeys, attr_mvN->data_for_write<packed_normal>() + motion_step * numkeys);
|
||||
}
|
||||
}
|
||||
|
|
@ -416,8 +405,10 @@ void Hair::get_uv_tiles(ustring map, unordered_set<int> &tiles)
|
|||
void Hair::compute_bounds()
|
||||
{
|
||||
BoundBox bnds = BoundBox::empty;
|
||||
const size_t positions_size = curve_keys.size();
|
||||
const size_t positions_size = num_keys();
|
||||
const size_t curve_num = num_curves();
|
||||
const packed_float3 *positions = get_position();
|
||||
const float *radius = get_radius();
|
||||
|
||||
if (positions_size > 0) {
|
||||
bnds.grow(parallel_reduce(
|
||||
|
|
@ -429,7 +420,7 @@ void Hair::compute_bounds()
|
|||
const Curve curve = get_curve(i);
|
||||
const int num_segments = curve.num_segments();
|
||||
for (int k = 0; k < num_segments; k++) {
|
||||
curve.bounds_grow(k, curve_keys.data(), curve_radius.data(), current_bounds);
|
||||
curve.bounds_grow(k, positions, radius, current_bounds);
|
||||
}
|
||||
}
|
||||
return current_bounds;
|
||||
|
|
@ -442,7 +433,7 @@ void Hair::compute_bounds()
|
|||
|
||||
Attribute *curve_attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
if (use_motion_blur && curve_attr) {
|
||||
const size_t steps_size = curve_keys.size() * (motion_steps - 1);
|
||||
const size_t steps_size = positions_size * (motion_steps - 1);
|
||||
// Attribute data is stored as a float4 and is not
|
||||
// interchangeable with float3
|
||||
const float4 *key_steps = curve_attr->data<float4>();
|
||||
|
|
@ -457,11 +448,11 @@ void Hair::compute_bounds()
|
|||
|
||||
/* skip nan or inf coordinates */
|
||||
for (size_t i = 0; i < positions_size; i++) {
|
||||
bnds.grow_safe(curve_keys[i], curve_radius[i]);
|
||||
bnds.grow_safe(positions[i], radius[i]);
|
||||
}
|
||||
|
||||
if (use_motion_blur && curve_attr) {
|
||||
const size_t steps_size = curve_keys.size() * (motion_steps - 1);
|
||||
const size_t steps_size = positions_size * (motion_steps - 1);
|
||||
// Attribute data is stored as a float4 which is not
|
||||
// interchangeable with float4
|
||||
const float4 *key_steps = curve_attr->data<float4>();
|
||||
|
|
@ -490,11 +481,11 @@ void Hair::apply_transform(const Transform &tfm, const bool apply_to_motion)
|
|||
const float scalar = powf(fabsf(dot(cross(c0, c1), c2)), 1.0f / 3.0f);
|
||||
|
||||
/* apply transform to curve keys */
|
||||
const size_t num_keys = curve_keys.size();
|
||||
packed_float3 *positions_data = curve_keys.data();
|
||||
float *radius_data = curve_radius.data();
|
||||
const size_t num_keys_local = num_keys();
|
||||
packed_float3 *positions_data = get_position_for_write();
|
||||
float *radius_data = get_radius_for_write();
|
||||
|
||||
for (size_t i = 0; i < num_keys; i++) {
|
||||
for (size_t i = 0; i < num_keys_local; i++) {
|
||||
const float3 co = transform_point(&tfm, positions_data[i]);
|
||||
const float radius = radius_data[i] * scalar;
|
||||
|
||||
|
|
@ -503,15 +494,12 @@ void Hair::apply_transform(const Transform &tfm, const bool apply_to_motion)
|
|||
radius_data[i] = radius;
|
||||
}
|
||||
|
||||
tag_position_modified();
|
||||
tag_radius_modified();
|
||||
|
||||
if (apply_to_motion) {
|
||||
Attribute *curve_attr = attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
|
||||
if (curve_attr) {
|
||||
/* apply transform to motion curve keys */
|
||||
const size_t steps_size = curve_keys.size() * (motion_steps - 1);
|
||||
const size_t steps_size = num_keys_local * (motion_steps - 1);
|
||||
float4 *key_steps = curve_attr->data_for_write<float4>();
|
||||
|
||||
for (size_t i = 0; i < steps_size; i++) {
|
||||
|
|
@ -531,12 +519,12 @@ void Hair::pack_curves(Scene *scene,
|
|||
KernelCurve *curves,
|
||||
KernelCurveSegment *curve_segments)
|
||||
{
|
||||
const size_t positions_size = curve_keys.size();
|
||||
const size_t positions_size = num_keys();
|
||||
|
||||
/* pack curve keys */
|
||||
if (positions_size) {
|
||||
packed_float3 *keys_ptr = curve_keys.data();
|
||||
float *radius_ptr = curve_radius.data();
|
||||
const packed_float3 *keys_ptr = get_position();
|
||||
const float *radius_ptr = get_radius();
|
||||
|
||||
for (size_t i = 0; i < positions_size; i++) {
|
||||
curve_key_co[i] = make_float4(float3(keys_ptr[i]), radius_ptr[i]);
|
||||
|
|
|
|||
|
|
@ -89,16 +89,9 @@ class Hair : public Geometry {
|
|||
float4 r_keys[4]) const;
|
||||
};
|
||||
|
||||
NODE_SOCKET_API_ARRAY(array<packed_float3>, curve_keys)
|
||||
NODE_SOCKET_API_ARRAY(array<float>, curve_radius)
|
||||
NODE_SOCKET_API_ARRAY(array<int>, curve_first_key)
|
||||
NODE_SOCKET_API_ARRAY(array<int>, curve_shader)
|
||||
|
||||
const packed_float3 *get_position() const;
|
||||
packed_float3 *get_position_for_write();
|
||||
const float *get_radius() const;
|
||||
float *get_radius_for_write();
|
||||
|
||||
/* BVH */
|
||||
size_t curve_key_offset;
|
||||
size_t curve_segment_offset;
|
||||
|
|
@ -123,16 +116,13 @@ class Hair : public Geometry {
|
|||
{
|
||||
const int first = curve_first_key[i];
|
||||
const int next_first = (i + 1 < curve_first_key.size()) ? curve_first_key[i + 1] :
|
||||
curve_keys.size();
|
||||
int(num_keys());
|
||||
|
||||
Curve curve = {first, next_first - first};
|
||||
return curve;
|
||||
}
|
||||
|
||||
size_t num_keys() const
|
||||
{
|
||||
return curve_keys.size();
|
||||
}
|
||||
size_t num_keys() const;
|
||||
|
||||
size_t num_curves() const
|
||||
{
|
||||
|
|
@ -164,6 +154,9 @@ class Hair : public Geometry {
|
|||
bool need_shadow_transparency() const;
|
||||
bool need_update_shadow_transparency() const;
|
||||
bool update_shadow_transparency(Device *device, Scene *scene, Progress &progress);
|
||||
|
||||
private:
|
||||
void add_builtin_attributes();
|
||||
};
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue