Cycles: add support for curve deformation motion blur.
This commit is contained in:
@@ -238,7 +238,6 @@ void BVH::refit(Progress& progress)
|
||||
|
||||
void BVH::pack_triangle(int idx, float4 woop[3])
|
||||
{
|
||||
/* create Woop triangle */
|
||||
int tob = pack.prim_object[idx];
|
||||
const Mesh *mesh = objects[tob]->mesh;
|
||||
|
||||
@@ -642,6 +641,20 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility
|
||||
curve.bounds_grow(k, &mesh->curve_keys[0], bbox);
|
||||
|
||||
visibility |= PATH_RAY_CURVE;
|
||||
|
||||
/* motion curves */
|
||||
if(mesh->use_motion_blur) {
|
||||
Attribute *attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
|
||||
if(attr) {
|
||||
size_t mesh_size = mesh->curve_keys.size();
|
||||
size_t steps = mesh->motion_steps - 1;
|
||||
float4 *key_steps = attr->data_float4();
|
||||
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
curve.bounds_grow(k, key_steps + i*mesh_size, bbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* triangles */
|
||||
|
||||
@@ -101,6 +101,11 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
|
||||
}
|
||||
}
|
||||
|
||||
Attribute *curve_attr_mP = NULL;
|
||||
|
||||
if(mesh->has_motion_blur())
|
||||
curve_attr_mP = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
|
||||
for(uint j = 0; j < mesh->curves.size(); j++) {
|
||||
Mesh::Curve curve = mesh->curves[j];
|
||||
PrimitiveType type = PRIMITIVE_CURVE;
|
||||
@@ -109,6 +114,18 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh,
|
||||
BoundBox bounds = BoundBox::empty;
|
||||
curve.bounds_grow(k, &mesh->curve_keys[0], bounds);
|
||||
|
||||
/* motion curve */
|
||||
if(curve_attr_mP) {
|
||||
size_t mesh_size = mesh->curve_keys.size();
|
||||
size_t steps = mesh->motion_steps - 1;
|
||||
float4 *key_steps = curve_attr_mP->data_float4();
|
||||
|
||||
for (size_t i = 0; i < steps; i++)
|
||||
curve.bounds_grow(k, key_steps + i*mesh_size, bounds);
|
||||
|
||||
type = PRIMITIVE_MOTION_CURVE;
|
||||
}
|
||||
|
||||
if(bounds.valid()) {
|
||||
int packed_type = PRIMITIVE_PACK_SEGMENT(type, k);
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ set(SRC_GEOM_HEADERS
|
||||
geom/geom_bvh_subsurface.h
|
||||
geom/geom_bvh_traversal.h
|
||||
geom/geom_curve.h
|
||||
geom/geom_motion_curve.h
|
||||
geom/geom_motion_triangle.h
|
||||
geom/geom_object.h
|
||||
geom/geom_triangle.h
|
||||
|
||||
@@ -41,9 +41,10 @@
|
||||
#endif
|
||||
|
||||
#include "geom_object.h"
|
||||
#include "geom_curve.h"
|
||||
#include "geom_triangle.h"
|
||||
#include "geom_motion_triangle.h"
|
||||
#include "geom_motion_curve.h"
|
||||
#include "geom_curve.h"
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
@@ -261,7 +261,8 @@ ccl_device bool BVH_FUNCTION_NAME
|
||||
break;
|
||||
}
|
||||
#if FEATURE(BVH_HAIR)
|
||||
case PRIMITIVE_CURVE: {
|
||||
case PRIMITIVE_CURVE:
|
||||
case PRIMITIVE_MOTION_CURVE: {
|
||||
#if FEATURE(BVH_HAIR_MINIMUM_WIDTH)
|
||||
if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE)
|
||||
hit = bvh_cardinal_curve_intersect(kg, isect, P, idir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax);
|
||||
|
||||
@@ -103,9 +103,17 @@ ccl_device float curve_thickness(KernelGlobals *kg, ShaderData *sd)
|
||||
int k0 = __float_as_int(curvedata.x) + PRIMITIVE_UNPACK_SEGMENT(sd->type);
|
||||
int k1 = k0 + 1;
|
||||
|
||||
float4 P1 = kernel_tex_fetch(__curve_keys, k0);
|
||||
float4 P2 = kernel_tex_fetch(__curve_keys, k1);
|
||||
r = (P2.w - P1.w) * sd->u + P1.w;
|
||||
float4 P_curve[2];
|
||||
|
||||
if(sd->type & PRIMITIVE_CURVE) {
|
||||
P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
|
||||
P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
|
||||
}
|
||||
else {
|
||||
motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
|
||||
}
|
||||
|
||||
r = (P_curve[1].w - P_curve[0].w) * sd->u + P_curve[0].w;
|
||||
}
|
||||
|
||||
return r*2.0f;
|
||||
@@ -226,10 +234,16 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
|
||||
|
||||
__m128 P_curve[4];
|
||||
|
||||
P_curve[0] = _mm_load_ps(&kg->__curve_keys.data[ka].x);
|
||||
P_curve[1] = _mm_load_ps(&kg->__curve_keys.data[k0].x);
|
||||
P_curve[2] = _mm_load_ps(&kg->__curve_keys.data[k1].x);
|
||||
P_curve[3] = _mm_load_ps(&kg->__curve_keys.data[kb].x);
|
||||
if(type & PRIMITIVE_CURVE) {
|
||||
P_curve[0] = _mm_load_ps(&kg->__curve_keys.data[ka].x);
|
||||
P_curve[1] = _mm_load_ps(&kg->__curve_keys.data[k0].x);
|
||||
P_curve[2] = _mm_load_ps(&kg->__curve_keys.data[k1].x);
|
||||
P_curve[3] = _mm_load_ps(&kg->__curve_keys.data[kb].x);
|
||||
}
|
||||
else {
|
||||
int fobject = (object == ~0)? kernel_tex_fetch(__prim_object, curveAddr): object;
|
||||
motion_cardinal_curve_keys(kg, fobject, prim, time, ka, k0, k1, kb, (float4*)&P_curve);
|
||||
}
|
||||
|
||||
__m128 rd_sgn = set_sign_bit<0, 1, 1, 1>(broadcast<0>(rd_ss));
|
||||
__m128 mul_zxxy = _mm_mul_ps(shuffle<2, 0, 0, 1>(vdir), rd_sgn);
|
||||
@@ -287,10 +301,16 @@ ccl_device_inline bool bvh_cardinal_curve_intersect(KernelGlobals *kg, Intersect
|
||||
|
||||
float4 P_curve[4];
|
||||
|
||||
P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
|
||||
P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
|
||||
P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
|
||||
P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
|
||||
if(type & PRIMITIVE_CURVE) {
|
||||
P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
|
||||
P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
|
||||
P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
|
||||
P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
|
||||
}
|
||||
else {
|
||||
int fobject = (object == ~0)? kernel_tex_fetch(__prim_object, curveAddr): object;
|
||||
motion_cardinal_curve_keys(kg, fobject, prim, time, ka, k0, k1, kb, P_curve);
|
||||
}
|
||||
|
||||
float3 p0 = transform_point(&htfm, float4_to_float3(P_curve[0]) - P);
|
||||
float3 p1 = transform_point(&htfm, float4_to_float3(P_curve[1]) - P);
|
||||
@@ -593,8 +613,14 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
|
||||
#ifndef __KERNEL_SSE2__
|
||||
float4 P_curve[2];
|
||||
|
||||
P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
|
||||
P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
|
||||
if(type & PRIMITIVE_CURVE) {
|
||||
P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
|
||||
P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
|
||||
}
|
||||
else {
|
||||
int fobject = (object == ~0)? kernel_tex_fetch(__prim_object, curveAddr): object;
|
||||
motion_curve_keys(kg, fobject, prim, time, k0, k1, P_curve);
|
||||
}
|
||||
|
||||
float or1 = P_curve[0].w;
|
||||
float or2 = P_curve[1].w;
|
||||
@@ -620,14 +646,23 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
|
||||
float sphere_b_tmp = dot3(dir, sphere_dif1);
|
||||
float3 sphere_dif2 = sphere_dif1 - sphere_b_tmp * dir;
|
||||
#else
|
||||
const __m128 p1 = _mm_load_ps(&kg->__curve_keys.data[k0].x);
|
||||
const __m128 p2 = _mm_load_ps(&kg->__curve_keys.data[k1].x);
|
||||
const __m128 or12 = shuffle<3, 3, 3, 3>(p1, p2);
|
||||
__m128 P_curve[2];
|
||||
|
||||
if(type & PRIMITIVE_CURVE) {
|
||||
P_curve[0] = _mm_load_ps(&kg->__curve_keys.data[k0].x);
|
||||
P_curve[1] = _mm_load_ps(&kg->__curve_keys.data[k1].x);
|
||||
}
|
||||
else {
|
||||
int fobject = (object == ~0)? kernel_tex_fetch(__prim_object, curveAddr): object;
|
||||
motion_curve_keys(kg, fobject, prim, time, k0, k1, (float4*)&P_curve);
|
||||
}
|
||||
|
||||
const __m128 or12 = shuffle<3, 3, 3, 3>(P_curve[0], P_curve[1]);
|
||||
|
||||
__m128 r12 = or12;
|
||||
const __m128 vP = load_m128(P);
|
||||
const __m128 dif = _mm_sub_ps(vP, p1);
|
||||
const __m128 dif_second = _mm_sub_ps(vP, p2);
|
||||
const __m128 dif = _mm_sub_ps(vP, P_curve[0]);
|
||||
const __m128 dif_second = _mm_sub_ps(vP, P_curve[1]);
|
||||
if(difl != 0.0f) {
|
||||
const __m128 len1_sq = len3_squared_splat(dif);
|
||||
const __m128 len2_sq = len3_squared_splat(dif_second);
|
||||
@@ -639,7 +674,7 @@ ccl_device_inline bool bvh_curve_intersect(KernelGlobals *kg, Intersection *isec
|
||||
float r1 = _mm_cvtss_f32(r12), r2 = _mm_cvtss_f32(broadcast<2>(r12));
|
||||
|
||||
const __m128 dir = _mm_div_ps(_mm_set1_ps(1.0f), load_m128(idir));
|
||||
const __m128 p21_diff = _mm_sub_ps(p2, p1);
|
||||
const __m128 p21_diff = _mm_sub_ps(P_curve[1], P_curve[0]);
|
||||
const __m128 sphere_dif1 = _mm_mul_ps(_mm_add_ps(dif, dif_second), _mm_set1_ps(0.5f));
|
||||
const __m128 sphere_b_tmp = dot3_splat(dir, sphere_dif1);
|
||||
const __m128 sphere_dif2 = fnma(sphere_b_tmp, dir, sphere_dif1);
|
||||
@@ -854,10 +889,15 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
|
||||
|
||||
float4 P_curve[4];
|
||||
|
||||
P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
|
||||
P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
|
||||
P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
|
||||
P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
|
||||
if(sd->type & PRIMITIVE_CURVE) {
|
||||
P_curve[0] = kernel_tex_fetch(__curve_keys, ka);
|
||||
P_curve[1] = kernel_tex_fetch(__curve_keys, k0);
|
||||
P_curve[2] = kernel_tex_fetch(__curve_keys, k1);
|
||||
P_curve[3] = kernel_tex_fetch(__curve_keys, kb);
|
||||
}
|
||||
else {
|
||||
motion_cardinal_curve_keys(kg, sd->object, sd->prim, sd->time, ka, k0, k1, kb, P_curve);
|
||||
}
|
||||
|
||||
float l = 1.0f;
|
||||
tg = normalize_len(float4_to_float3(P_curve[2] - P_curve[1]), &l);
|
||||
@@ -893,8 +933,13 @@ ccl_device_inline float3 bvh_curve_refine(KernelGlobals *kg, ShaderData *sd, con
|
||||
else {
|
||||
float4 P_curve[2];
|
||||
|
||||
P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
|
||||
P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
|
||||
if(sd->type & PRIMITIVE_CURVE) {
|
||||
P_curve[0]= kernel_tex_fetch(__curve_keys, k0);
|
||||
P_curve[1]= kernel_tex_fetch(__curve_keys, k1);
|
||||
}
|
||||
else {
|
||||
motion_curve_keys(kg, sd->object, sd->prim, sd->time, k0, k1, P_curve);
|
||||
}
|
||||
|
||||
float l = 1.0f;
|
||||
tg = normalize_len(float4_to_float3(P_curve[1] - P_curve[0]), &l);
|
||||
|
||||
139
intern/cycles/kernel/geom/geom_motion_curve.h
Normal file
139
intern/cycles/kernel/geom/geom_motion_curve.h
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#ifdef __HAIR__
|
||||
|
||||
/* todo: find a better (faster) solution for this, maybe store offset per object */
|
||||
ccl_device_inline int find_attribute_curve_motion(KernelGlobals *kg, int object, uint id, AttributeElement *elem)
|
||||
{
|
||||
uint attr_offset = object*kernel_data.bvh.attributes_map_stride + ATTR_PRIM_CURVE;
|
||||
uint4 attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
||||
|
||||
while(attr_map.x != id) {
|
||||
attr_offset += ATTR_PRIM_TYPES;
|
||||
attr_map = kernel_tex_fetch(__attributes_map, attr_offset);
|
||||
}
|
||||
|
||||
*elem = (AttributeElement)attr_map.y;
|
||||
|
||||
/* return result */
|
||||
return (attr_map.y == ATTR_ELEMENT_NONE) ? (int)ATTR_STD_NOT_FOUND : (int)attr_map.z;
|
||||
}
|
||||
|
||||
ccl_device_inline void motion_curve_keys_for_step(KernelGlobals *kg, int offset, int numkeys, int numsteps, int step, int k0, int k1, float4 keys[2])
|
||||
{
|
||||
if(step == numsteps) {
|
||||
/* center step: regular vertex location */
|
||||
keys[0] = kernel_tex_fetch(__curve_keys, k0);
|
||||
keys[1] = kernel_tex_fetch(__curve_keys, k1);
|
||||
}
|
||||
else {
|
||||
/* center step not store in this array */
|
||||
if(step > numsteps)
|
||||
step--;
|
||||
|
||||
offset += step*numkeys;
|
||||
|
||||
keys[0] = kernel_tex_fetch(__attributes_float3, offset + k0);
|
||||
keys[1] = kernel_tex_fetch(__attributes_float3, offset + k1);
|
||||
}
|
||||
}
|
||||
|
||||
/* return 2 curve key locations */
|
||||
ccl_device_inline void motion_curve_keys(KernelGlobals *kg, int object, int prim, float time, int k0, int k1, float4 keys[2])
|
||||
{
|
||||
/* get motion info */
|
||||
int numsteps, numkeys;
|
||||
object_motion_info(kg, object, &numsteps, NULL, &numkeys);
|
||||
|
||||
/* figure out which steps we need to fetch and their interpolation factor */
|
||||
int maxstep = numsteps*2;
|
||||
int step = min((int)(time*maxstep), maxstep-1);
|
||||
float t = time*maxstep - step;
|
||||
|
||||
/* find attribute */
|
||||
AttributeElement elem;
|
||||
int offset = find_attribute_curve_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
|
||||
kernel_assert(offset != ATTR_STD_NOT_FOUND);
|
||||
|
||||
/* fetch key coordinates */
|
||||
float4 next_keys[2];
|
||||
|
||||
motion_curve_keys_for_step(kg, offset, numkeys, numsteps, step, k0, k1, keys);
|
||||
motion_curve_keys_for_step(kg, offset, numkeys, numsteps, step+1, k0, k1, next_keys);
|
||||
|
||||
/* interpolate between steps */
|
||||
keys[0] = (1.0f - t)*keys[0] + t*next_keys[0];
|
||||
keys[1] = (1.0f - t)*keys[1] + t*next_keys[1];
|
||||
}
|
||||
|
||||
ccl_device_inline void motion_cardinal_curve_keys_for_step(KernelGlobals *kg, int offset, int numkeys, int numsteps, int step, int k0, int k1, int k2, int k3, float4 keys[4])
|
||||
{
|
||||
if(step == numsteps) {
|
||||
/* center step: regular vertex location */
|
||||
keys[0] = kernel_tex_fetch(__curve_keys, k0);
|
||||
keys[1] = kernel_tex_fetch(__curve_keys, k1);
|
||||
keys[2] = kernel_tex_fetch(__curve_keys, k2);
|
||||
keys[3] = kernel_tex_fetch(__curve_keys, k3);
|
||||
}
|
||||
else {
|
||||
/* center step not store in this array */
|
||||
if(step > numsteps)
|
||||
step--;
|
||||
|
||||
offset += step*numkeys;
|
||||
|
||||
keys[0] = kernel_tex_fetch(__attributes_float3, offset + k0);
|
||||
keys[1] = kernel_tex_fetch(__attributes_float3, offset + k1);
|
||||
keys[2] = kernel_tex_fetch(__attributes_float3, offset + k2);
|
||||
keys[3] = kernel_tex_fetch(__attributes_float3, offset + k3);
|
||||
}
|
||||
}
|
||||
|
||||
/* return 2 curve key locations */
|
||||
ccl_device_inline void motion_cardinal_curve_keys(KernelGlobals *kg, int object, int prim, float time, int k0, int k1, int k2, int k3, float4 keys[4])
|
||||
{
|
||||
/* get motion info */
|
||||
int numsteps, numkeys;
|
||||
object_motion_info(kg, object, &numsteps, NULL, &numkeys);
|
||||
|
||||
/* figure out which steps we need to fetch and their interpolation factor */
|
||||
int maxstep = numsteps*2;
|
||||
int step = min((int)(time*maxstep), maxstep-1);
|
||||
float t = time*maxstep - step;
|
||||
|
||||
/* find attribute */
|
||||
AttributeElement elem;
|
||||
int offset = find_attribute_curve_motion(kg, object, ATTR_STD_MOTION_VERTEX_POSITION, &elem);
|
||||
kernel_assert(offset != ATTR_STD_NOT_FOUND);
|
||||
|
||||
/* fetch key coordinates */
|
||||
float4 next_keys[4];
|
||||
|
||||
motion_cardinal_curve_keys_for_step(kg, offset, numkeys, numsteps, step, k0, k1, k2, k3, keys);
|
||||
motion_cardinal_curve_keys_for_step(kg, offset, numkeys, numsteps, step+1, k0, k1, k2, k3, next_keys);
|
||||
|
||||
/* interpolate between steps */
|
||||
keys[0] = (1.0f - t)*keys[0] + t*next_keys[0];
|
||||
keys[1] = (1.0f - t)*keys[1] + t*next_keys[1];
|
||||
keys[2] = (1.0f - t)*keys[2] + t*next_keys[2];
|
||||
keys[3] = (1.0f - t)*keys[3] + t*next_keys[3];
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_END
|
||||
|
||||
@@ -199,7 +199,7 @@ void Mesh::compute_bounds()
|
||||
}
|
||||
|
||||
Attribute *curve_attr = curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
if (curve_attr) {
|
||||
if(use_motion_blur && curve_attr) {
|
||||
size_t steps_size = curve_keys.size() * (motion_steps - 1);
|
||||
float3 *key_steps = curve_attr->data_float3();
|
||||
|
||||
@@ -225,7 +225,7 @@ void Mesh::compute_bounds()
|
||||
bnds.grow_safe(vert_steps[i]);
|
||||
}
|
||||
|
||||
if (curve_attr) {
|
||||
if (use_motion_blur && curve_attr) {
|
||||
size_t steps_size = curve_keys.size() * (motion_steps - 1);
|
||||
float3 *key_steps = curve_attr->data_float3();
|
||||
|
||||
@@ -536,7 +536,9 @@ void Mesh::tag_update(Scene *scene, bool rebuild)
|
||||
|
||||
bool Mesh::has_motion_blur() const
|
||||
{
|
||||
return (use_motion_blur && attributes.find(ATTR_STD_MOTION_VERTEX_POSITION));
|
||||
return (use_motion_blur &&
|
||||
(attributes.find(ATTR_STD_MOTION_VERTEX_POSITION) ||
|
||||
curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION)));
|
||||
}
|
||||
|
||||
/* Mesh Manager */
|
||||
|
||||
@@ -84,11 +84,6 @@ void Object::apply_transform()
|
||||
if(!mesh || tfm == transform_identity())
|
||||
return;
|
||||
|
||||
float3 c0 = transform_get_column(&tfm, 0);
|
||||
float3 c1 = transform_get_column(&tfm, 1);
|
||||
float3 c2 = transform_get_column(&tfm, 2);
|
||||
float scalar = pow(fabsf(dot(cross(c0, c1), c2)), 1.0f/3.0f);
|
||||
|
||||
/* triangles */
|
||||
if(mesh->verts.size()) {
|
||||
/* store matrix to transform later. when accessing these as attributes we
|
||||
@@ -121,23 +116,40 @@ void Object::apply_transform()
|
||||
}
|
||||
}
|
||||
|
||||
/* apply to curve keys */
|
||||
for(size_t i = 0; i < mesh->curve_keys.size(); i++) {
|
||||
float3 co = transform_point(&tfm, float4_to_float3(mesh->curve_keys[i]));
|
||||
float radius = mesh->curve_keys[i].w * scalar;
|
||||
/* curves */
|
||||
if(mesh->curve_keys.size()) {
|
||||
/* compute uniform scale */
|
||||
float3 c0 = transform_get_column(&tfm, 0);
|
||||
float3 c1 = transform_get_column(&tfm, 1);
|
||||
float3 c2 = transform_get_column(&tfm, 2);
|
||||
float scalar = pow(fabsf(dot(cross(c0, c1), c2)), 1.0f/3.0f);
|
||||
|
||||
mesh->curve_keys[i] = float3_to_float4(co);
|
||||
/* scale for strand radius - only correct for uniform transforms*/
|
||||
mesh->curve_keys[i].w *= radius;
|
||||
}
|
||||
/* apply transform to curve keys */
|
||||
for(size_t i = 0; i < mesh->curve_keys.size(); i++) {
|
||||
float3 co = transform_point(&tfm, float4_to_float3(mesh->curve_keys[i]));
|
||||
float radius = mesh->curve_keys[i].w * scalar;
|
||||
|
||||
Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
if (curve_attr) {
|
||||
size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
|
||||
float3 *vert_steps = curve_attr->data_float3();
|
||||
/* scale for curve radius is only correct for uniform scale */
|
||||
mesh->curve_keys[i] = float3_to_float4(co);
|
||||
mesh->curve_keys[i].w = radius;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < steps_size; i++)
|
||||
vert_steps[i] = transform_point(&tfm, vert_steps[i]);
|
||||
Attribute *curve_attr = mesh->curve_attributes.find(ATTR_STD_MOTION_VERTEX_POSITION);
|
||||
|
||||
if (curve_attr) {
|
||||
/* apply transform to motion curve keys */
|
||||
size_t steps_size = mesh->curve_keys.size() * (mesh->motion_steps - 1);
|
||||
float4 *key_steps = curve_attr->data_float4();
|
||||
|
||||
for (size_t i = 0; i < steps_size; i++) {
|
||||
float3 co = transform_point(&tfm, float4_to_float3(key_steps[i]));
|
||||
float radius = key_steps[i].w * scalar;
|
||||
|
||||
/* scale for curve radius is only correct for uniform scale */
|
||||
key_steps[i] = float3_to_float4(co);
|
||||
key_steps[i].w = radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* we keep normals pointing in same direction on negative scale, notify
|
||||
|
||||
Reference in New Issue
Block a user