diff options
author | Ines Almeida <britalmeida@gmail.com> | 2015-01-13 14:04:25 +0300 |
---|---|---|
committer | Ines Almeida <britalmeida@gmail.com> | 2015-01-13 14:04:25 +0300 |
commit | cb61c5aeee94af943b0306550daef45c2018126a (patch) | |
tree | dbb2a9b5600bc53de35162e79091772bff1b6f8b | |
parent | d7cabe7d6f4519856969137df415692e16a5372d (diff) | |
parent | 117edbbf881be1764db852d9805c523590a19f84 (diff) |
Merge branch 'master' into soc-2014-bgesoc-2014-bge
55 files changed, 996 insertions, 408 deletions
diff --git a/intern/cycles/bvh/bvh.cpp b/intern/cycles/bvh/bvh.cpp index ac2762b80bd..5fc4ddb3a0e 100644 --- a/intern/cycles/bvh/bvh.cpp +++ b/intern/cycles/bvh/bvh.cpp @@ -504,12 +504,20 @@ RegularBVH::RegularBVH(const BVHParams& params_, const vector<Object*>& objects_ void RegularBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) { - if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) + if(leaf->num_triangles() == 1 && pack.prim_index[leaf->m_lo] == -1) { /* object */ - pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0, leaf->m_visibility, leaf->m_visibility); - else - /* triangle */ - pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, leaf->m_lo, leaf->m_hi, leaf->m_visibility, leaf->m_visibility); + pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, ~(leaf->m_lo), 0, + leaf->m_visibility, leaf->m_visibility); + } + else { + int prim_type = leaf->num_triangles() ? pack.prim_type[leaf->m_lo] : 0; + /* Triangle/curve primitive leaf. */ + pack_node(e.idx, leaf->m_bounds, leaf->m_bounds, + leaf->m_lo, leaf->m_hi, + leaf->m_visibility, + prim_type); + } + } void RegularBVH::pack_inner(const BVHStackEntry& e, const BVHStackEntry& e0, const BVHStackEntry& e1) @@ -657,7 +665,7 @@ void RegularBVH::refit_node(int idx, bool leaf, BoundBox& bbox, uint& visibility visibility |= ob->visibility; } - pack_node(idx, bbox, bbox, c0, c1, visibility, visibility); + pack_node(idx, bbox, bbox, c0, c1, visibility, data[3].w); } else { /* refit inner node, set bbox from children */ @@ -700,6 +708,9 @@ void QBVH::pack_leaf(const BVHStackEntry& e, const LeafNode *leaf) data[6].y = __int_as_float(leaf->m_hi); } data[6].z = __uint_as_float(leaf->m_visibility); + if(leaf->num_triangles() != 0) { + data[6].w = __uint_as_float(pack.prim_type[leaf->m_lo]); + } memcpy(&pack.nodes[e.idx * BVH_QNODE_SIZE], data, sizeof(float4)*BVH_QNODE_SIZE); } diff --git a/intern/cycles/bvh/bvh_build.cpp b/intern/cycles/bvh/bvh_build.cpp index 5547229a910..da263c4945e 100644 --- a/intern/cycles/bvh/bvh_build.cpp +++ b/intern/cycles/bvh/bvh_build.cpp @@ -34,6 +34,21 @@ CCL_NAMESPACE_BEGIN +#if !defined(__KERNEL_SSE2__) +/* TODO(sergey): Move to some generic header so all code + * can use bitscan on non-SSE processors. + */ +ccl_device_inline int bitscan(int value) +{ + assert(value != 0); + int bit = 0; + while (value >>= 1) { + ++bit; + } + return bit; +} +#endif + /* BVH Build Task */ class BVHBuildTask : public Task { @@ -449,61 +464,119 @@ BVHNode *BVHBuild::create_object_leaf_nodes(const BVHReference *ref, int start, } } -BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) +BVHNode *BVHBuild::create_primitive_leaf_node(const int *p_type, + const int *p_index, + const int *p_object, + const BoundBox& bounds, + uint visibility, + int start, + int num) { - vector<int>& p_type = prim_type; - vector<int>& p_index = prim_index; - vector<int>& p_object = prim_object; - BoundBox bounds = BoundBox::empty; - int num = 0, ob_num = 0; - uint visibility = 0; + for(int i = 0; i < num; ++i) { + if(start + i == prim_index.size()) { + assert(params.use_spatial_split); + prim_type.push_back(p_type[i]); + prim_index.push_back(p_index[i]); + prim_object.push_back(p_object[i]); + } + else { + prim_type[start + i] = p_type[i]; + prim_index[start + i] = p_index[i]; + prim_object[start + i] = p_object[i]; + } + } + return new LeafNode(bounds, visibility, start, start + num); +} +BVHNode* BVHBuild::create_leaf_node(const BVHRange& range) +{ +#define MAX_LEAF_SIZE 8 + int p_num[PRIMITIVE_NUM_TOTAL] = {0}; + int p_type[PRIMITIVE_NUM_TOTAL][MAX_LEAF_SIZE]; + int p_index[PRIMITIVE_NUM_TOTAL][MAX_LEAF_SIZE]; + int p_object[PRIMITIVE_NUM_TOTAL][MAX_LEAF_SIZE]; + uint visibility[PRIMITIVE_NUM_TOTAL] = {0}; + /* NOTE: Keep initializtion in sync with actual number of primitives. */ + BoundBox bounds[PRIMITIVE_NUM_TOTAL] = {BoundBox::empty, + BoundBox::empty, + BoundBox::empty, + BoundBox::empty}; + int ob_num = 0; + + /* Fill in per-type type/index array. */ for(int i = 0; i < range.size(); i++) { BVHReference& ref = references[range.start() + i]; - if(ref.prim_index() != -1) { - if(range.start() + num == prim_index.size()) { - assert(params.use_spatial_split); - - p_type.push_back(ref.prim_type()); - p_index.push_back(ref.prim_index()); - p_object.push_back(ref.prim_object()); - } - else { - p_type[range.start() + num] = ref.prim_type(); - p_index[range.start() + num] = ref.prim_index(); - p_object[range.start() + num] = ref.prim_object(); - } - - bounds.grow(ref.bounds()); - visibility |= objects[ref.prim_object()]->visibility; - num++; + int type_index = bitscan(ref.prim_type() & PRIMITIVE_ALL); + int idx = p_num[type_index]; + p_type[type_index][idx] = ref.prim_type(); + p_index[type_index][idx] = ref.prim_index(); + p_object[type_index][idx] = ref.prim_object(); + ++p_num[type_index]; + + bounds[type_index].grow(ref.bounds()); + visibility[type_index] |= objects[ref.prim_object()]->visibility; } else { - if(ob_num < i) + if(ob_num < i) { references[range.start() + ob_num] = ref; + } ob_num++; } } - BVHNode *leaf = NULL; - - if(num > 0) { - leaf = new LeafNode(bounds, visibility, range.start(), range.start() + num); + /* Create leaf nodes for every existing primitive. */ + BVHNode *leaves[PRIMITIVE_NUM_TOTAL + 1] = {NULL}; + int num_leaves = 0; + int start = range.start(); + for(int i = 0; i < PRIMITIVE_NUM_TOTAL; ++i) { + if(p_num[i] != 0) { + leaves[num_leaves] = create_primitive_leaf_node(p_type[i], + p_index[i], + p_object[i], + bounds[i], + visibility[i], + start, + p_num[i]); + ++num_leaves; + start += p_num[i]; + } + } - if(num == range.size()) - return leaf; + /* Create leaf node for object. */ + if(num_leaves == 0 || ob_num) { + /* Only create object leaf nodes if there are objects or no other + * nodes created. + */ + const BVHReference *ref = (ob_num)? &references[range.start()]: NULL; + leaves[num_leaves] = create_object_leaf_nodes(ref, start, ob_num); + ++num_leaves; } - /* while there may be multiple triangles in a leaf, for object primitives - * we want there to be the only one, so we keep splitting */ - const BVHReference *ref = (ob_num)? &references[range.start()]: NULL; - BVHNode *oleaf = create_object_leaf_nodes(ref, range.start() + num, ob_num); - - if(leaf) - return new InnerNode(range.bounds(), leaf, oleaf); - else - return oleaf; + if(num_leaves == 1) { + /* Simplest case: single leaf, just return it. + * In all the rest cases we'll be creating intermediate inner node with + * an appropriate bounding box. + */ + return leaves[0]; + } + else if(num_leaves == 2) { + return new InnerNode(range.bounds(), leaves[0], leaves[1]); + } + else if(num_leaves == 3) { + BoundBox inner_bounds = merge(bounds[1], bounds[2]); + BVHNode *inner = new InnerNode(inner_bounds, leaves[1], leaves[2]); + return new InnerNode(range.bounds(), leaves[0], inner); + } else /*if(num_leaves == 4)*/ { + /* Shpuld be doing more branches if more primitive types added. */ + assert(num_leaves == 4); + BoundBox inner_bounds_a = merge(bounds[0], bounds[1]); + BoundBox inner_bounds_b = merge(bounds[2], bounds[3]); + BVHNode *inner_a = new InnerNode(inner_bounds_a, leaves[0], leaves[1]); + BVHNode *inner_b = new InnerNode(inner_bounds_b, leaves[2], leaves[3]); + return new InnerNode(range.bounds(), inner_a, inner_b); + } +#undef AMX_LEAF_SIZE } /* Tree Rotations */ @@ -588,4 +661,3 @@ void BVHBuild::rotate(BVHNode *node, int max_depth) } CCL_NAMESPACE_END - diff --git a/intern/cycles/bvh/bvh_build.h b/intern/cycles/bvh/bvh_build.h index a6b9916de9b..294c5a1758d 100644 --- a/intern/cycles/bvh/bvh_build.h +++ b/intern/cycles/bvh/bvh_build.h @@ -70,6 +70,15 @@ protected: BVHNode *create_leaf_node(const BVHRange& range); BVHNode *create_object_leaf_nodes(const BVHReference *ref, int start, int num); + /* Leaf node type splitting. */ + BVHNode *create_primitive_leaf_node(const int *p_type, + const int *p_index, + const int *p_object, + const BoundBox& bounds, + uint visibility, + int start, + int nun); + bool range_within_max_leaf_size(const BVHRange& range); /* threads */ @@ -116,4 +125,3 @@ protected: CCL_NAMESPACE_END #endif /* __BVH_BUILD_H__ */ - diff --git a/intern/cycles/bvh/bvh_params.h b/intern/cycles/bvh/bvh_params.h index 43c2d9b2683..3fa6ebd75af 100644 --- a/intern/cycles/bvh/bvh_params.h +++ b/intern/cycles/bvh/bvh_params.h @@ -49,8 +49,6 @@ public: /* QBVH */ int use_qbvh; - int pad; - /* fixed parameters */ enum { MAX_DEPTH = 64, @@ -75,7 +73,6 @@ public: top_level = false; use_cache = false; use_qbvh = false; - pad = false; } /* SAH costs */ diff --git a/intern/cycles/kernel/geom/geom_bvh_shadow.h b/intern/cycles/kernel/geom/geom_bvh_shadow.h index 6dafd2c9fdc..193f49074a3 100644 --- a/intern/cycles/kernel/geom/geom_bvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_bvh_shadow.h @@ -206,7 +206,9 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, #if BVH_FEATURE(BVH_INSTANCING) if(primAddr >= 0) { #endif - int primAddr2 = __float_as_int(leaf.y); + const int primAddr2 = __float_as_int(leaf.y); + const uint type = __float_as_int(leaf.w); + const uint p_type = type & PRIMITIVE_ALL; /* pop */ nodeAddr = traversalStack[stackPtr]; @@ -214,14 +216,15 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, /* primitive intersection */ while(primAddr < primAddr2) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + bool hit; - uint type = kernel_tex_fetch(__prim_type, primAddr); /* todo: specialized intersect functions which don't fill in * isect unless needed and check SD_HAS_TRANSPARENT_SHADOW? * might give a few % performance improvement */ - switch(type & PRIMITIVE_ALL) { + switch(p_type) { case PRIMITIVE_TRIANGLE: { hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr); break; diff --git a/intern/cycles/kernel/geom/geom_bvh_subsurface.h b/intern/cycles/kernel/geom/geom_bvh_subsurface.h index ea9d7c07a72..290297ef5c5 100644 --- a/intern/cycles/kernel/geom/geom_bvh_subsurface.h +++ b/intern/cycles/kernel/geom/geom_bvh_subsurface.h @@ -193,37 +193,43 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, #if BVH_FEATURE(BVH_INSTANCING) if(primAddr >= 0) { #endif - int primAddr2 = __float_as_int(leaf.y); + const int primAddr2 = __float_as_int(leaf.y); + const uint type = __float_as_int(leaf.w); /* pop */ nodeAddr = traversalStack[stackPtr]; --stackPtr; /* primitive intersection */ - for(; primAddr < primAddr2; primAddr++) { - /* only primitives from the same object */ - uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; - - if(tri_object != subsurface_object) - continue; - - /* intersect ray against primitive */ - uint type = kernel_tex_fetch(__prim_type, primAddr); - - switch(type & PRIMITIVE_ALL) { - case PRIMITIVE_TRIANGLE: { + switch(type & PRIMITIVE_ALL) { + case PRIMITIVE_TRIANGLE: { + /* intersect ray against primitive */ + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* only primitives from the same object */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + if(tri_object != subsurface_object) + continue; triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits); - break; } + break; + } #if BVH_FEATURE(BVH_MOTION) - case PRIMITIVE_MOTION_TRIANGLE: { + case PRIMITIVE_MOTION_TRIANGLE: { + /* intersect ray against primitive */ + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* only primitives from the same object */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + if(tri_object != subsurface_object) + continue; motion_triangle_intersect_subsurface(kg, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits); - break; } + break; + } #endif - default: { - break; - } + default: { + break; } } } diff --git a/intern/cycles/kernel/geom/geom_bvh_traversal.h b/intern/cycles/kernel/geom/geom_bvh_traversal.h index b948ab8f5e4..0298e687de2 100644 --- a/intern/cycles/kernel/geom/geom_bvh_traversal.h +++ b/intern/cycles/kernel/geom/geom_bvh_traversal.h @@ -254,62 +254,85 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, #if BVH_FEATURE(BVH_INSTANCING) if(primAddr >= 0) { #endif - int primAddr2 = __float_as_int(leaf.y); + const int primAddr2 = __float_as_int(leaf.y); + const uint type = __float_as_int(leaf.w); /* pop */ nodeAddr = traversalStack[stackPtr]; --stackPtr; /* primitive intersection */ - while(primAddr < primAddr2) { - bool hit; - uint type = kernel_tex_fetch(__prim_type, primAddr); - - switch(type & PRIMITIVE_ALL) { - case PRIMITIVE_TRIANGLE: { - hit = triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr); - break; + switch(type & PRIMITIVE_ALL) { + case PRIMITIVE_TRIANGLE: { + for(; primAddr < primAddr2; primAddr++) { +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps++; +#endif + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + if(triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr)) { + /* shadow ray early termination */ +#if defined(__KERNEL_SSE2__) + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; + tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); +#else + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; +#endif + } } + break; + } #if BVH_FEATURE(BVH_MOTION) - case PRIMITIVE_MOTION_TRIANGLE: { - hit = motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr); - break; - } + case PRIMITIVE_MOTION_TRIANGLE: { + for(; primAddr < primAddr2; primAddr++) { +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps++; #endif -#if BVH_FEATURE(BVH_HAIR) - case PRIMITIVE_CURVE: - case PRIMITIVE_MOTION_CURVE: { - if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) - hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax); - else - hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax); - break; - } + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) { + /* shadow ray early termination */ +#if defined(__KERNEL_SSE2__) + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; + tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); +#else + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; #endif - default: { - hit = false; - break; + } } + break; } - +#endif /* BVH_FEATURE(BVH_MOTION) */ +#if BVH_FEATURE(BVH_HAIR) + case PRIMITIVE_CURVE: + case PRIMITIVE_MOTION_CURVE: { + for(; primAddr < primAddr2; primAddr++) { #if defined(__KERNEL_DEBUG__) - isect->num_traversal_steps++; + isect->num_traversal_steps++; #endif - - /* shadow ray early termination */ + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + bool hit; + if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) + hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax); + else + hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax); + if(hit) { + /* shadow ray early termination */ #if defined(__KERNEL_SSE2__) - if(hit) { - if(visibility == PATH_RAY_SHADOW_OPAQUE) - return true; - - tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); - } + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; + tsplat = ssef(0.0f, 0.0f, -isect->t, -isect->t); #else - if(hit && visibility == PATH_RAY_SHADOW_OPAQUE) - return true; + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; #endif - - primAddr++; + } + } + break; + } +#endif /* BVH_FEATURE(BVH_HAIR) */ } } #if BVH_FEATURE(BVH_INSTANCING) diff --git a/intern/cycles/kernel/geom/geom_bvh_volume.h b/intern/cycles/kernel/geom/geom_bvh_volume.h index f1f2e6d1f46..0862812a170 100644 --- a/intern/cycles/kernel/geom/geom_bvh_volume.h +++ b/intern/cycles/kernel/geom/geom_bvh_volume.h @@ -194,49 +194,67 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(BVH)(KernelGlobals *kg, #if BVH_FEATURE(BVH_INSTANCING) if(primAddr >= 0) { #endif - int primAddr2 = __float_as_int(leaf.y); + const int primAddr2 = __float_as_int(leaf.y); + const uint type = __float_as_int(leaf.w); /* pop */ nodeAddr = traversalStack[stackPtr]; --stackPtr; /* primitive intersection */ - for(; primAddr < primAddr2; primAddr++) { - /* only primitives from volume object */ - uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; - int object_flag = kernel_tex_fetch(__object_flag, tri_object); - - if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { - continue; - } - - /* intersect ray against primitive */ - uint type = kernel_tex_fetch(__prim_type, primAddr); - - switch(type & PRIMITIVE_ALL) { - case PRIMITIVE_TRIANGLE: { + switch(type & PRIMITIVE_ALL) { + case PRIMITIVE_TRIANGLE: { + /* intersect ray against primitive */ + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* only primitives from volume object */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr); - break; } + break; + } #if BVH_FEATURE(BVH_MOTION) - case PRIMITIVE_MOTION_TRIANGLE: { + case PRIMITIVE_MOTION_TRIANGLE: { + /* intersect ray against primitive */ + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* only primitives from volume object */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr); - break; } + break; + } #endif #if BVH_FEATURE(BVH_HAIR) - case PRIMITIVE_CURVE: - case PRIMITIVE_MOTION_CURVE: { - if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) + case PRIMITIVE_CURVE: + case PRIMITIVE_MOTION_CURVE: { + /* intersect ray against primitive */ + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* only primitives from volume object */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } + if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); else bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); - break; } + break; + } #endif - default: { - break; - } + default: { + break; } } } diff --git a/intern/cycles/kernel/geom/geom_qbvh_shadow.h b/intern/cycles/kernel/geom/geom_qbvh_shadow.h index e493a3f51bd..e77e220c919 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_shadow.h +++ b/intern/cycles/kernel/geom/geom_qbvh_shadow.h @@ -216,6 +216,8 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, if(primAddr >= 0) { #endif int primAddr2 = __float_as_int(leaf.y); + const uint type = __float_as_int(leaf.w); + const uint p_type = type & PRIMITIVE_ALL; /* Pop. */ nodeAddr = traversalStack[stackPtr].addr; @@ -223,14 +225,15 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, /* Primitive intersection. */ while(primAddr < primAddr2) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + bool hit; - uint type = kernel_tex_fetch(__prim_type, primAddr); /* todo: specialized intersect functions which don't fill in * isect unless needed and check SD_HAS_TRANSPARENT_SHADOW? * might give a few % performance improvement */ - switch(type & PRIMITIVE_ALL) { + switch(p_type) { case PRIMITIVE_TRIANGLE: { hit = triangle_intersect(kg, &isect_precalc, isect_array, P, dir, PATH_RAY_SHADOW, object, primAddr); break; diff --git a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h index 0154772988f..ef1754e711c 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_subsurface.h +++ b/intern/cycles/kernel/geom/geom_qbvh_subsurface.h @@ -203,37 +203,44 @@ ccl_device uint BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, if(primAddr >= 0) { #endif int primAddr2 = __float_as_int(leaf.y); + const uint type = __float_as_int(leaf.w); /* Pop. */ nodeAddr = traversalStack[stackPtr].addr; --stackPtr; /* Primitive intersection. */ - for(; primAddr < primAddr2; primAddr++) { - /* only primitives from the same object */ - uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; - - if(tri_object != subsurface_object) - continue; - - /* Intersect ray against primitive */ - uint type = kernel_tex_fetch(__prim_type, primAddr); - - switch(type & PRIMITIVE_ALL) { - case PRIMITIVE_TRIANGLE: { + switch(type & PRIMITIVE_ALL) { + case PRIMITIVE_TRIANGLE: { + /* Intersect ray against primitive, */ + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* Only primitives from the same object. */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + if(tri_object != subsurface_object) { + continue; + } triangle_intersect_subsurface(kg, &isect_precalc, isect_array, P, dir, object, primAddr, isect_t, &num_hits, lcg_state, max_hits); - break; } + break; + } #if BVH_FEATURE(BVH_MOTION) - case PRIMITIVE_MOTION_TRIANGLE: { + case PRIMITIVE_MOTION_TRIANGLE: { + /* Intersect ray against primitive. */ + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* Only primitives from the same object. */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + if(tri_object != subsurface_object) { + continue; + } motion_triangle_intersect_subsurface(kg, isect_array, P, dir, ray->time, object, primAddr, isect_t, &num_hits, lcg_state, max_hits); - break; - } -#endif - default: { - break; } + break; } +#endif + default: + break; } } #if BVH_FEATURE(BVH_INSTANCING) diff --git a/intern/cycles/kernel/geom/geom_qbvh_traversal.h b/intern/cycles/kernel/geom/geom_qbvh_traversal.h index 8d81f475848..64da51360de 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_traversal.h +++ b/intern/cycles/kernel/geom/geom_qbvh_traversal.h @@ -275,6 +275,7 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, if(primAddr >= 0) { #endif int primAddr2 = __float_as_int(leaf.y); + const uint type = __float_as_int(leaf.w); /* Pop. */ nodeAddr = traversalStack[stackPtr].addr; @@ -282,49 +283,62 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, --stackPtr; /* Primitive intersection. */ - while(primAddr < primAddr2) { - bool hit; - uint type = kernel_tex_fetch(__prim_type, primAddr); - - switch(type & PRIMITIVE_ALL) { - case PRIMITIVE_TRIANGLE: { - hit = triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr); - break; + switch(type & PRIMITIVE_ALL) { + case PRIMITIVE_TRIANGLE: { + for(; primAddr < primAddr2; primAddr++) { +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps++; +#endif + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + if(triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr)) { + tfar = ssef(isect->t); + /* Shadow ray early termination. */ + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; + } } + break; + } #if BVH_FEATURE(BVH_MOTION) - case PRIMITIVE_MOTION_TRIANGLE: { - hit = motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr); - break; - } + case PRIMITIVE_MOTION_TRIANGLE: { + for(; primAddr < primAddr2; primAddr++) { +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps++; #endif + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + if(motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr)) { + tfar = ssef(isect->t); + /* Shadow ray early termination. */ + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; + } + } + break; + } +#endif /* BVH_FEATURE(BVH_MOTION) */ #if BVH_FEATURE(BVH_HAIR) - case PRIMITIVE_CURVE: - case PRIMITIVE_MOTION_CURVE: { - if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) + case PRIMITIVE_CURVE: + case PRIMITIVE_MOTION_CURVE: { + for(; primAddr < primAddr2; primAddr++) { +#if defined(__KERNEL_DEBUG__) + isect->num_traversal_steps++; +#endif + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + bool hit; + if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) hit = bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax); else hit = bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, lcg_state, difl, extmax); - break; + if(hit) { + tfar = ssef(isect->t); + /* Shadow ray early termination. */ + if(visibility == PATH_RAY_SHADOW_OPAQUE) + return true; + } } -#endif - default: { - hit = false; - break; - } - } - -#if defined(__KERNEL_DEBUG__) - isect->num_traversal_steps++; -#endif - - /* Shadow ray early termination. */ - if(hit) { - tfar = ssef(isect->t); - if(visibility == PATH_RAY_SHADOW_OPAQUE) - return true; + break; } - - primAddr++; +#endif /* BVH_FEATURE(BVH_HAIR) */ } } #if BVH_FEATURE(BVH_INSTANCING) diff --git a/intern/cycles/kernel/geom/geom_qbvh_volume.h b/intern/cycles/kernel/geom/geom_qbvh_volume.h index 9e6e7552b3f..a2a8d1a20ab 100644 --- a/intern/cycles/kernel/geom/geom_qbvh_volume.h +++ b/intern/cycles/kernel/geom/geom_qbvh_volume.h @@ -209,49 +209,65 @@ ccl_device bool BVH_FUNCTION_FULL_NAME(QBVH)(KernelGlobals *kg, if(primAddr >= 0) { #endif int primAddr2 = __float_as_int(leaf.y); + const uint type = __float_as_int(leaf.w); + const uint p_type = type & PRIMITIVE_ALL; /* Pop. */ nodeAddr = traversalStack[stackPtr].addr; --stackPtr; /* Primitive intersection. */ - for(; primAddr < primAddr2; primAddr++) { - /* Only primitives from volume object. */ - uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; - int object_flag = kernel_tex_fetch(__object_flag, tri_object); - - if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { - continue; - } - - /* Intersect ray against primitive. */ - uint type = kernel_tex_fetch(__prim_type, primAddr); - - switch(type & PRIMITIVE_ALL) { - case PRIMITIVE_TRIANGLE: { + switch(p_type) { + case PRIMITIVE_TRIANGLE: { + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* Only primitives from volume object. */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } + /* Intersect ray against primitive. */ triangle_intersect(kg, &isect_precalc, isect, P, dir, visibility, object, primAddr); - break; } + break; + } #if BVH_FEATURE(BVH_MOTION) - case PRIMITIVE_MOTION_TRIANGLE: { + case PRIMITIVE_MOTION_TRIANGLE: { + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* Only primitives from volume object. */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } + /* Intersect ray against primitive. */ motion_triangle_intersect(kg, isect, P, dir, ray->time, visibility, object, primAddr); - break; } + break; + } #endif #if BVH_FEATURE(BVH_HAIR) - case PRIMITIVE_CURVE: - case PRIMITIVE_MOTION_CURVE: { - if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) + case PRIMITIVE_CURVE: + case PRIMITIVE_MOTION_CURVE: { + for(; primAddr < primAddr2; primAddr++) { + kernel_assert(kernel_tex_fetch(__prim_type, primAddr) == type); + /* Only primitives from volume object. */ + uint tri_object = (object == OBJECT_NONE)? kernel_tex_fetch(__prim_object, primAddr): object; + int object_flag = kernel_tex_fetch(__object_flag, tri_object); + if((object_flag & SD_OBJECT_HAS_VOLUME) == 0) { + continue; + } + /* Intersect ray against primitive. */ + if(kernel_data.curve.curveflags & CURVE_KN_INTERPOLATE) bvh_cardinal_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); else bvh_curve_intersect(kg, isect, P, dir, visibility, object, primAddr, ray->time, type, NULL, 0, 0); - break; - } -#endif - default: { - break; } + break; } +#endif } } #if BVH_FEATURE(BVH_INSTANCING) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index aff9a001061..82619b3f854 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -481,7 +481,12 @@ typedef enum PrimitiveType { PRIMITIVE_ALL_TRIANGLE = (PRIMITIVE_TRIANGLE|PRIMITIVE_MOTION_TRIANGLE), PRIMITIVE_ALL_CURVE = (PRIMITIVE_CURVE|PRIMITIVE_MOTION_CURVE), PRIMITIVE_ALL_MOTION = (PRIMITIVE_MOTION_TRIANGLE|PRIMITIVE_MOTION_CURVE), - PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE) + PRIMITIVE_ALL = (PRIMITIVE_ALL_TRIANGLE|PRIMITIVE_ALL_CURVE), + + /* Total number of different primitives. + * NOTE: This is an actual value, not a bitflag. + */ + PRIMITIVE_NUM_TOTAL = 4, } PrimitiveType; #define PRIMITIVE_PACK_SEGMENT(type, segment) ((segment << 16) | type) diff --git a/intern/ghost/intern/GHOST_ContextCGL.mm b/intern/ghost/intern/GHOST_ContextCGL.mm index 37fd4a36ea4..0b290c617a5 100644 --- a/intern/ghost/intern/GHOST_ContextCGL.mm +++ b/intern/ghost/intern/GHOST_ContextCGL.mm @@ -75,9 +75,10 @@ GHOST_ContextCGL::GHOST_ContextCGL( GHOST_ContextCGL::~GHOST_ContextCGL() { if (m_openGLContext != nil) { - if (m_openGLContext == [NSOpenGLContext currentContext]) + if (m_openGLContext == [NSOpenGLContext currentContext]) { [NSOpenGLContext clearCurrentContext]; [m_openGLView clearGLContext]; + } if (m_openGLContext != s_sharedOpenGLContext || s_sharedCount == 1) { assert(s_sharedCount > 0); diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index 1d2c730ecab..1cf9a3bb36e 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -25,7 +25,7 @@ roles: # Default color space sequencer is working in default_sequencer: sRGB - # Color spaces for color picking and exture painting (not internally supported yet) + # Color spaces for color picking and texture painting (not internally supported yet) color_picking: Raw texture_paint: Raw diff --git a/release/scripts/modules/bpy_extras/view3d_utils.py b/release/scripts/modules/bpy_extras/view3d_utils.py index b25024fca9b..ec4a395f1e1 100644 --- a/release/scripts/modules/bpy_extras/view3d_utils.py +++ b/release/scripts/modules/bpy_extras/view3d_utils.py @@ -63,10 +63,18 @@ def region_2d_to_vector_3d(region, rv3d, coord): return view_vector -def region_2d_to_origin_3d(region, rv3d, coord): +def region_2d_to_origin_3d(region, rv3d, coord, clamp=None): """ Return the 3d view origin from the region relative 2d coords. + .. note:: + + Orthographic views have a less obvious origin, the far clip is used to define the viewport near/far extents. + Since far clip can be a very large value, the result may give with numeric precision issues. + + To avoid this problem, you can optionally clamp the far clip to a smaller value + based on the data you're operating on. + :arg region: region of the 3D viewport, typically bpy.context.region. :type region: :class:`bpy.types.Region` :arg rv3d: 3D region data, typically bpy.context.space_data.region_3d. @@ -74,6 +82,9 @@ def region_2d_to_origin_3d(region, rv3d, coord): :arg coord: 2d coordinates relative to the region; (event.mouse_region_x, event.mouse_region_y) for example. :type coord: 2d vector + :arg clamp: Clamp the maximum far-clip value used. + (negative value will move the offset away from the view_location) + :type clamp: float or None :return: The origin of the viewpoint in 3d space. :rtype: :class:`mathutils.Vector` """ @@ -89,6 +100,20 @@ def region_2d_to_origin_3d(region, rv3d, coord): origin_start = ((persinv.col[0].xyz * dx) + (persinv.col[1].xyz * dy) + viewinv.translation) + + if clamp != 0.0: + if rv3d.view_perspective != 'CAMERA': + # this value is scaled to the far clip already + origin_offset = persinv.col[2].xyz + if clamp is not None: + if clamp < 0.0: + origin_offset.negate() + clamp = -clamp + if origin_offset.length > clamp: + origin_offset.length = clamp + + origin_start -= origin_offset + return origin_start diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py index e6b62cae6ef..0c5aae1de2f 100644 --- a/release/scripts/startup/bl_ui/properties_constraint.py +++ b/release/scripts/startup/bl_ui/properties_constraint.py @@ -768,9 +768,27 @@ class ConstraintButtonsPanel(): col = layout.column() col.label(text="Chain Scaling:") col.prop(con, "use_y_stretch") - col.prop(con, "xz_scale_mode") col.prop(con, "use_curve_radius") + layout.prop(con, "xz_scale_mode") + + if con.xz_scale_mode == 'VOLUME_PRESERVE': + layout.prop(con, "bulge", text="Volume Variation") + split = layout.split() + col = split.column(align=True) + col.prop(con, "use_bulge_min", text="Volume Min") + sub = col.column() + sub.active = con.use_bulge_min + sub.prop(con, "bulge_min", text="") + col = split.column(align=True) + col.prop(con, "use_bulge_max", text="Volume Max") + sub = col.column() + sub.active = con.use_bulge_max + sub.prop(con, "bulge_max", text="") + col = layout.column() + col.active = con.use_bulge_min or con.use_bulge_max + col.prop(con, "bulge_smooth", text="Smooth") + def PIVOT(self, context, layout, con): self.target_template(layout, con) diff --git a/release/scripts/startup/bl_ui/space_info.py b/release/scripts/startup/bl_ui/space_info.py index 2b075128fef..b642b61fcdc 100644 --- a/release/scripts/startup/bl_ui/space_info.py +++ b/release/scripts/startup/bl_ui/space_info.py @@ -132,6 +132,7 @@ class INFO_MT_file(Menu): layout.operator_context = 'INVOKE_AREA' layout.operator("wm.link", text="Link", icon='LINK_BLEND') layout.operator("wm.append", text="Append", icon='APPEND_BLEND') + layout.menu("INFO_MT_file_previews") layout.separator() @@ -195,6 +196,15 @@ class INFO_MT_file_external_data(Menu): layout.operator("file.find_missing_files") +class INFO_MT_file_previews(Menu): + bl_label = "Data Previews" + + def draw(self, context): + layout = self.layout + + layout.operator("wm.previews_ensure") + + class INFO_MT_game(Menu): bl_label = "Game" diff --git a/release/scripts/templates_py/operator_modal_view3d_raycast.py b/release/scripts/templates_py/operator_modal_view3d_raycast.py index 1aa13c90ca3..b72b2f76750 100644 --- a/release/scripts/templates_py/operator_modal_view3d_raycast.py +++ b/release/scripts/templates_py/operator_modal_view3d_raycast.py @@ -14,10 +14,6 @@ def main(context, event, ray_max=1000.0): view_vector = view3d_utils.region_2d_to_vector_3d(region, rv3d, coord) ray_origin = view3d_utils.region_2d_to_origin_3d(region, rv3d, coord) - if rv3d.view_perspective == 'ORTHO': - # move ortho origin back - ray_origin = ray_origin - (view_vector * (ray_max / 2.0)) - ray_target = ray_origin + (view_vector * ray_max) def visible_objects_and_duplis(): diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 08edde1cec0..f11aad27e4b 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -373,10 +373,10 @@ void CustomData_external_reload(struct CustomData *data, /* Mesh-to-mesh transfer data. */ struct MeshPairRemap; -typedef struct CustomDataTransferLayerMap CustomDataTransferLayerMap; +struct CustomDataTransferLayerMap; typedef void (*cd_datatransfer_interp)( - const CustomDataTransferLayerMap *laymap, void *dest, + const struct CustomDataTransferLayerMap *laymap, void *dest, void **sources, const float *weights, const int count, const float mix_factor); /** @@ -423,7 +423,7 @@ enum { }; typedef struct CustomDataTransferLayerMap { - CustomDataTransferLayerMap *next, *prev; + struct CustomDataTransferLayerMap *next, *prev; int data_type; int mix_mode; diff --git a/source/blender/blenkernel/BKE_object_data_transfer.h b/source/blender/blenkernel/BKE_data_transfer.h index fe218901201..07ef16e8161 100644 --- a/source/blender/blenkernel/BKE_object_data_transfer.h +++ b/source/blender/blenkernel/BKE_data_transfer.h @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/blenkernel/BKE_object_data_transfer.h +/** \file blender/blenkernel/BKE_data_transfer.h * \ingroup bke */ diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 31e28f9e51b..c71595e7a3e 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -85,6 +85,7 @@ set(SRC intern/curve.c intern/customdata.c intern/customdata_file.c + intern/data_transfer.c intern/deform.c intern/depsgraph.c intern/displist.c @@ -130,7 +131,6 @@ set(SRC intern/nla.c intern/node.c intern/object.c - intern/object_data_transfer.c intern/object_deform.c intern/object_dupli.c intern/ocean.c @@ -203,6 +203,7 @@ set(SRC BKE_curve.h BKE_customdata.h BKE_customdata_file.h + BKE_data_transfer.h BKE_deform.h BKE_depsgraph.h BKE_displist.h @@ -239,7 +240,6 @@ set(SRC BKE_nla.h BKE_node.h BKE_object.h - BKE_object_data_transfer.h BKE_object_deform.h BKE_ocean.h BKE_packedFile.h diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index df57db21e3b..03372b97049 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -2166,9 +2166,9 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o mul_v3_fl(poseMat[2], scale); break; } - case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC: + case CONSTRAINT_SPLINEIK_XZS_INVERSE: { - /* 'volume preservation' */ + /* old 'volume preservation' method using the inverse scale */ float scale; /* calculate volume preservation factor which is @@ -2189,6 +2189,54 @@ static void splineik_evaluate_bone(tSplineIK_Tree *tree, Scene *scene, Object *o mul_v3_fl(poseMat[2], scale); break; } + case CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC: + { + /* improved volume preservation based on the Stretch To constraint */ + float final_scale; + + /* as the basis for volume preservation, we use the inverse scale factor... */ + if (fabsf(scaleFac) != 0.0f) { + /* NOTE: The method here is taken wholesale from the Stretch To constraint */ + float bulge = powf(1.0f / fabsf(scaleFac), ikData->bulge); + + if (bulge > 1.0f) { + if (ikData->flag & STRETCHTOCON_USE_BULGE_MAX) { + float bulge_max = max_ff(ikData->bulge_max, 1.0f); + float hard = min_ff(bulge, bulge_max); + + float range = bulge_max - 1.0f; + float scale = (range > 0.0f) ? 1.0f / range : 0.0f; + float soft = 1.0f + range * atanf((bulge - 1.0f) * scale) / (0.5f * M_PI); + + bulge = interpf(soft, hard, ikData->bulge_smooth); + } + } + if (bulge < 1.0f) { + if (ikData->flag & STRETCHTOCON_USE_BULGE_MIN) { + float bulge_min = CLAMPIS(ikData->bulge_min, 0.0f, 1.0f); + float hard = max_ff(bulge, bulge_min); + + float range = 1.0f - bulge_min; + float scale = (range > 0.0f) ? 1.0f / range : 0.0f; + float soft = 1.0f - range * atanf((1.0f - bulge) * scale) / (0.5f * M_PI); + + bulge = interpf(soft, hard, ikData->bulge_smooth); + } + } + + /* compute scale factor for xz axes from this value */ + final_scale = sqrt(bulge); + } + else { + /* no scaling, so scale factor is simple */ + final_scale = 1.0f; + } + + /* apply the scaling (assuming normalised scale) */ + mul_v3_fl(poseMat[0], final_scale); + mul_v3_fl(poseMat[2], final_scale); + break; + } } /* finally, multiply the x and z scaling by the radius of the curve too, diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 9072acd8b02..f591fe857f8 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -2722,7 +2722,7 @@ static void stretchto_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t } if (bulge < 1.0f) { if (data->flag & STRETCHTOCON_USE_BULGE_MIN) { - float bulge_min = CLAMPIS(data->bulge_max, 0.0f, 1.0f); + float bulge_min = CLAMPIS(data->bulge_min, 0.0f, 1.0f); float hard = max_ff(bulge, bulge_min); float range = 1.0f - bulge_min; @@ -3698,6 +3698,9 @@ static void splineik_new_data(void *cdata) bSplineIKConstraint *data = (bSplineIKConstraint *)cdata; data->chainlen = 1; + data->bulge = 1.0; + data->bulge_max = 1.0f; + data->bulge_min = 1.0f; } static void splineik_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata) diff --git a/source/blender/blenkernel/intern/object_data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 78a293c644e..b573d621052 100644 --- a/source/blender/blenkernel/intern/object_data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -25,7 +25,7 @@ * ***** END GPL LICENSE BLOCK ***** */ -/** \file blender/blenkernel/intern/object_data_transfer.c +/** \file blender/blenkernel/intern/data_transfer.c * \ingroup bke */ @@ -44,7 +44,7 @@ #include "BKE_context.h" #include "BKE_customdata.h" -#include "BKE_object_data_transfer.h" +#include "BKE_data_transfer.h" #include "BKE_deform.h" #include "BKE_DerivedMesh.h" #include "BKE_mesh_mapping.h" diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 4ed9278ab26..80db62801d6 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -52,7 +52,7 @@ #include "BLF_translation.h" #include "BKE_customdata.h" -#include "BKE_object_data_transfer.h" +#include "BKE_data_transfer.h" #include "BKE_deform.h" /* own include */ #include "BKE_mesh_mapping.h" #include "BKE_object_deform.h" diff --git a/source/blender/blenkernel/intern/mesh_evaluate.c b/source/blender/blenkernel/intern/mesh_evaluate.c index 4c9e44682c3..915abdb6766 100644 --- a/source/blender/blenkernel/intern/mesh_evaluate.c +++ b/source/blender/blenkernel/intern/mesh_evaluate.c @@ -896,13 +896,6 @@ float BKE_mesh_calc_poly_area(MPoly *mpoly, MLoop *loopstart, mvarray[loopstart[2].v].co ); } - else if (mpoly->totloop == 4) { - return area_quad_v3(mvarray[loopstart[0].v].co, - mvarray[loopstart[1].v].co, - mvarray[loopstart[2].v].co, - mvarray[loopstart[3].v].co - ); - } else { int i; MLoop *l_iter = loopstart; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index b158f7bec96..fb6b65d7a00 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -3507,6 +3507,88 @@ int BKE_object_is_modified(Scene *scene, Object *ob) return flag; } +/* Check of objects moves in time. */ +/* NOTE: This function is currently optimized for usage in combination + * with mti->canDeform, so modifiers can quickly check if their target + * objects moves (causing deformation motion blur) or not. + * + * This makes it possible to give some degree of false-positives here, + * but it's currently an acceptable tradeof between complexity and check + * speed. In combination with checks of modifier stack and real life usage + * percentage of false-positives shouldn't be that hight. + */ +static bool object_moves_in_time(Object *object) +{ + AnimData *adt = object->adt; + if (adt != NULL) { + /* If object has any sort of animation data assume it is moving. */ + if (adt->action != NULL || + !BLI_listbase_is_empty(&adt->nla_tracks) || + !BLI_listbase_is_empty(&adt->drivers) || + !BLI_listbase_is_empty(&adt->overrides)) + { + return true; + } + } + if (!BLI_listbase_is_empty(&object->constraints)) { + return true; + } + if (object->parent != NULL) { + /* TODO(sergey): Do recursive check here? */ + return true; + } + return false; +} + +static bool constructive_modifier_is_deform_modified(ModifierData *md) +{ + /* TODO(sergey): Consider generalizing this a bit so all modifier logic + * is concentrated in MOD_{modifier}.c file, + */ + if (md->type == eModifierType_Array) { + ArrayModifierData *amd = (ArrayModifierData *)md; + /* TODO(sergey): Check if curve is deformed. */ + return (amd->start_cap != NULL && object_moves_in_time(amd->start_cap)) || + (amd->end_cap != NULL && object_moves_in_time(amd->end_cap)) || + (amd->curve_ob != NULL && object_moves_in_time(amd->curve_ob)) || + (amd->offset_ob != NULL && object_moves_in_time(amd->offset_ob)); + } + else if (md->type == eModifierType_Mirror) { + MirrorModifierData *mmd = (MirrorModifierData *)md; + return mmd->mirror_ob != NULL && object_moves_in_time(mmd->mirror_ob); + } + else if (md->type == eModifierType_Screw) { + ScrewModifierData *smd = (ScrewModifierData *)md; + return smd->ob_axis != NULL && object_moves_in_time(smd->ob_axis); + } + return false; +} + +static bool modifiers_has_animation_check(Object *ob) +{ + /* TODO(sergey): This is a bit code duplication with depsgraph, but + * would be nicer to solve this as a part of new dependency graph + * work, so we avoid conflicts and so. + */ + if (ob->adt != NULL) { + AnimData *adt = ob->adt; + FCurve *fcu; + if (adt->action != NULL) { + for (fcu = adt->action->curves.first; fcu; fcu = fcu->next) { + if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) { + return true; + } + } + } + for (fcu = adt->drivers.first; fcu; fcu = fcu->next) { + if (fcu->rna_path && strstr(fcu->rna_path, "modifiers[")) { + return true; + } + } + } + return false; +} + /* test if object is affected by deforming modifiers (for motion blur). again * most important is to avoid false positives, this is to skip computations * and we can still if there was actual deformation afterwards */ @@ -3515,6 +3597,7 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob) ModifierData *md; VirtualModifierData virtualModifierData; int flag = 0; + const bool is_modifier_animated = modifiers_has_animation_check(ob); if (BKE_key_from_object(ob)) flag |= eModifierMode_Realtime | eModifierMode_Render; @@ -3525,8 +3608,14 @@ int BKE_object_is_deform_modified(Scene *scene, Object *ob) md = md->next) { ModifierTypeInfo *mti = modifierType_getInfo(md->type); + bool can_deform = mti->type == eModifierTypeType_OnlyDeform || + is_modifier_animated; + + if (!can_deform) { + can_deform = constructive_modifier_is_deform_modified(md); + } - if (mti->type == eModifierTypeType_OnlyDeform) { + if (can_deform) { if (!(flag & eModifierMode_Render) && modifier_isEnabled(scene, md, eModifierMode_Render)) flag |= eModifierMode_Render; diff --git a/source/blender/blenlib/BLI_linklist_stack.h b/source/blender/blenlib/BLI_linklist_stack.h index 17d40e068b3..9ac233a8fa4 100644 --- a/source/blender/blenlib/BLI_linklist_stack.h +++ b/source/blender/blenlib/BLI_linklist_stack.h @@ -51,46 +51,46 @@ #define BLI_LINKSTACK_DECLARE(var, type) \ LinkNode *var; \ - BLI_mempool *_##var##_pool; \ - type _##var##_type + BLI_mempool *var##_pool_; \ + type var##_type_ #define BLI_LINKSTACK_INIT(var) { \ var = NULL; \ - _##var##_pool = BLI_mempool_create(sizeof(LinkNode), 0, 64, BLI_MEMPOOL_NOP); \ + var##_pool_ = BLI_mempool_create(sizeof(LinkNode), 0, 64, BLI_MEMPOOL_NOP); \ } (void)0 #define BLI_LINKSTACK_SIZE(var) \ - BLI_mempool_count(_##var##_pool) + BLI_mempool_count(var##_pool_) /* check for typeof() */ #ifdef __GNUC__ #define BLI_LINKSTACK_PUSH(var, ptr) ( \ - CHECK_TYPE_INLINE(ptr, typeof(_##var##_type)), \ - BLI_linklist_prepend_pool(&(var), ptr, _##var##_pool)) + CHECK_TYPE_INLINE(ptr, typeof(var##_type_)), \ + BLI_linklist_prepend_pool(&(var), ptr, var##_pool_)) #define BLI_LINKSTACK_POP(var) \ - (var ? (typeof(_##var##_type))BLI_linklist_pop_pool(&(var), _##var##_pool) : NULL) + (var ? (typeof(var##_type_))BLI_linklist_pop_pool(&(var), var##_pool_) : NULL) #define BLI_LINKSTACK_POP_DEFAULT(var, r) \ - (var ? (typeof(_##var##_type))BLI_linklist_pop_pool(&(var), _##var##_pool) : r) + (var ? (typeof(var##_type_))BLI_linklist_pop_pool(&(var), var##_pool_) : r) #else /* non gcc */ #define BLI_LINKSTACK_PUSH(var, ptr) ( \ - BLI_linklist_prepend_pool(&(var), ptr, _##var##_pool)) + BLI_linklist_prepend_pool(&(var), ptr, var##_pool_)) #define BLI_LINKSTACK_POP(var) \ - (var ? BLI_linklist_pop_pool(&(var), _##var##_pool) : NULL) + (var ? BLI_linklist_pop_pool(&(var), var##_pool_) : NULL) #define BLI_LINKSTACK_POP_DEFAULT(var, r) \ - (var ? BLI_linklist_pop_pool(&(var), _##var##_pool) : r) + (var ? BLI_linklist_pop_pool(&(var), var##_pool_) : r) #endif /* gcc check */ #define BLI_LINKSTACK_SWAP(var_a, var_b) { \ - CHECK_TYPE_PAIR(_##var_a##_type, _##var_b##_type); \ + CHECK_TYPE_PAIR(var_a##_type_, var_b##_type_); \ SWAP(LinkNode *, var_a, var_b); \ - SWAP(BLI_mempool *, _##var_a##_pool, _##var_b##_pool); \ + SWAP(BLI_mempool *, var_a##_pool_, var_b##_pool_); \ } (void)0 #define BLI_LINKSTACK_FREE(var) { \ - BLI_mempool_destroy(_##var##_pool); \ - _##var##_pool = NULL; (void)_##var##_pool; \ + BLI_mempool_destroy(var##_pool_); \ + var##_pool_ = NULL; (void)var##_pool_; \ var = NULL; (void)var; \ - (void)&(_##var##_type); \ + (void)&(var##_type_); \ } (void)0 #include "BLI_linklist.h" diff --git a/source/blender/blenlib/BLI_math_geom.h b/source/blender/blenlib/BLI_math_geom.h index ee99f860a97..495aa6b2465 100644 --- a/source/blender/blenlib/BLI_math_geom.h +++ b/source/blender/blenlib/BLI_math_geom.h @@ -52,16 +52,23 @@ float normal_quad_v3(float r[3], const float a[3], const float b[3], const float float normal_poly_v3(float r[3], const float verts[][3], unsigned int nr); MINLINE float area_tri_v2(const float a[2], const float b[2], const float c[2]); +MINLINE float area_squared_tri_v2(const float a[2], const float b[2], const float c[2]); MINLINE float area_tri_signed_v2(const float v1[2], const float v2[2], const float v3[2]); float area_tri_v3(const float a[3], const float b[3], const float c[3]); +float area_squared_tri_v3(const float a[3], const float b[3], const float c[3]); float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3]); float area_quad_v3(const float a[3], const float b[3], const float c[3], const float d[3]); +float area_squared_quad_v3(const float a[3], const float b[3], const float c[3], const float d[3]); float area_poly_v3(const float verts[][3], unsigned int nr); float area_poly_v2(const float verts[][2], unsigned int nr); +float area_squared_poly_v3(const float verts[][3], unsigned int nr); +float area_squared_poly_v2(const float verts[][2], unsigned int nr); +float area_poly_signed_v2(const float verts[][2], unsigned int nr); float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3]); void cross_tri_v3(float n[3], const float v1[3], const float v2[3], const float v3[3]); MINLINE float cross_tri_v2(const float v1[2], const float v2[2], const float v3[2]); +void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr); float cross_poly_v2(const float verts[][2], unsigned int nr); /********************************* Planes **********************************/ diff --git a/source/blender/blenlib/intern/math_geom.c b/source/blender/blenlib/intern/math_geom.c index 59d9cf85dec..05a527c4f7a 100644 --- a/source/blender/blenlib/intern/math_geom.c +++ b/source/blender/blenlib/intern/math_geom.c @@ -109,58 +109,44 @@ float normal_quad_v3(float n[3], const float v1[3], const float v2[3], const flo */ float normal_poly_v3(float n[3], const float verts[][3], unsigned int nr) { - const float *v_prev = verts[nr - 1]; - const float *v_curr = verts[0]; - unsigned int i; - - zero_v3(n); - - /* Newell's Method */ - for (i = 0; i < nr; v_prev = v_curr, v_curr = verts[++i]) { - add_newell_cross_v3_v3v3(n, v_prev, v_curr); - } - + cross_poly_v3(n, verts, nr); return normalize_v3(n); } -/* only convex Quadrilaterals */ float area_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]) { - float len, vec1[3], vec2[3], n[3]; - - sub_v3_v3v3(vec1, v2, v1); - sub_v3_v3v3(vec2, v4, v1); - cross_v3_v3v3(n, vec1, vec2); - len = len_v3(n); - - sub_v3_v3v3(vec1, v4, v3); - sub_v3_v3v3(vec2, v2, v3); - cross_v3_v3v3(n, vec1, vec2); - len += len_v3(n); + const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}}; + return area_poly_v3(verts, 4); +} - return (len / 2.0f); +float area_squared_quad_v3(const float v1[3], const float v2[3], const float v3[3], const float v4[3]) +{ + const float verts[4][3] = {{UNPACK3(v1)}, {UNPACK3(v2)}, {UNPACK3(v3)}, {UNPACK3(v4)}}; + return area_squared_poly_v3(verts, 4); } /* Triangles */ float area_tri_v3(const float v1[3], const float v2[3], const float v3[3]) { - float vec1[3], vec2[3], n[3]; - - sub_v3_v3v3(vec1, v3, v2); - sub_v3_v3v3(vec2, v1, v2); - cross_v3_v3v3(n, vec1, vec2); + float n[3]; + cross_tri_v3(n, v1, v2, v3); + return len_v3(n) * 0.5f; +} - return len_v3(n) / 2.0f; +float area_squared_tri_v3(const float v1[3], const float v2[3], const float v3[3]) +{ + float n[3]; + cross_tri_v3(n, v1, v2, v3); + mul_v3_fl(n, 0.5f); + return len_squared_v3(n); } float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3], const float normal[3]) { - float area, vec1[3], vec2[3], n[3]; + float area, n[3]; - sub_v3_v3v3(vec1, v3, v2); - sub_v3_v3v3(vec2, v1, v2); - cross_v3_v3v3(n, vec1, vec2); - area = len_v3(n) / 2.0f; + cross_tri_v3(n, v1, v2, v3); + area = len_v3(n) * 0.5f; /* negate area for flipped triangles */ if (dot_v3v3(n, normal) < 0.0f) @@ -172,7 +158,17 @@ float area_tri_signed_v3(const float v1[3], const float v2[3], const float v3[3] float area_poly_v3(const float verts[][3], unsigned int nr) { float n[3]; - return normal_poly_v3(n, verts, nr) * 0.5f; + cross_poly_v3(n, verts, nr); + return len_v3(n) * 0.5f; +} + +float area_squared_poly_v3(const float verts[][3], unsigned int nr) +{ + float n[3]; + + cross_poly_v3(n, verts, nr); + mul_v3_fl(n, 0.5f); + return len_squared_v3(n); } /** @@ -200,11 +196,36 @@ float cross_poly_v2(const float verts[][2], unsigned int nr) return cross; } +void cross_poly_v3(float n[3], const float verts[][3], unsigned int nr) +{ + const float *v_prev = verts[nr - 1]; + const float *v_curr = verts[0]; + unsigned int i; + + zero_v3(n); + + /* Newell's Method */ + for (i = 0; i < nr; v_prev = v_curr, v_curr = verts[++i]) { + add_newell_cross_v3_v3v3(n, v_prev, v_curr); + } +} + float area_poly_v2(const float verts[][2], unsigned int nr) { return fabsf(0.5f * cross_poly_v2(verts, nr)); } +float area_poly_signed_v2(const float verts[][2], unsigned int nr) +{ + return (0.5f * cross_poly_v2(verts, nr)); +} + +float area_squared_poly_v2(const float verts[][2], unsigned int nr) +{ + float area = area_poly_signed_v2(verts, nr); + return area * area; +} + float cotangent_tri_weight_v3(const float v1[3], const float v2[3], const float v3[3]) { float a[3], b[3], c[3], c_len; diff --git a/source/blender/blenlib/intern/math_geom_inline.c b/source/blender/blenlib/intern/math_geom_inline.c index 5a64ed63ecf..44b17681540 100644 --- a/source/blender/blenlib/intern/math_geom_inline.c +++ b/source/blender/blenlib/intern/math_geom_inline.c @@ -54,6 +54,12 @@ MINLINE float area_tri_v2(const float v1[2], const float v2[2], const float v3[2 return fabsf(area_tri_signed_v2(v1, v2, v3)); } +MINLINE float area_squared_tri_v2(const float v1[2], const float v2[2], const float v3[2]) +{ + float area = area_tri_signed_v2(v1, v2, v3); + return area * area; +} + /****************************** Spherical Harmonics **************************/ MINLINE void zero_sh(float r[9]) diff --git a/source/blender/bmesh/intern/bmesh_polygon.c b/source/blender/bmesh/intern/bmesh_polygon.c index f2c426133c2..e4aa4bb0c0e 100644 --- a/source/blender/bmesh/intern/bmesh_polygon.c +++ b/source/blender/bmesh/intern/bmesh_polygon.c @@ -214,9 +214,6 @@ float BM_face_calc_area(BMFace *f) if (f->len == 3) { area = area_tri_v3(verts[0], verts[1], verts[2]); } - else if (f->len == 4) { - area = area_quad_v3(verts[0], verts[1], verts[2], verts[3]); - } else { area = area_poly_v3((const float (*)[3])verts, f->len); } diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index e7b65a10790..da1991a187d 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -236,6 +236,20 @@ static void bmo_region_extend_expand( bmo_face_flag_set_flush(bm, f, SEL_FLAG, true); } } + + /* handle wire edges (when stepping over faces) */ + { + BMIter eiter; + BMEdge *e; + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (BM_edge_is_wire(e)) { + if (!BMO_elem_flag_test(bm, e, SEL_FLAG)) { + BMO_elem_flag_enable(bm, e, SEL_FLAG); + BMO_elem_flag_enable(bm, BM_edge_other_vert(e, v), SEL_FLAG); + } + } + } + } } } } @@ -306,6 +320,21 @@ static void bmo_region_extend_contract( break; } } + + /* handle wire edges (when stepping over faces) */ + if (!found) { + BMIter eiter; + BMEdge *e; + + BM_ITER_ELEM (e, &eiter, v, BM_EDGES_OF_VERT) { + if (BM_edge_is_wire(e)) { + if (!BMO_elem_flag_test(bm, e, SEL_ORIG)) { + found = true; + break; + } + } + } + } } if (found) { diff --git a/source/blender/editors/include/ED_render.h b/source/blender/editors/include/ED_render.h index 32fa641e3ae..de3843c91eb 100644 --- a/source/blender/editors/include/ED_render.h +++ b/source/blender/editors/include/ED_render.h @@ -72,7 +72,7 @@ void ED_preview_init_dbase(void); void ED_preview_free_dbase(void); void ED_preview_shader_job(const struct bContext *C, void *owner, struct ID *id, struct ID *parent, struct MTex *slot, int sizex, int sizey, int method); -void ED_preview_icon_render(const struct bContext *C, void *owner, struct ID *id, unsigned int *rect, int sizex, int sizey); +void ED_preview_icon_render(struct Scene *scene, struct ID *id, unsigned int *rect, int sizex, int sizey); void ED_preview_icon_job(const struct bContext *C, void *owner, struct ID *id, unsigned int *rect, int sizex, int sizey); void ED_preview_kill_jobs(struct wmWindowManager *wm, struct Main *bmain); diff --git a/source/blender/editors/include/ED_screen.h b/source/blender/editors/include/ED_screen.h index ed2465647da..b790c656b61 100644 --- a/source/blender/editors/include/ED_screen.h +++ b/source/blender/editors/include/ED_screen.h @@ -107,6 +107,7 @@ void ED_screen_set_subwinactive(struct bContext *C, struct wmEvent *event); void ED_screen_exit(struct bContext *C, struct wmWindow *window, struct bScreen *screen); void ED_screen_animation_timer(struct bContext *C, int redraws, int refresh, int sync, int enable); void ED_screen_animation_timer_update(struct bScreen *screen, int redraws, int refresh); +void ED_screen_retore_temp_type(struct bContext *C, ScrArea *sa, bool is_screen_change); ScrArea *ED_screen_full_newspace(struct bContext *C, ScrArea *sa, int type); void ED_screen_full_prevspace(struct bContext *C, ScrArea *sa); void ED_screen_full_restore(struct bContext *C, ScrArea *sa); diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index 2ba3d309aa7..74927428363 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -64,7 +64,8 @@ void UI_icons_init(int first_dyn_id); int UI_icon_get_width(int icon_id); int UI_icon_get_height(int icon_id); -void UI_id_icon_render(const struct bContext *C, struct ID *id, const bool big, const bool use_job); +void UI_id_icon_render( + const struct bContext *C, struct Scene *scene, struct ID *id, const bool big, const bool use_job); void UI_icon_draw(float x, float y, int icon_id); void UI_icon_draw_preview(float x, float y, int icon_id); diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index ac9abe8e781..679681cb372 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -931,7 +931,8 @@ static void icon_create_rect(struct PreviewImage *prv_img, enum eIconSizes size) /* only called when icon has changed */ /* only call with valid pointer from UI_icon_draw */ -static void icon_set_image(const bContext *C, ID *id, PreviewImage *prv_img, enum eIconSizes size, const bool use_job) +static void icon_set_image( + const bContext *C, Scene *scene, ID *id, PreviewImage *prv_img, enum eIconSizes size, const bool use_job) { if (!prv_img) { if (G.debug & G_DEBUG) @@ -946,8 +947,11 @@ static void icon_set_image(const bContext *C, ID *id, PreviewImage *prv_img, enu ED_preview_icon_job(C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]); } else { + if (!scene) { + scene = CTX_data_scene(C); + } /* Immediate version */ - ED_preview_icon_render(C, prv_img, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]); + ED_preview_icon_render(scene, id, prv_img->rect[size], prv_img->w[size], prv_img->h[size]); } } @@ -1155,25 +1159,26 @@ static void icon_draw_size(float x, float y, int icon_id, float aspect, float al } } -static void ui_id_preview_image_render_size(const bContext *C, ID *id, PreviewImage *pi, int size, const bool use_job) +static void ui_id_preview_image_render_size( + const bContext *C, Scene *scene, ID *id, PreviewImage *pi, int size, const bool use_job) { if ((pi->changed[size] || !pi->rect[size])) { /* changed only ever set by dynamic icons */ /* create the rect if necessary */ - icon_set_image(C, id, pi, size, use_job); + icon_set_image(C, scene, id, pi, size, use_job); pi->changed[size] = 0; } } -void UI_id_icon_render(const bContext *C, ID *id, const bool big, const bool use_job) +void UI_id_icon_render(const bContext *C, Scene *scene, ID *id, const bool big, const bool use_job) { PreviewImage *pi = BKE_previewimg_get(id); if (pi) { if (big) - ui_id_preview_image_render_size(C, id, pi, ICON_SIZE_PREVIEW, use_job); /* bigger preview size */ + ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_PREVIEW, use_job); /* bigger preview size */ else - ui_id_preview_image_render_size(C, id, pi, ICON_SIZE_ICON, use_job); /* icon size */ + ui_id_preview_image_render_size(C, scene, id, pi, ICON_SIZE_ICON, use_job); /* icon size */ } } @@ -1189,7 +1194,7 @@ static void ui_id_brush_render(const bContext *C, ID *id) /* check if rect needs to be created; changed * only set by dynamic icons */ if ((pi->changed[i] || !pi->rect[i])) { - icon_set_image(C, id, pi, i, true); + icon_set_image(C, NULL, id, pi, i, true); pi->changed[i] = 0; } } @@ -1265,7 +1270,7 @@ int ui_id_icon_get(const bContext *C, ID *id, const bool big) case ID_LA: /* fall through */ iconid = BKE_icon_getid(id); /* checks if not exists, or changed */ - UI_id_icon_render(C, id, big, true); + UI_id_icon_render(C, NULL, id, big, true); break; default: break; diff --git a/source/blender/editors/interface/interface_panel.c b/source/blender/editors/interface/interface_panel.c index 5ccfa4193e9..e68c86353a3 100644 --- a/source/blender/editors/interface/interface_panel.c +++ b/source/blender/editors/interface/interface_panel.c @@ -753,9 +753,13 @@ static int find_highest_panel(const void *a1, const void *a2) const PanelSort *ps1 = a1, *ps2 = a2; /* stick uppermost header-less panels to the top of the region - - * prevent them from being sorted */ - if (ps1->pa->sortorder < ps2->pa->sortorder && ps1->pa->type->flag & PNL_NO_HEADER) return -1; - + * prevent them from being sorted (multiple header-less panels have to be sorted though) */ + if (ps1->pa->type->flag & PNL_NO_HEADER && ps2->pa->type->flag & PNL_NO_HEADER) { + /* skip and check for ofs and sortorder below */ + } + else if (ps1->pa->type->flag & PNL_NO_HEADER) return -1; + else if (ps2->pa->type->flag & PNL_NO_HEADER) return 1; + if (ps1->pa->ofsy + ps1->pa->sizey < ps2->pa->ofsy + ps2->pa->sizey) return 1; else if (ps1->pa->ofsy + ps1->pa->sizey > ps2->pa->ofsy + ps2->pa->sizey) return -1; else if (ps1->pa->sortorder > ps2->pa->sortorder) return 1; diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index 7f20970cfb9..10541a6d02e 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -75,10 +75,16 @@ #define KMAXDIST 10 /* max mouse distance from edge before not detecting it */ +/* WARNING: knife float precision is fragile: + * be careful before making changes here see: (T43229, T42864, T42459, T41164). + */ #define KNIFE_FLT_EPS 0.00001f #define KNIFE_FLT_EPS_SQUARED (KNIFE_FLT_EPS * KNIFE_FLT_EPS) #define KNIFE_FLT_EPSBIG 0.0005f -#define KNIFE_FLT_EPS_PX 0.2f + +#define KNIFE_FLT_EPS_PX_VERT 0.5f +#define KNIFE_FLT_EPS_PX_EDGE 0.05f +#define KNIFE_FLT_EPS_PX_FACE 0.05f typedef struct KnifeColors { unsigned char line[3]; @@ -1318,7 +1324,6 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) float vert_tol, vert_tol_sq; float line_tol, line_tol_sq; float face_tol, face_tol_sq; - float eps_scale, eps_scale_px; int isect_kind; unsigned int tot; int i; @@ -1426,19 +1431,10 @@ static void knife_find_line_hits(KnifeTool_OpData *kcd) /* Now go through the candidates and find intersections */ /* These tolerances, in screen space, are for intermediate hits, as ends are already snapped to screen */ - { - /* Scale the epsilon by the zoom level - * to compensate for projection imprecision, see T41164 */ - const float zoom_xy[2] = { - kcd->vc.rv3d->winmat[0][0], - kcd->vc.rv3d->winmat[1][1]}; - eps_scale = len_v2(zoom_xy); - eps_scale_px = eps_scale * (kcd->is_interactive ? KNIFE_FLT_EPS_PX : KNIFE_FLT_EPSBIG); - } - - vert_tol = eps_scale_px; - line_tol = eps_scale_px; - face_tol = max_ff(vert_tol, line_tol); + + vert_tol = KNIFE_FLT_EPS_PX_VERT; + line_tol = KNIFE_FLT_EPS_PX_EDGE; + face_tol = KNIFE_FLT_EPS_PX_FACE; vert_tol_sq = vert_tol * vert_tol; line_tol_sq = line_tol * line_tol; diff --git a/source/blender/editors/object/object_data_transfer.c b/source/blender/editors/object/object_data_transfer.c index 71ad73ac420..95dc3de0b7f 100644 --- a/source/blender/editors/object/object_data_transfer.c +++ b/source/blender/editors/object/object_data_transfer.c @@ -41,7 +41,7 @@ #include "BLI_utildefines.h" #include "BKE_context.h" -#include "BKE_object_data_transfer.h" +#include "BKE_data_transfer.h" #include "BKE_DerivedMesh.h" #include "BKE_mesh_mapping.h" #include "BKE_mesh_remap.h" diff --git a/source/blender/editors/render/render_preview.c b/source/blender/editors/render/render_preview.c index 8833d76fde2..ea80a07fdd4 100644 --- a/source/blender/editors/render/render_preview.c +++ b/source/blender/editors/render/render_preview.c @@ -1098,14 +1098,13 @@ static void icon_preview_free(void *customdata) MEM_freeN(ip); } -void ED_preview_icon_render(const bContext *C, void *UNUSED(owner), ID *id, unsigned int *rect, int sizex, int sizey) +void ED_preview_icon_render(Scene *scene, ID *id, unsigned int *rect, int sizex, int sizey) { IconPreview ip = {0}; short stop = false, update = false; float progress = 0.0f; - /* customdata for preview thread */ - ip.scene = CTX_data_scene(C); + ip.scene = scene; ip.owner = id; ip.id = id; diff --git a/source/blender/editors/screen/screen_edit.c b/source/blender/editors/screen/screen_edit.c index c179cfc464c..3f814084238 100644 --- a/source/blender/editors/screen/screen_edit.c +++ b/source/blender/editors/screen/screen_edit.c @@ -1748,6 +1748,13 @@ ScrArea *ED_screen_full_newspace(bContext *C, ScrArea *sa, int type) } } + if (sa && (sa->spacetype != type)) { + newsa->flag |= AREA_FLAG_TEMP_TYPE; + } + else { + newsa->flag &= ~AREA_FLAG_TEMP_TYPE; + } + ED_area_newspace(C, newsa, type); return newsa; @@ -1763,6 +1770,21 @@ void ED_screen_full_prevspace(bContext *C, ScrArea *sa) ED_screen_state_toggle(C, win, sa, SCREENMAXIMIZED); } +void ED_screen_retore_temp_type(bContext *C, ScrArea *sa, bool is_screen_change) +{ + /* incase nether functions below run */ + ED_area_tag_redraw(sa); + + if (sa->flag & AREA_FLAG_TEMP_TYPE) { + ED_area_prevspace(C, sa); + sa->flag &= ~AREA_FLAG_TEMP_TYPE; + } + + if (is_screen_change && sa->full) { + ED_screen_state_toggle(C, CTX_wm_window(C), sa, SCREENMAXIMIZED); + } +} + /* restore a screen / area back to default operation, after temp fullscreen modes */ void ED_screen_full_restore(bContext *C, ScrArea *sa) { @@ -1789,12 +1811,14 @@ void ED_screen_full_restore(bContext *C, ScrArea *sa) else ED_screen_state_toggle(C, win, sa, state); } - else if (sl->spacetype == SPACE_FILE) { + else if (sa->flag & AREA_FLAG_TEMP_TYPE) { ED_screen_full_prevspace(C, sa); } else { ED_screen_state_toggle(C, win, sa, state); } + + sa->flag &= ~AREA_FLAG_TEMP_TYPE; } /* otherwise just tile the area again */ else { diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 5d0734db18b..3f3c14d3a7d 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -111,6 +111,7 @@ void file_draw_buttons(const bContext *C, ARegion *ar) SpaceFile *sfile = CTX_wm_space_file(C); FileSelectParams *params = ED_fileselect_get_params(sfile); ARegion *artmp; + const bool is_browse_only = (sfile->op == NULL); /* Initialize UI block. */ BLI_snprintf(uiblockstr, sizeof(uiblockstr), "win %p", (void *)ar); @@ -124,15 +125,22 @@ void file_draw_buttons(const bContext *C, ARegion *ar) available_w -= chan_offs; } } - + /* Is there enough space for the execute / cancel buttons? */ - loadbutton = UI_fontstyle_string_width(params->title) + btn_margin; - CLAMP_MIN(loadbutton, btn_minw); - if (available_w <= loadbutton + separator + input_minw || params->title[0] == 0) { + + if (is_browse_only) { loadbutton = 0; } else { + loadbutton = UI_fontstyle_string_width(params->title) + btn_margin; + CLAMP_MIN(loadbutton, btn_minw); + if (available_w <= loadbutton + separator + input_minw) { + loadbutton = 0; + } + } + + if (loadbutton) { line1_w -= (loadbutton + separator); line2_w = line1_w; } @@ -145,7 +153,7 @@ void file_draw_buttons(const bContext *C, ARegion *ar) else { line2_w -= (fnumbuttons + separator); } - + /* Text input fields for directory and file. */ if (available_w > 0) { int overwrite_alert = file_draw_check_exists(sfile); diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h index fb33879e2c1..86991245068 100644 --- a/source/blender/makesdna/DNA_constraint_types.h +++ b/source/blender/makesdna/DNA_constraint_types.h @@ -173,6 +173,12 @@ typedef struct bSplineIKConstraint { /* settings */ short flag; /* general settings for constraint */ short xzScaleMode; /* method used for determining the x & z scaling of the bones */ + + /* volume preservation settings */ + float bulge; + float bulge_min; + float bulge_max; + float bulge_smooth; } bSplineIKConstraint; @@ -680,15 +686,19 @@ typedef enum eKinematic_Flags { /* bSplineIKConstraint->flag */ typedef enum eSplineIK_Flags { /* chain has been attached to spline */ - CONSTRAINT_SPLINEIK_BOUND = (1<<0), + CONSTRAINT_SPLINEIK_BOUND = (1 << 0), /* root of chain is not influenced by the constraint */ - CONSTRAINT_SPLINEIK_NO_ROOT = (1<<1), + CONSTRAINT_SPLINEIK_NO_ROOT = (1 << 1), /* bones in the chain should not scale to fit the curve */ - CONSTRAINT_SPLINEIK_SCALE_LIMITED = (1<<2), + CONSTRAINT_SPLINEIK_SCALE_LIMITED = (1 << 2), /* evenly distribute the bones along the path regardless of length */ - CONSTRAINT_SPLINEIK_EVENSPLITS = (1<<3), + CONSTRAINT_SPLINEIK_EVENSPLITS = (1 << 3), /* don't adjust the x and z scaling of the bones by the curve radius */ - CONSTRAINT_SPLINEIK_NO_CURVERAD = (1<<4) + CONSTRAINT_SPLINEIK_NO_CURVERAD = (1 << 4), + + /* for "volumetric" xz scale mode, limit the minimum or maximum scale values */ + CONSTRAINT_SPLINEIK_USE_BULGE_MIN = (1 << 5), + CONSTRAINT_SPLINEIK_USE_BULGE_MAX = (1 << 6), } eSplineIK_Flags; /* bSplineIKConstraint->xzScaleMode */ @@ -698,7 +708,9 @@ typedef enum eSplineIK_XZScaleModes { /* bones in the chain should take their x/z scales from the original scaling */ CONSTRAINT_SPLINEIK_XZS_ORIGINAL = 1, /* x/z scales are the inverse of the y-scale */ - CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC = 2 + CONSTRAINT_SPLINEIK_XZS_INVERSE = 2, + /* x/z scales are computed using a volume preserving technique (from Stretch To constraint) */ + CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC = 3 } eSplineIK_XZScaleModes; /* MinMax (floor) flags */ diff --git a/source/blender/makesdna/DNA_screen_types.h b/source/blender/makesdna/DNA_screen_types.h index 47a08c62f95..941a7d020bc 100644 --- a/source/blender/makesdna/DNA_screen_types.h +++ b/source/blender/makesdna/DNA_screen_types.h @@ -272,12 +272,16 @@ typedef struct ARegion { // #define WIN_EQUAL 3 // UNUSED /* area->flag */ -#define HEADER_NO_PULLDOWN (1 << 0) -#define AREA_FLAG_DRAWJOINTO (1 << 1) -#define AREA_FLAG_DRAWJOINFROM (1 << 2) -#define AREA_TEMP_INFO (1 << 3) -#define AREA_FLAG_DRAWSPLIT_H (1 << 4) -#define AREA_FLAG_DRAWSPLIT_V (1 << 5) +enum { + HEADER_NO_PULLDOWN = (1 << 0), + AREA_FLAG_DRAWJOINTO = (1 << 1), + AREA_FLAG_DRAWJOINFROM = (1 << 2), + AREA_TEMP_INFO = (1 << 3), + AREA_FLAG_DRAWSPLIT_H = (1 << 4), + AREA_FLAG_DRAWSPLIT_V = (1 << 5), + /* used to check if we should switch back to prevspace (of a different type) */ + AREA_FLAG_TEMP_TYPE = (1 << 6), +}; #define EDGEWIDTH 1 #define AREAGRID 4 diff --git a/source/blender/makesrna/intern/rna_ID.c b/source/blender/makesrna/intern/rna_ID.c index 51d81295f8c..009e3799c49 100644 --- a/source/blender/makesrna/intern/rna_ID.c +++ b/source/blender/makesrna/intern/rna_ID.c @@ -64,6 +64,7 @@ EnumPropertyItem id_type_items[] = { {ID_MA, "MATERIAL", ICON_MATERIAL_DATA, "Material", ""}, {ID_MB, "META", ICON_META_DATA, "MetaBall", ""}, {ID_ME, "MESH", ICON_MESH_DATA, "Mesh", ""}, + {ID_MC, "MOVIECLIP", ICON_CLIP, "MovieClip", ""}, {ID_NT, "NODETREE", ICON_NODETREE, "NodeTree", ""}, {ID_OB, "OBJECT", ICON_OBJECT_DATA, "Object", ""}, {ID_PC, "PAINTCURVE", ICON_CURVE_BEZCURVE, "Paint Curve", ""}, @@ -71,12 +72,12 @@ EnumPropertyItem id_type_items[] = { {ID_PA, "PARTICLE", ICON_PARTICLE_DATA, "Particle", ""}, {ID_SCE, "SCENE", ICON_SCENE_DATA, "Scene", ""}, {ID_SCR, "SCREEN", ICON_SPLITSCREEN, "Screen", ""}, + {ID_SO, "SOUND", ICON_PLAY_AUDIO, "Sound", ""}, {ID_SPK, "SPEAKER", ICON_SPEAKER, "Speaker", ""}, - {ID_SO, "SOUND", ICON_PLAY_AUDIO, "Sound", ""}, {ID_TXT, "TEXT", ICON_TEXT, "Text", ""}, {ID_TE, "TEXTURE", ICON_TEXTURE_DATA, "Texture", ""}, - {ID_WO, "WORLD", ICON_WORLD_DATA, "World", ""}, {ID_WM, "WINDOWMANAGER", ICON_FULLSCREEN, "Window Manager", ""}, + {ID_WO, "WORLD", ICON_WORLD_DATA, "World", ""}, {0, NULL, 0, NULL, NULL} }; @@ -141,23 +142,23 @@ short RNA_type_to_ID_code(StructRNA *type) if (RNA_struct_is_a(type, &RNA_Lattice)) return ID_LT; if (RNA_struct_is_a(type, &RNA_Material)) return ID_MA; if (RNA_struct_is_a(type, &RNA_MetaBall)) return ID_MB; - if (RNA_struct_is_a(type, &RNA_NodeTree)) return ID_NT; + if (RNA_struct_is_a(type, &RNA_MovieClip)) return ID_MC; if (RNA_struct_is_a(type, &RNA_Mesh)) return ID_ME; + if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK; + if (RNA_struct_is_a(type, &RNA_NodeTree)) return ID_NT; if (RNA_struct_is_a(type, &RNA_Object)) return ID_OB; if (RNA_struct_is_a(type, &RNA_ParticleSettings)) return ID_PA; + if (RNA_struct_is_a(type, &RNA_Palette)) return ID_PAL; + if (RNA_struct_is_a(type, &RNA_PaintCurve)) return ID_PC; if (RNA_struct_is_a(type, &RNA_Scene)) return ID_SCE; if (RNA_struct_is_a(type, &RNA_Screen)) return ID_SCR; - if (RNA_struct_is_a(type, &RNA_Speaker)) return ID_SPK; if (RNA_struct_is_a(type, &RNA_Sound)) return ID_SO; - if (RNA_struct_is_a(type, &RNA_Text)) return ID_TXT; + if (RNA_struct_is_a(type, &RNA_Speaker)) return ID_SPK; if (RNA_struct_is_a(type, &RNA_Texture)) return ID_TE; + if (RNA_struct_is_a(type, &RNA_Text)) return ID_TXT; if (RNA_struct_is_a(type, &RNA_VectorFont)) return ID_VF; if (RNA_struct_is_a(type, &RNA_World)) return ID_WO; if (RNA_struct_is_a(type, &RNA_WindowManager)) return ID_WM; - if (RNA_struct_is_a(type, &RNA_MovieClip)) return ID_MC; - if (RNA_struct_is_a(type, &RNA_Mask)) return ID_MSK; - if (RNA_struct_is_a(type, &RNA_Palette)) return ID_PAL; - if (RNA_struct_is_a(type, &RNA_PaintCurve)) return ID_PC; return 0; } @@ -180,23 +181,23 @@ StructRNA *ID_code_to_RNA_type(short idcode) case ID_LT: return &RNA_Lattice; case ID_MA: return &RNA_Material; case ID_MB: return &RNA_MetaBall; - case ID_NT: return &RNA_NodeTree; + case ID_MC: return &RNA_MovieClip; case ID_ME: return &RNA_Mesh; + case ID_MSK: return &RNA_Mask; + case ID_NT: return &RNA_NodeTree; case ID_OB: return &RNA_Object; case ID_PA: return &RNA_ParticleSettings; + case ID_PAL: return &RNA_Palette; + case ID_PC: return &RNA_PaintCurve; case ID_SCE: return &RNA_Scene; case ID_SCR: return &RNA_Screen; - case ID_SPK: return &RNA_Speaker; case ID_SO: return &RNA_Sound; - case ID_TXT: return &RNA_Text; + case ID_SPK: return &RNA_Speaker; case ID_TE: return &RNA_Texture; + case ID_TXT: return &RNA_Text; case ID_VF: return &RNA_VectorFont; - case ID_WO: return &RNA_World; case ID_WM: return &RNA_WindowManager; - case ID_MC: return &RNA_MovieClip; - case ID_MSK: return &RNA_Mask; - case ID_PAL: return &RNA_Palette; - case ID_PC: return &RNA_PaintCurve; + case ID_WO: return &RNA_World; default: return &RNA_ID; } diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c index 77355dbad0e..b6845b1df2e 100644 --- a/source/blender/makesrna/intern/rna_constraint.c +++ b/source/blender/makesrna/intern/rna_constraint.c @@ -1388,7 +1388,7 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna) prop = RNA_def_property(srna, "bulge_smooth", PROP_FLOAT, PROP_FACTOR); RNA_def_property_range(prop, 0.0, 1.0f); - RNA_def_property_ui_text(prop, "Volume Variation Smoothness", ""); + RNA_def_property_ui_text(prop, "Volume Variation Smoothness", "Strength of volume stretching clamping"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); } @@ -2272,8 +2272,10 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) {CONSTRAINT_SPLINEIK_XZS_NONE, "NONE", 0, "None", "Don't scale the X and Z axes (Default)"}, {CONSTRAINT_SPLINEIK_XZS_ORIGINAL, "BONE_ORIGINAL", 0, "Bone Original", "Use the original scaling of the bones"}, + {CONSTRAINT_SPLINEIK_XZS_INVERSE, "INVERSE_PRESERVE", 0, "Inverse Scale", + "Scale of the X and Z axes is the inverse of the Y-Scale"}, {CONSTRAINT_SPLINEIK_XZS_VOLUMETRIC, "VOLUME_PRESERVE", 0, "Volume Preservation", - "Scale of the X and Z axes is the inverse of the Y-Scale"}, + "Scale of the X and Z axes are adjusted to preserve the volume of the bones"}, {0, NULL, 0, NULL, NULL} }; @@ -2333,12 +2335,44 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna) "on top of XZ Scale mode"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + /* xz scaling mode */ prop = RNA_def_property(srna, "xz_scale_mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "xzScaleMode"); RNA_def_property_enum_items(prop, splineik_xz_scale_mode); RNA_def_property_ui_text(prop, "XZ Scale Mode", "Method used for determining the scaling of the X and Z axes of the bones"); RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + /* volume presevation for "volumetric" scale mode */ + prop = RNA_def_property(srna, "bulge", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, 100.f); + RNA_def_property_ui_text(prop, "Volume Variation", "Factor between volume variation and stretching"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + prop = RNA_def_property(srna, "use_bulge_min", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_USE_BULGE_MIN); + RNA_def_property_ui_text(prop, "Use Volume Variation Minimum", "Use lower limit for volume variation"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + prop = RNA_def_property(srna, "use_bulge_max", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_SPLINEIK_USE_BULGE_MAX); + RNA_def_property_ui_text(prop, "Use Volume Variation Maximum", "Use upper limit for volume variation"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + prop = RNA_def_property(srna, "bulge_min", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 0.0, 1.0f); + RNA_def_property_ui_text(prop, "Volume Variation Minimum", "Minimum volume stretching factor"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + prop = RNA_def_property(srna, "bulge_max", PROP_FLOAT, PROP_NONE); + RNA_def_property_range(prop, 1.0, 100.0f); + RNA_def_property_ui_text(prop, "Volume Variation Maximum", "Maximum volume stretching factor"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); + + prop = RNA_def_property(srna, "bulge_smooth", PROP_FLOAT, PROP_FACTOR); + RNA_def_property_range(prop, 0.0, 1.0f); + RNA_def_property_ui_text(prop, "Volume Variation Smoothness", "Strength of volume stretching clamping"); + RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update"); } static void rna_def_constraint_pivot(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index 03e73ec186a..9554b219da9 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -43,7 +43,7 @@ #include "BLF_translation.h" #include "BKE_animsys.h" -#include "BKE_object_data_transfer.h" +#include "BKE_data_transfer.h" #include "BKE_DerivedMesh.h" #include "BKE_dynamicpaint.h" #include "BKE_mesh_mapping.h" diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 7ad7f129218..8eed482327d 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -2200,13 +2200,20 @@ static void rna_def_space_view3d(BlenderRNA *brna) RNA_def_property_float_sdna(prop, NULL, "persmat"); RNA_def_property_clear_flag(prop, PROP_EDITABLE); /* XXX: for now, it's too risky for users to do this */ RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); - RNA_def_property_ui_text(prop, "Perspective Matrix", "Current perspective matrix of the 3D region"); + RNA_def_property_ui_text(prop, "Perspective Matrix", + "Current perspective matrix (``window_matrix * view_matrix``)"); + + prop = RNA_def_property(srna, "window_matrix", PROP_FLOAT, PROP_MATRIX); + RNA_def_property_float_sdna(prop, NULL, "winmat"); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); + RNA_def_property_ui_text(prop, "Window Matrix", "Current window matrix"); prop = RNA_def_property(srna, "view_matrix", PROP_FLOAT, PROP_MATRIX); RNA_def_property_float_sdna(prop, NULL, "viewmat"); RNA_def_property_multi_array(prop, 2, rna_matrix_dimsize_4x4); RNA_def_property_float_funcs(prop, NULL, "rna_RegionView3D_view_matrix_set", NULL); - RNA_def_property_ui_text(prop, "View Matrix", "Current view matrix of the 3D region"); + RNA_def_property_ui_text(prop, "View Matrix", "Current view matrix"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL); prop = RNA_def_property(srna, "view_perspective", PROP_ENUM, PROP_NONE); diff --git a/source/blender/modifiers/intern/MOD_datatransfer.c b/source/blender/modifiers/intern/MOD_datatransfer.c index 06f9d274576..2dca3218e41 100644 --- a/source/blender/modifiers/intern/MOD_datatransfer.c +++ b/source/blender/modifiers/intern/MOD_datatransfer.c @@ -37,7 +37,7 @@ #include "DNA_object_types.h" #include "BKE_customdata.h" -#include "BKE_object_data_transfer.h" +#include "BKE_data_transfer.h" #include "BKE_DerivedMesh.h" #include "BKE_library.h" #include "BKE_mesh_mapping.h" diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index c7170cfa4b4..35878f664ea 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -2721,12 +2721,13 @@ static void init_render_curve(Render *re, ObjectRen *obr, int timeoffset) vlr->v4= NULL; /* to prevent float accuracy issues, we calculate normal in local object space (not world) */ - if (area_tri_v3(co3, co2, co1)>FLT_EPSILON) { - if (negative_scale) - normal_tri_v3(tmp, co1, co2, co3); - else - normal_tri_v3(tmp, co3, co2, co1); - add_v3_v3(n, tmp); + if (normal_tri_v3(tmp, co1, co2, co3) > FLT_EPSILON) { + if (negative_scale == false) { + add_v3_v3(n, tmp); + } + else { + sub_v3_v3(n, tmp); + } } vlr->mat= matar[ dl->col ]; diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index e7b3de74a5c..1fc1348385b 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1707,16 +1707,12 @@ static int wm_handler_fileselect_do(bContext *C, ListBase *handlers, wmEventHand /* remlink now, for load file case before removing*/ BLI_remlink(handlers, handler); - + if (val != EVT_FILESELECT_EXTERNAL_CANCEL) { - if (screen != handler->filescreen) { - ED_screen_full_prevspace(C, CTX_wm_area(C)); - } - else { - ED_area_prevspace(C, CTX_wm_area(C)); - } + ScrArea *sa = CTX_wm_area(C); + ED_screen_retore_temp_type(C, sa, screen != handler->filescreen); } - + wm_handler_op_context(C, handler); /* needed for UI_popup_menu_reports */ diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index fabb69b8eff..c1c31f6795d 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -101,7 +101,6 @@ #include "GHOST_Path-api.h" #include "UI_interface.h" -#include "UI_interface_icons.h" #include "UI_view2d.h" #include "GPU_draw.h" @@ -895,24 +894,6 @@ bool write_crash_blend(void) } } -static void UNUSED_FUNCTION(wm_ensure_previews)(bContext *C, Main *mainvar) -{ - ListBase *lb[] = {&mainvar->mat, &mainvar->tex, &mainvar->image, &mainvar->world, &mainvar->lamp, NULL}; - ID *id; - int i; - - for (i = 0; lb[i]; i++) { - for (id = lb[i]->first; id; id = id->next) { - /* Only preview non-library datablocks, lib ones do not pertain to this .blend file! - * Same goes for ID with no user. */ - if (!id->lib && (id->us != 0)) { - UI_id_icon_render(C, id, false, false); - UI_id_icon_render(C, id, true, false); - } - } - } -} - /** * \see #wm_homefile_write_exec wraps #BLO_write_file in a similar way. */ diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index 5b944a7b1ec..02a029fc3f3 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -61,6 +61,7 @@ #include "BLI_blenlib.h" #include "BLI_dial.h" #include "BLI_dynstr.h" /*for WM_operator_pystring */ +#include "BLI_linklist_stack.h" #include "BLI_math.h" #include "BLI_utildefines.h" #include "BLI_ghash.h" @@ -76,6 +77,7 @@ #include "BKE_idprop.h" #include "BKE_image.h" #include "BKE_library.h" +#include "BKE_library_query.h" #include "BKE_global.h" #include "BKE_main.h" #include "BKE_material.h" @@ -105,6 +107,7 @@ #include "RNA_enum_types.h" #include "UI_interface.h" +#include "UI_interface_icons.h" #include "UI_resources.h" #include "WM_api.h" @@ -4705,6 +4708,90 @@ static void WM_OT_dependency_relations(wmOperatorType *ot) ot->exec = dependency_relations_exec; } +/* *************************** Mat/tex/etc. previews generation ************* */ + +typedef struct PreviewsIDEnsureStack { + Scene *scene; + + BLI_LINKSTACK_DECLARE(id_stack, ID *); +} PreviewsIDEnsureStack; + +static void previews_id_ensure(bContext *C, Scene *scene, ID *id) +{ + BLI_assert(ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA)); + + /* Only preview non-library datablocks, lib ones do not pertain to this .blend file! + * Same goes for ID with no user. */ + if (!id->lib && (id->us != 0)) { + UI_id_icon_render(C, scene, id, false, false); + UI_id_icon_render(C, scene, id, true, false); + } +} + +static bool previews_id_ensure_callback(void *todo_v, ID **idptr, int UNUSED(cd_flag)) +{ + PreviewsIDEnsureStack *todo = todo_v; + ID *id = *idptr; + + if (id && (id->flag & LIB_DOIT)) { + if (ELEM(GS(id->name), ID_MA, ID_TE, ID_IM, ID_WO, ID_LA)) { + previews_id_ensure(NULL, todo->scene, id); + } + id->flag &= ~LIB_DOIT; /* Tag the ID as done in any case. */ + BLI_LINKSTACK_PUSH(todo->id_stack, id); + } + + return true; +} + +static int previews_ensure_exec(bContext *C, wmOperator *UNUSED(op)) +{ + Main *bmain = CTX_data_main(C); + ListBase *lb[] = {&bmain->mat, &bmain->tex, &bmain->image, &bmain->world, &bmain->lamp, NULL}; + PreviewsIDEnsureStack preview_id_stack; + Scene *scene; + ID *id; + int i; + + /* We use LIB_DOIT to check whether we have already handled a given ID or not. */ + BKE_main_id_flag_all(bmain, LIB_DOIT, true); + + BLI_LINKSTACK_INIT(preview_id_stack.id_stack); + + for (scene = bmain->scene.first; scene; scene = scene->id.next) { + preview_id_stack.scene = scene; + id = (ID *)scene; + + do { + /* This will loop over all IDs linked by current one, render icons for them if needed, + * and add them to 'todo' preview_id_stack. */ + BKE_library_foreach_ID_link(id, previews_id_ensure_callback, &preview_id_stack, IDWALK_READONLY); + } while((id = BLI_LINKSTACK_POP(preview_id_stack.id_stack))); + } + + BLI_LINKSTACK_FREE(preview_id_stack.id_stack); + + /* Check a last time for ID not used (fake users only, in theory), and + * do our best for those, using current scene... */ + for (i = 0; lb[i]; i++) { + for (id = lb[i]->first; id; id = id->next) { + previews_id_ensure(C, NULL, id); + } + } + + return OPERATOR_FINISHED; +} + +static void WM_OT_previews_ensure(wmOperatorType *ot) +{ + ot->name = "Refresh DataBlock Previews"; + ot->idname = "WM_OT_previews_ensure"; + ot->description = "Ensure datablock previews are available and up-to-date " + "(to be saved in .blend file, only for some types like materials, textures, etc.)"; + + ot->exec = previews_ensure_exec; +} + /* ******************************************************* */ static void operatortype_ghash_free_cb(wmOperatorType *ot) @@ -4768,6 +4855,7 @@ void wm_operatortype_init(void) #if defined(WIN32) WM_operatortype_append(WM_OT_console_toggle); #endif + WM_operatortype_append(WM_OT_previews_ensure); } /* circleselect-like modal operators */ |