45 float radius = 1.0f -
time;
49 radius =
powf(radius, 1.0f + shape);
51 radius =
powf(radius, 1.0f / (1.0f - shape));
53 return (radius * (root - tip)) + tip;
64 if (!(hair && b_mesh && b_ob && CData))
70 for (BL::Modifier &b_mod : b_ob->modifiers) {
71 if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) &&
72 (background ? b_mod.show_render() : b_mod.show_viewport())) {
73 BL::ParticleSystemModifier psmd((
const PointerRNA)b_mod.ptr);
77 if ((b_part.render_type() == BL::ParticleSettings::render_type_PATH) &&
78 (b_part.type() == BL::ParticleSettings::type_HAIR)) {
79 int shader =
clamp(b_part.material() - 1, 0, hair->get_used_shaders().size() - 1);
80 int display_step = background ? b_part.render_step() : b_part.display_step();
81 int totparts = b_psys.particles.length();
82 int totchild = background ? b_psys.child_particles.length() :
83 (int)((
float)b_psys.child_particles.length() *
84 (
float)b_part.display_percentage() / 100.0f);
85 int totcurves = totchild;
87 if (b_part.child_type() == 0 || totchild == 0)
88 totcurves += totparts;
93 int ren_step = (1 << display_step) + 1;
94 if (b_part.kink() == BL::ParticleSettings::kink_SPIRAL)
95 ren_step += b_part.kink_extra_steps();
101 float radius = b_part.radius_scale() * 0.5f;
109 if (!(b_part.child_type() == 0) && totchild != 0)
112 int num_add = (totparts + totchild - pa_no);
119 for (; pa_no < totparts + totchild; pa_no++) {
123 float curve_length = 0.0f;
126 for (
int step_no = 0; step_no < ren_step; step_no++) {
127 float3 co_world = prev_co_world;
128 b_psys.co_hair(*b_ob, pa_no, step_no, &co_world.
x);
131 const float step_length =
len(co_object - prev_co_object);
132 curve_length += step_length;
136 prev_co_object = co_object;
137 prev_co_world = co_world;
160 if (!(hair && b_mesh && b_ob && CData))
165 for (BL::Modifier &b_mod : b_ob->modifiers) {
166 if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) &&
167 (background ? b_mod.show_render() : b_mod.show_viewport())) {
168 BL::ParticleSystemModifier psmd((
const PointerRNA)b_mod.ptr);
172 if ((b_part.render_type() == BL::ParticleSettings::render_type_PATH) &&
173 (b_part.type() == BL::ParticleSettings::type_HAIR)) {
174 int totparts = b_psys.particles.length();
175 int totchild = background ? b_psys.child_particles.length() :
176 (int)((
float)b_psys.child_particles.length() *
177 (
float)b_part.display_percentage() / 100.0f);
178 int totcurves = totchild;
180 if (b_part.child_type() == 0 || totchild == 0)
181 totcurves += totparts;
187 if (!(b_part.child_type() == 0) && totchild != 0)
190 int num_add = (totparts + totchild - pa_no);
193 BL::ParticleSystem::particles_iterator b_pa;
194 b_psys.particles.begin(b_pa);
195 for (; pa_no < totparts + totchild; pa_no++) {
197 BL::Mesh::uv_layers_iterator
l;
198 b_mesh->uv_layers.begin(
l);
201 if (b_mesh->uv_layers.length())
202 b_psys.uv_on_emitter(psmd, *b_pa, pa_no, uv_num, &uv.
x);
205 if (pa_no < totparts && b_pa != b_psys.particles.end())
222 if (!(hair && b_mesh && b_ob && CData))
227 for (BL::Modifier &b_mod : b_ob->modifiers) {
228 if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) &&
229 (background ? b_mod.show_render() : b_mod.show_viewport())) {
230 BL::ParticleSystemModifier psmd((
const PointerRNA)b_mod.ptr);
234 if ((b_part.render_type() == BL::ParticleSettings::render_type_PATH) &&
235 (b_part.type() == BL::ParticleSettings::type_HAIR)) {
236 int totparts = b_psys.particles.length();
237 int totchild = background ? b_psys.child_particles.length() :
238 (int)((
float)b_psys.child_particles.length() *
239 (
float)b_part.display_percentage() / 100.0f);
240 int totcurves = totchild;
242 if (b_part.child_type() == 0 || totchild == 0)
243 totcurves += totparts;
249 if (!(b_part.child_type() == 0) && totchild != 0)
252 int num_add = (totparts + totchild - pa_no);
255 BL::ParticleSystem::particles_iterator b_pa;
256 b_psys.particles.begin(b_pa);
257 for (; pa_no < totparts + totchild; pa_no++) {
259 BL::Mesh::vertex_colors_iterator
l;
260 b_mesh->vertex_colors.begin(
l);
263 if (b_mesh->vertex_colors.length())
264 b_psys.mcol_on_emitter(psmd, *b_pa, pa_no, vcol_num, &vcol.x);
267 if (pa_no < totparts && b_pa != b_psys.particles.end())
296 curve < CData->psys_firstcurve[sys] + CData->
psys_curvenum[sys];
303 if (num_curves > 0) {
304 VLOG(1) <<
"Exporting curve segments for mesh " << hair->
name;
315 curve < CData->psys_firstcurve[sys] + CData->
psys_curvenum[sys];
317 size_t num_curve_keys = 0;
325 const float time = (curve_length > 0.0f) ? curve_time / curve_length : 0.0f;
339 if (attr_random !=
NULL) {
344 num_keys += num_curve_keys;
350 if ((hair->get_curve_keys().size() != num_keys) || (hair->
num_curves() != num_curves)) {
351 VLOG(1) <<
"Allocation failed, clearing data";
361 float time = (curve_length > 0.0f) ? curve_time / curve_length : 0.0f;
377 assert(step >= 0.0f);
378 assert(step <= 1.0f);
381 int curvekey = (int)
floorf(curve_key_f);
382 const float remainder = curve_key_f - curvekey;
383 if (remainder == 0.0f) {
386 int curvekey2 = curvekey + 1;
389 curvekey = curvekey2 - 1;
393 return lerp(mP, mP2, remainder);
402 const int num_keys = hair->get_curve_keys().size();
404 if (num_motion_keys != num_keys || !have_motion) {
406 if (num_motion_keys != num_keys) {
407 VLOG(1) <<
"Hair topology changed, removing attribute.";
410 VLOG(1) <<
"No motion, removing attribute.";
414 else if (motion_step > 0) {
415 VLOG(1) <<
"Filling in new motion vertex position for motion_step " << motion_step;
419 for (
int step = 0; step < motion_step; step++) {
420 float4 *mP = attr_mP->
data_float4() + step * num_keys;
422 for (
int key = 0; key < num_keys; key++) {
424 mP[key].w = hair->get_curve_radius()[key];
432 VLOG(1) <<
"Exporting curve motion segments for hair " << hair->
name <<
", motion step "
437 bool new_attribute =
false;
441 VLOG(1) <<
"Creating new motion vertex position attribute";
443 new_attribute =
true;
447 size_t numkeys = hair->get_curve_keys().size();
448 float4 *mP = attr_mP->
data_float4() + motion_step * numkeys;
449 bool have_motion =
false;
455 curve < CData->psys_firstcurve[sys] + CData->
psys_curvenum[sys];
458 int curve_key_end = (num_curves + 1 < (int)hair->get_curve_first_key().size() ?
459 hair->get_curve_first_key()[num_curves + 1] :
460 (int)hair->get_curve_keys().size());
461 const int num_center_curve_keys = curve_key_end - hair->get_curve_first_key()[num_curves];
462 const int is_num_keys_different = CData->
curve_keynum[
curve] - num_center_curve_keys;
464 if (!is_num_keys_different) {
468 if (i < hair->get_curve_keys().size()) {
475 curve_key.w = hair->get_curve_radius()[i];
476 if (
len_squared(mP[i] - curve_key) > 1e-5f * 1e-5f)
486 const float step_size = num_center_curve_keys > 1 ? 1.0f / (num_center_curve_keys - 1) :
488 for (
int step_index = 0; step_index < num_center_curve_keys; ++step_index) {
489 const float step = step_index * step_size;
507 bool BlenderSync::object_has_particle_hair(
BL::Object b_ob)
510 for (BL::Modifier &b_mod : b_ob.modifiers) {
511 if ((b_mod.type() == b_mod.type_PARTICLE_SYSTEM) &&
512 (preview ? b_mod.show_viewport() : b_mod.show_render())) {
513 BL::ParticleSystemModifier psmd((
const PointerRNA)b_mod.ptr);
517 if ((b_part.render_type() == BL::ParticleSettings::render_type_PATH) &&
518 (b_part.type() == BL::ParticleSettings::type_HAIR)) {
528 void BlenderSync::sync_particle_hair(
532 if (b_ob.mode() == b_ob.mode_PARTICLE_EDIT || b_ob.mode() == b_ob.mode_EDIT) {
558 for (
size_t i = 0; i < hair->
num_curves(); i++) {
560 generated[i] = co *
size - loc;
567 BL::Mesh::vertex_colors_iterator
l;
570 for (b_mesh.vertex_colors.begin(
l);
l != b_mesh.vertex_colors.end(); ++
l, vcol_num++) {
594 BL::Mesh::uv_layers_iterator
l;
597 for (b_mesh.uv_layers.begin(
l);
l != b_mesh.uv_layers.end(); ++
l, uv_num++) {
598 bool active_render =
l->active_render();
600 ustring name = ustring(
l->name().c_str());
627 #ifdef WITH_HAIR_NODES
628 static float4 hair_point_as_float4(BL::HairPoint b_point)
631 mP.w = b_point.radius();
635 static float4 interpolate_hair_points(
BL::Hair b_hair,
636 const int first_point_index,
637 const int num_points,
640 const float curve_t = step * (num_points - 1);
641 const int point_a =
clamp((
int)curve_t, 0, num_points - 1);
642 const int point_b =
min(point_a + 1, num_points - 1);
643 const float t = curve_t - (
float)point_a;
644 return lerp(hair_point_as_float4(b_hair.points[first_point_index + point_a]),
645 hair_point_as_float4(b_hair.points[first_point_index + point_b]),
665 const int num_keys = b_hair.points.length();
666 const int num_curves = b_hair.curves.length();
668 if (num_curves > 0) {
669 VLOG(1) <<
"Exporting curve segments for hair " << hair->
name;
678 const int first_point_index = b_curve.first_point_index();
679 const int num_points = b_curve.num_points();
683 if (attr_intercept) {
684 points_length.clear();
685 points_length.reserve(num_points);
689 for (
int i = 0; i < num_points; i++) {
690 BL::HairPoint b_point = b_hair.points[first_point_index + i];
693 const float radius = b_point.radius();
696 if (attr_intercept) {
699 points_length.push_back(
length);
706 if (attr_intercept) {
707 for (
int i = 0; i < num_points; i++) {
708 attr_intercept->
add((
length == 0.0f) ? 0.0f : points_length[i] /
length);
713 if (attr_random !=
NULL) {
718 const int shader_index = 0;
719 hair->
add_curve(first_point_index, shader_index);
723 static void export_hair_curves_motion(
Hair *hair,
BL::Hair b_hair,
int motion_step)
725 VLOG(1) <<
"Exporting curve motion segments for hair " << hair->
name <<
", motion step "
730 bool new_attribute =
false;
733 VLOG(1) <<
"Creating new motion vertex position attribute";
735 new_attribute =
true;
739 const int num_keys = hair->get_curve_keys().size();
740 float4 *mP = attr_mP->
data_float4() + motion_step * num_keys;
741 bool have_motion =
false;
742 int num_motion_keys = 0;
746 const int first_point_index = b_curve.first_point_index();
747 const int num_points = b_curve.num_points();
752 if (num_points ==
curve.num_keys) {
754 for (
int i = 0; i < num_points; i++) {
755 int point_index = first_point_index + i;
757 if (point_index < num_keys) {
758 mP[num_motion_keys] = hair_point_as_float4(b_hair.points[point_index]);
765 curve_key.w = hair->get_curve_radius()[i];
766 have_motion = !(mP[i] == curve_key);
774 const float step_size =
curve.num_keys > 1 ? 1.0f / (
curve.num_keys - 1) : 0.0f;
775 for (
int i = 0; i <
curve.num_keys; i++) {
776 const float step = i * step_size;
777 mP[num_motion_keys] = interpolate_hair_points(b_hair, first_point_index, num_points, step);
791 void BlenderSync::sync_hair(
Hair *hair,
BL::Object &b_ob,
bool motion,
int motion_step)
796 export_hair_curves_motion(hair, b_hair, motion_step);
799 export_hair_curves(scene, hair, b_hair);
803 void BlenderSync::sync_hair(
Hair *hair,
BL::Object &b_ob,
bool motion,
int motion_step)
819 new_hair.set_used_shaders(used_shaders);
821 if (view_layer.use_hair) {
822 if (b_ob.type() == BL::Object::type_HAIR) {
824 sync_hair(&new_hair, b_ob,
false);
833 sync_particle_hair(&new_hair, b_mesh, b_ob,
false);
843 if (socket.
name ==
"use_motion_blur" || socket.
name ==
"motion_steps" ||
844 socket.
name ==
"used_shaders") {
847 hair->
set_value(socket, new_hair, socket);
856 const bool rebuild = (hair->curve_keys_is_modified() || hair->curve_radius_is_modified());
861 void BlenderSync::sync_hair_motion(
BL::Depsgraph b_depsgraph,
873 if (b_ob.type() == BL::Object::type_HAIR) {
875 sync_hair(hair, b_ob,
true, motion_step);
882 sync_particle_hair(hair, b_mesh, b_ob,
true, motion_step);
typedef float(TangentPoint)[2]
int BKE_object_is_deform_modified(struct Scene *scene, struct Object *ob)
struct Depsgraph Depsgraph
struct HairCurve HairCurve
struct ParticleSettings ParticleSettings
struct ParticleSystem ParticleSystem
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
static bool ObtainCacheParticleData(Hair *hair, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background)
static float4 CurveSegmentMotionCV(ParticleCurveData *CData, int sys, int curve, int curvekey)
static void export_hair_motion_validate_attribute(Hair *hair, int motion_step, int num_motion_keys, bool have_motion)
static bool ObtainCacheParticleUV(Hair *hair, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int uv_num)
static bool ObtainCacheParticleVcol(Hair *hair, BL::Mesh *b_mesh, BL::Object *b_ob, ParticleCurveData *CData, bool background, int vcol_num)
static void ExportCurveSegments(Scene *scene, Hair *hair, ParticleCurveData *CData)
static float shaperadius(float shape, float root, float tip, float time)
static void ExportCurveSegmentsMotion(Hair *hair, ParticleCurveData *CData, int motion_step)
static float4 LerpCurveSegmentMotionCV(ParticleCurveData *CData, int sys, int curve, float step)
static float3 get_float3(const BL::Array< float, 2 > &array)
static BL::Mesh object_to_mesh(BL::BlendData &, BL::Object &object, BL::Depsgraph &, bool, Mesh::SubdivisionType subdivision_type)
static void free_object_to_mesh(BL::BlendData &, BL::Object &object, BL::Mesh &mesh)
static Transform get_transform(const BL::Array< float, 16 > &array)
static void mesh_texture_space(BL::Mesh &b_mesh, float3 &loc, float3 &size)
ATTR_WARN_UNUSED_RESULT const BMLoop * l
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Attribute * add(ustring name, TypeDesc type, AttributeElement element)
void update(AttributeSet &&new_attributes)
Attribute * find(ustring name) const
void remove(ustring name)
bool need_attribute(Scene *scene, AttributeStandard std)
void tag_update(Scene *scene, bool rebuild)
array< int > curve_firstkey
array< bool > psys_closetip
array< float > psys_tipradius
array< float > curve_length
array< float4 > curve_vcol
array< float > curvekey_time
array< float > psys_rootradius
array< int > psys_firstcurve
array< int > psys_curvenum
array< float > psys_shape
array< int > curve_keynum
array< float3 > curvekey_co
void reserve(size_t newcapacity)
void push_back_slow(const T &t)
#define CCL_NAMESPACE_END
#define make_float4(x, y, z, w)
void KERNEL_FUNCTION_FULL_NAME() shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int filter, int i, int offset, int sample)
@ ATTR_STD_CURVE_INTERCEPT
@ ATTR_STD_MOTION_VERTEX_POSITION
static float lerp(float t, float a, float b)
void add_curve(int first_key, int shader)
Curve get_curve(size_t i) const
void reserve_curves(int numcurves, int numkeys)
size_t num_curves() const
void copy_center_to_motion_step(const int motion_step)
void clear(bool preserve_shaders=false) override
void add_curve_key(float3 loc, float radius)
vector< SocketType, std::allocator< SocketType > > inputs
void set_value(const SocketType &input, const Node &other, const SocketType &other_input)
ccl_device float4 color_srgb_to_linear_v4(float4 c)
ccl_device_inline float hash_uint2_to_float(uint kx, uint ky)
ccl_device_inline float4 float3_to_float4(const float3 a)
ccl_device_inline int clamp(int a, int mn, int mx)
ccl_device_inline float2 zero_float2()
ccl_device_inline float3 zero_float3()
ccl_device_inline float len_squared(const float3 a)
static constexpr TypeDesc TypeRGBA(TypeDesc::FLOAT, TypeDesc::VEC4, TypeDesc::COLOR)
CCL_NAMESPACE_BEGIN static constexpr OIIO_NAMESPACE_USING TypeDesc TypeFloat2(TypeDesc::FLOAT, TypeDesc::VEC2)