From 934767cf7f51ae82224138de2ffcafe7bae2b8fa Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 29 Mar 2014 13:03:46 +0100 Subject: [PATCH] Cycles code refactor: change curve key to float4 for easier storage as attribute. --- intern/cycles/blender/blender_curves.cpp | 20 ++++++--- intern/cycles/blender/blender_mesh.cpp | 4 +- intern/cycles/bvh/bvh.cpp | 28 ++++--------- intern/cycles/bvh/bvh_build.cpp | 21 +--------- intern/cycles/bvh/bvh_split.cpp | 18 ++++---- intern/cycles/render/mesh.cpp | 53 ++++++++++++++++++------ intern/cycles/render/mesh.h | 9 ++-- intern/cycles/render/object.cpp | 11 +++-- intern/cycles/util/util_math.h | 19 ++++++--- 9 files changed, 101 insertions(+), 82 deletions(-) diff --git a/intern/cycles/blender/blender_curves.cpp b/intern/cycles/blender/blender_curves.cpp index 92c51b0aad3..4420a306e31 100644 --- a/intern/cycles/blender/blender_curves.cpp +++ b/intern/cycles/blender/blender_curves.cpp @@ -588,7 +588,7 @@ void ExportCurveSegments(Scene *scene, Mesh *mesh, ParticleCurveData *CData) float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time); if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)) - radius =0.0f; + radius = 0.0f; mesh->add_curve_key(ickey_loc, radius); if(attr_intercept) @@ -617,8 +617,8 @@ static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveDat /* export motion vectors for curve keys */ AttributeStandard std = (motion == -1)? ATTR_STD_MOTION_PRE: ATTR_STD_MOTION_POST; Attribute *attr_motion = mesh->curve_attributes.add(std); - float3 *data_motion = attr_motion->data_float3(); - float3 *current_motion = data_motion; + float4 *data_motion = attr_motion->data_float4(); + float4 *current_motion = data_motion; size_t size = mesh->curve_keys.size(); size_t i = 0; bool have_motion = false; @@ -633,12 +633,20 @@ static void ExportCurveSegmentsMotion(Scene *scene, Mesh *mesh, ParticleCurveDat for(int curvekey = CData->curve_firstkey[curve]; curvekey < CData->curve_firstkey[curve] + CData->curve_keynum[curve]; curvekey++) { if(i < mesh->curve_keys.size()) { - *current_motion = CData->curvekey_co[curvekey]; + float3 ickey_loc = CData->curvekey_co[curvekey]; + float time = CData->curvekey_time[curvekey]/CData->curve_length[curve]; + float radius = shaperadius(CData->psys_shape[sys], CData->psys_rootradius[sys], CData->psys_tipradius[sys], time); + + if(CData->psys_closetip[sys] && (curvekey == CData->curve_firstkey[curve] + CData->curve_keynum[curve] - 1)) + radius = 0.0f; + + *current_motion = float3_to_float4(ickey_loc); + current_motion->w = radius; /* unlike mesh coordinates, these tend to be slightly different * between frames due to particle transforms into/out of object * space, so we use an epsilon to detect actual changes */ - if(len_squared(*current_motion - mesh->curve_keys[i].co) > 1e-5f*1e-5f) + if(len_squared(*current_motion - mesh->curve_keys[i]) > 1e-5f*1e-5f) have_motion = true; current_motion++; @@ -876,7 +884,7 @@ void BlenderSync::sync_curves(Mesh *mesh, BL::Mesh b_mesh, BL::Object b_ob, int size_t i = 0; foreach(Mesh::Curve& curve, mesh->curves) { - float3 co = mesh->curve_keys[curve.first_key].co; + float3 co = float4_to_float3(mesh->curve_keys[curve.first_key]); generated[i++] = co*size - loc; } } diff --git a/intern/cycles/blender/blender_mesh.cpp b/intern/cycles/blender/blender_mesh.cpp index 0972cf6a939..b356537e971 100644 --- a/intern/cycles/blender/blender_mesh.cpp +++ b/intern/cycles/blender/blender_mesh.cpp @@ -481,7 +481,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri /* compares curve_keys rather than strands in order to handle quick hair * adjustsments in dynamic BVH - other methods could probably do this better*/ - vector oldcurve_keys = mesh->curve_keys; + vector oldcurve_keys = mesh->curve_keys; mesh->clear(); mesh->used_shaders = used_shaders; @@ -535,7 +535,7 @@ Mesh *BlenderSync::sync_mesh(BL::Object b_ob, bool object_updated, bool hide_tri if(oldcurve_keys.size() != mesh->curve_keys.size()) rebuild = true; else if(oldcurve_keys.size()) { - if(memcmp(&oldcurve_keys[0], &mesh->curve_keys[0], sizeof(Mesh::CurveKey)*oldcurve_keys.size()) != 0) + if(memcmp(&oldcurve_keys[0], &mesh->curve_keys[0], sizeof(float4)*oldcurve_keys.size()) != 0) rebuild = true; } diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index 0d46638c82d..c0d70e0bc61 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -283,8 +283,8 @@ void BVH::pack_curve_segment(int idx, float4 woop[3]) int segment = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[idx]); int k0 = mesh->curves[tidx].first_key + segment; int k1 = mesh->curves[tidx].first_key + segment + 1; - float3 v0 = mesh->curve_keys[k0].co; - float3 v1 = mesh->curve_keys[k1].co; + float3 v0 = float4_to_float3(mesh->curve_keys[k0]); + float3 v1 = float4_to_float3(mesh->curve_keys[k1]); float3 d0 = v1 - v0; float l = len(d0); @@ -632,34 +632,20 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility if(pack.prim_type[prim] & PRIMITIVE_ALL_CURVE) { /* curves */ int str_offset = (params.top_level)? mesh->curve_offset: 0; - int k0 = mesh->curves[pidx - str_offset].first_key + PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]); - int k1 = k0 + 1; + const Mesh::Curve& curve = mesh->curves[pidx - str_offset]; + int k = PRIMITIVE_UNPACK_SEGMENT(pack.prim_type[prim]); - float3 p[4]; - p[0] = mesh->curve_keys[max(k0 - 1,mesh->curves[pidx - str_offset].first_key)].co; - p[1] = mesh->curve_keys[k0].co; - p[2] = mesh->curve_keys[k1].co; - p[3] = mesh->curve_keys[min(k1 + 1,mesh->curves[pidx - str_offset].first_key + mesh->curves[pidx - str_offset].num_keys - 1)].co; - float3 lower; - float3 upper; - curvebounds(&lower.x, &upper.x, p, 0); - curvebounds(&lower.y, &upper.y, p, 1); - curvebounds(&lower.z, &upper.z, p, 2); - float mr = max(mesh->curve_keys[k0].radius,mesh->curve_keys[k1].radius); - bbox.grow(lower, mr); - bbox.grow(upper, mr); + curve.bounds_grow(k, &mesh->curve_keys[0], bbox); visibility |= PATH_RAY_CURVE; } else { /* triangles */ int tri_offset = (params.top_level)? mesh->tri_offset: 0; - const int *vidx = mesh->triangles[pidx - tri_offset].v; + const Mesh::Triangle& triangle = mesh->triangles[pidx - tri_offset]; const float3 *vpos = &mesh->verts[0]; - bbox.grow(vpos[vidx[0]]); - bbox.grow(vpos[vidx[1]]); - bbox.grow(vpos[vidx[2]]); + triangle.bounds_grow(vpos, bbox); } } diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index aa8ba36f891..ef48c1edc63 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -75,10 +75,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, BoundBox bounds = BoundBox::empty; PrimitiveType type = PRIMITIVE_TRIANGLE; - for(int k = 0; k < 3; k++) { - float3 co = mesh->verts[t.v[k]]; - bounds.grow(co); - } + t.bounds_grow(&mesh->verts[0], bounds); if(bounds.valid()) { references.push_back(BVHReference(bounds, j, i, type)); @@ -93,21 +90,7 @@ void BVHBuild::add_reference_mesh(BoundBox& root, BoundBox& center, Mesh *mesh, for(int k = 0; k < curve.num_keys - 1; k++) { BoundBox bounds = BoundBox::empty; - - float3 co[4]; - co[0] = mesh->curve_keys[max(curve.first_key + k - 1,curve.first_key)].co; - co[1] = mesh->curve_keys[curve.first_key + k].co; - co[2] = mesh->curve_keys[curve.first_key + k + 1].co; - co[3] = mesh->curve_keys[min(curve.first_key + k + 2, curve.first_key + curve.num_keys - 1)].co; - - float3 lower; - float3 upper; - curvebounds(&lower.x, &upper.x, co, 0); - curvebounds(&lower.y, &upper.y, co, 1); - curvebounds(&lower.z, &upper.z, co, 2); - float mr = max(mesh->curve_keys[curve.first_key + k].radius, mesh->curve_keys[curve.first_key + k + 1].radius); - bounds.grow(lower, mr); - bounds.grow(upper, mr); + curve.bounds_grow(k, &mesh->curve_keys[0], bounds); if(bounds.valid()) { int packed_type = PRIMITIVE_PACK_SEGMENT(type, k); diff --git a/intern/cycles/bvh/bvh_split.cpp b/intern/cycles/bvh/bvh_split.cpp index 864626da134..e293e8f4c3f 100644 --- a/intern/cycles/bvh/bvh_split.cpp +++ b/intern/cycles/bvh/bvh_split.cpp @@ -284,28 +284,28 @@ void BVHSpatialSplit::split_reference(BVHBuild *builder, BVHReference& left, BVH /* curve split: NOTE - Currently ignores curve width and needs to be fixed.*/ const int k0 = mesh->curves[ref.prim_index()].first_key + PRIMITIVE_UNPACK_SEGMENT(ref.prim_type()); const int k1 = k0 + 1; - const float3* v0 = &mesh->curve_keys[k0].co; - const float3* v1 = &mesh->curve_keys[k1].co; + const float3 v0 = float4_to_float3(mesh->curve_keys[k0]); + const float3 v1 = float4_to_float3(mesh->curve_keys[k1]); - float v0p = (*v0)[dim]; - float v1p = (*v1)[dim]; + float v0p = v0[dim]; + float v1p = v1[dim]; /* insert vertex to the boxes it belongs to. */ if(v0p <= pos) - left_bounds.grow(*v0); + left_bounds.grow(v0); if(v0p >= pos) - right_bounds.grow(*v0); + right_bounds.grow(v0); if(v1p <= pos) - left_bounds.grow(*v1); + left_bounds.grow(v1); if(v1p >= pos) - right_bounds.grow(*v1); + right_bounds.grow(v1); /* edge intersects the plane => insert intersection to both boxes. */ if((v0p < pos && v1p > pos) || (v0p > pos && v1p < pos)) { - float3 t = lerp(*v0, *v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f)); + float3 t = lerp(v0, v1, clamp((pos - v0p) / (v1p - v0p), 0.0f, 1.0f)); left_bounds.grow(t); right_bounds.grow(t); } diff --git a/intern/cycles/render/mesh.cpp b/intern/cycles/render/mesh.cpp index 717ebb42f5c..c6ddb00e76b 100644 --- a/intern/cycles/render/mesh.cpp +++ b/intern/cycles/render/mesh.cpp @@ -18,6 +18,7 @@ #include "bvh_build.h" #include "camera.h" +#include "curves.h" #include "device.h" #include "shader.h" #include "light.h" @@ -34,6 +35,39 @@ CCL_NAMESPACE_BEGIN +/* Triangle */ + +void Mesh::Triangle::bounds_grow(const float3 *verts, BoundBox& bounds) const +{ + bounds.grow(verts[v[0]]); + bounds.grow(verts[v[1]]); + bounds.grow(verts[v[2]]); +} + +/* Curve */ + +void Mesh::Curve::bounds_grow(const int k, const float4 *curve_keys, BoundBox& bounds) const +{ + float3 P[4]; + + P[0] = float4_to_float3(curve_keys[max(first_key + k - 1,first_key)]); + P[1] = float4_to_float3(curve_keys[first_key + k]); + P[2] = float4_to_float3(curve_keys[first_key + k + 1]); + P[3] = float4_to_float3(curve_keys[min(first_key + k + 2, first_key + num_keys - 1)]); + + float3 lower; + float3 upper; + + curvebounds(&lower.x, &upper.x, P, 0); + curvebounds(&lower.y, &upper.y, P, 1); + curvebounds(&lower.z, &upper.z, P, 2); + + float mr = max(curve_keys[first_key + k].w, curve_keys[first_key + k + 1].w); + + bounds.grow(lower, mr); + bounds.grow(upper, mr); +} + /* Mesh */ Mesh::Mesh() @@ -125,9 +159,8 @@ void Mesh::add_triangle(int v0, int v1, int v2, int shader_, bool smooth_) void Mesh::add_curve_key(float3 co, float radius) { - CurveKey key; - key.co = co; - key.radius = radius; + float4 key = float3_to_float4(co); + key.w = radius; curve_keys.push_back(key); } @@ -153,7 +186,7 @@ void Mesh::compute_bounds() bnds.grow(verts[i]); for(size_t i = 0; i < curve_keys_size; i++) - bnds.grow(curve_keys[i].co, curve_keys[i].radius); + bnds.grow(float4_to_float3(curve_keys[i]), curve_keys[i].w); if(!bnds.valid()) { bnds = BoundBox::empty; @@ -163,7 +196,7 @@ void Mesh::compute_bounds() bnds.grow_safe(verts[i]); for(size_t i = 0; i < curve_keys_size; i++) - bnds.grow_safe(curve_keys[i].co, curve_keys[i].radius); + bnds.grow_safe(float4_to_float3(curve_keys[i]), curve_keys[i].w); } } @@ -337,18 +370,14 @@ void Mesh::pack_verts(float4 *tri_verts, float4 *tri_vindex, size_t vert_offset) void Mesh::pack_curves(Scene *scene, float4 *curve_key_co, float4 *curve_data, size_t curvekey_offset) { size_t curve_keys_size = curve_keys.size(); - CurveKey *keys_ptr = NULL; + float4 *keys_ptr = NULL; /* pack curve keys */ if(curve_keys_size) { keys_ptr = &curve_keys[0]; - for(size_t i = 0; i < curve_keys_size; i++) { - float3 p = keys_ptr[i].co; - float radius = keys_ptr[i].radius; - - curve_key_co[i] = make_float4(p.x, p.y, p.z, radius); - } + for(size_t i = 0; i < curve_keys_size; i++) + curve_key_co[i] = keys_ptr[i]; } /* pack curve segments */ diff --git a/intern/cycles/render/mesh.h b/intern/cycles/render/mesh.h index 9c59aca4c72..5ae8f1f6033 100644 --- a/intern/cycles/render/mesh.h +++ b/intern/cycles/render/mesh.h @@ -46,6 +46,8 @@ public: /* Mesh Triangle */ struct Triangle { int v[3]; + + void bounds_grow(const float3 *verts, BoundBox& bounds) const; }; /* Mesh Curve */ @@ -55,11 +57,8 @@ public: uint shader; int num_segments() { return num_keys - 1; } - }; - struct CurveKey { - float3 co; - float radius; + void bounds_grow(const int k, const float4 *curve_keys, BoundBox& bounds) const; }; /* Displacement */ @@ -77,7 +76,7 @@ public: vector shader; vector smooth; - vector curve_keys; + vector curve_keys; /* co + radius */ vector curves; vector used_shaders; diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp index 0a89642fc4a..362b4762b74 100644 --- a/intern/cycles/render/object.cpp +++ b/intern/cycles/render/object.cpp @@ -86,19 +86,24 @@ 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); + /* apply to mesh vertices */ for(size_t i = 0; i < mesh->verts.size(); i++) mesh->verts[i] = transform_point(&tfm, mesh->verts[i]); + /* apply to curve keys */ for(size_t i = 0; i < mesh->curve_keys.size(); i++) { - mesh->curve_keys[i].co = transform_point(&tfm, mesh->curve_keys[i].co); + float3 co = transform_point(&tfm, float4_to_float3(mesh->curve_keys[i])); + float radius = mesh->curve_keys[i].w * scalar; + + mesh->curve_keys[i] = float3_to_float4(co); /* scale for strand radius - only correct for uniform transforms*/ - mesh->curve_keys[i].radius *= scalar; + mesh->curve_keys[i].w *= radius; } /* store matrix to transform later. when accessing these as attributes we diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index 2e73639d2bb..dc58b93bd5d 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -469,6 +469,15 @@ ccl_device_inline float dot(const float3 a, const float3 b) #endif } +ccl_device_inline float dot(const float4 a, const float4 b) +{ +#if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__) + return _mm_cvtss_f32(_mm_dp_ps(a, b, 0xFF)); +#else + return (a.x*b.x + a.y*b.y) + (a.z*b.z + a.w*b.w); +#endif +} + ccl_device_inline float3 cross(const float3 a, const float3 b) { float3 r = make_float3(a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x); @@ -493,6 +502,11 @@ ccl_device_inline float len_squared(const float3 a) #ifndef __KERNEL_OPENCL__ +ccl_device_inline float len_squared(const float4 a) +{ + return dot(a, a); +} + ccl_device_inline float3 normalize(const float3 a) { #if defined(__KERNEL_SSE41__) && defined(__KERNEL_SSE__) @@ -812,11 +826,6 @@ ccl_device_inline float average(const float4& a) return reduce_add(a) * 0.25f; } -ccl_device_inline float dot(const float4& a, const float4& b) -{ - return reduce_add(a * b); -} - ccl_device_inline float len(const float4 a) { return sqrtf(dot(a, a));