From 204113b791a8eea6087de61199df1d5811055244 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Wed, 7 Nov 2012 21:00:49 +0000 Subject: [PATCH 001/118] Fix #33107: cycles fixed threads 1 was still having two cores do work, because main thread works as well. --- intern/cycles/blender/blender_sync.cpp | 5 ++++- intern/cycles/device/device.cpp | 4 ++-- intern/cycles/device/device.h | 2 +- intern/cycles/device/device_cpu.cpp | 8 ++++---- intern/cycles/device/device_intern.h | 2 +- intern/cycles/render/session.cpp | 2 +- intern/cycles/util/util_task.cpp | 10 ++++++++-- intern/cycles/util/util_task.h | 5 ++++- 8 files changed, 25 insertions(+), 13 deletions(-) diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index c63f72c68c6..024cb1685d0 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -379,7 +379,10 @@ SessionParams BlenderSync::get_session_params(BL::RenderEngine b_engine, BL::Use params.start_resolution = get_int(cscene, "preview_start_resolution"); /* other parameters */ - params.threads = b_scene.render().threads(); + if(b_scene.render().threads_mode() == BL::RenderSettings::threads_mode_FIXED) + params.threads = b_scene.render().threads(); + else + params.threads = 0; params.cancel_timeout = get_float(cscene, "debug_cancel_timeout"); params.reset_timeout = get_float(cscene, "debug_reset_timeout"); diff --git a/intern/cycles/device/device.cpp b/intern/cycles/device/device.cpp index 550da2982a3..c6a2c678bac 100644 --- a/intern/cycles/device/device.cpp +++ b/intern/cycles/device/device.cpp @@ -78,13 +78,13 @@ void Device::draw_pixels(device_memory& rgba, int y, int w, int h, int dy, int w glDisable(GL_BLEND); } -Device *Device::create(DeviceInfo& info, Stats &stats, bool background, int threads) +Device *Device::create(DeviceInfo& info, Stats &stats, bool background) { Device *device; switch(info.type) { case DEVICE_CPU: - device = device_cpu_create(info, stats, threads); + device = device_cpu_create(info, stats); break; #ifdef WITH_CUDA case DEVICE_CUDA: diff --git a/intern/cycles/device/device.h b/intern/cycles/device/device.h index 95da0a89833..9840687b76a 100644 --- a/intern/cycles/device/device.h +++ b/intern/cycles/device/device.h @@ -134,7 +134,7 @@ public: virtual int device_number(Device *sub_device) { return 0; } /* static */ - static Device *create(DeviceInfo& info, Stats &stats, bool background = true, int threads = 0); + static Device *create(DeviceInfo& info, Stats &stats, bool background = true); static DeviceType type_from_string(const char *name); static string string_from_type(DeviceType type); diff --git a/intern/cycles/device/device_cpu.cpp b/intern/cycles/device/device_cpu.cpp index 519c458ffdf..bc280616615 100644 --- a/intern/cycles/device/device_cpu.cpp +++ b/intern/cycles/device/device_cpu.cpp @@ -45,7 +45,7 @@ public: TaskPool task_pool; KernelGlobals *kg; - CPUDevice(Stats &stats, int threads_num) : Device(stats) + CPUDevice(Stats &stats) : Device(stats) { kg = kernel_globals_create(); @@ -274,7 +274,7 @@ public: /* split task into smaller ones, more than number of threads for uneven * workloads where some parts of the image render slower than others */ list tasks; - task.split(tasks, TaskScheduler::num_threads()+1); + task.split(tasks, TaskScheduler::num_threads()); foreach(DeviceTask& task, tasks) task_pool.push(new CPUDeviceTask(this, task)); @@ -291,9 +291,9 @@ public: } }; -Device *device_cpu_create(DeviceInfo& info, Stats &stats, int threads) +Device *device_cpu_create(DeviceInfo& info, Stats &stats) { - return new CPUDevice(stats, threads); + return new CPUDevice(stats); } void device_cpu_info(vector& devices) diff --git a/intern/cycles/device/device_intern.h b/intern/cycles/device/device_intern.h index 02fbac6860e..b49ebba3e8b 100644 --- a/intern/cycles/device/device_intern.h +++ b/intern/cycles/device/device_intern.h @@ -23,7 +23,7 @@ CCL_NAMESPACE_BEGIN class Device; -Device *device_cpu_create(DeviceInfo& info, Stats &stats, int threads); +Device *device_cpu_create(DeviceInfo& info, Stats &stats); Device *device_opencl_create(DeviceInfo& info, Stats &stats, bool background); Device *device_cuda_create(DeviceInfo& info, Stats &stats, bool background); Device *device_network_create(DeviceInfo& info, Stats &stats, const char *address); diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 7303cb52ad8..024af8dede8 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -49,7 +49,7 @@ Session::Session(const SessionParams& params_) TaskScheduler::init(params.threads); - device = Device::create(params.device, stats, params.background, params.threads); + device = Device::create(params.device, stats, params.background); if(params.background) { buffers = NULL; diff --git a/intern/cycles/util/util_task.cpp b/intern/cycles/util/util_task.cpp index ea0abd6f54f..8c4ec312256 100644 --- a/intern/cycles/util/util_task.cpp +++ b/intern/cycles/util/util_task.cpp @@ -168,10 +168,16 @@ void TaskScheduler::init(int num_threads) if(users == 0) { do_exit = false; - /* launch threads that will be waiting for work */ - if(num_threads == 0) + if(num_threads == 0) { + /* automatic number of threads will be main thread + num cores */ num_threads = system_cpu_thread_count(); + } + else { + /* main thread will also work, for fixed threads we count it too */ + num_threads -= 1; + } + /* launch threads that will be waiting for work */ threads.resize(num_threads); thread_level.resize(num_threads); diff --git a/intern/cycles/util/util_task.h b/intern/cycles/util/util_task.h index a2f284479c7..b795ca7524b 100644 --- a/intern/cycles/util/util_task.h +++ b/intern/cycles/util/util_task.h @@ -94,7 +94,10 @@ public: static void init(int num_threads = 0); static void exit(); - static int num_threads() { return threads.size(); } + /* number of threads that can work on tasks, main thread counts too */ + static int num_threads() { return threads.size() + 1; } + + /* test if any session is using the scheduler */ static bool active() { return users != 0; } protected: From aa42934cef8a5f545518bbfe3d7ddf4825818b3b Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Wed, 7 Nov 2012 21:19:43 +0000 Subject: [PATCH 002/118] itask: reworked conditionals for osx version compatibility --- intern/itasc/kdl/chain.hpp | 9 +++++++-- intern/itasc/kdl/tree.hpp | 19 +++++++++++++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/intern/itasc/kdl/chain.hpp b/intern/itasc/kdl/chain.hpp index 24e40858bff..fde9d4ed23e 100644 --- a/intern/itasc/kdl/chain.hpp +++ b/intern/itasc/kdl/chain.hpp @@ -35,11 +35,16 @@ namespace KDL { */ class Chain { private: -#if !defined(__APPLE__) +#if defined(__APPLE__) +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 + std::vector segments; +# else // Eigen allocator is needed for alignment of Eigen data types std::vector > segments; +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ #else - std::vector segments; + // Eigen allocator is needed for alignment of Eigen data types + std::vector > segments; #endif unsigned int nrOfJoints; unsigned int nrOfSegments; diff --git a/intern/itasc/kdl/tree.hpp b/intern/itasc/kdl/tree.hpp index 4da764ac6d6..a020c6cf2cf 100644 --- a/intern/itasc/kdl/tree.hpp +++ b/intern/itasc/kdl/tree.hpp @@ -27,19 +27,30 @@ #include #include -#if !defined(__APPLE__) -#include +#if defined(__APPLE__) +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 + //no include +# else +# include +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ +#else +# include #endif namespace KDL { //Forward declaration class TreeElement; -#if !defined(__APPLE__) +#if defined(__APPLE__) +# if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_5 + typedef std::map SegmentMap; +# else // Eigen allocator is needed for alignment of Eigen data types typedef std::map, Eigen::aligned_allocator > > SegmentMap; +# endif /* MAC_OS_X_VERSION_MIN_REQUIRED */ #else - typedef std::map SegmentMap; + // Eigen allocator is needed for alignment of Eigen data types + typedef std::map, Eigen::aligned_allocator > > SegmentMap; #endif class TreeElement { From 620a78c106c4615a9e08d682fa099b889fad597c Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 7 Nov 2012 22:28:50 +0000 Subject: [PATCH 003/118] decimate - degenerate edges are now added back into the heap (with an dummy cost), so when surrounding geometry may be modified and the previously degenerate edge re-evaluated after. The C++ LOD decimator did this too. --- .../bmesh/intern/bmesh_decimate_collapse.c | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/intern/bmesh_decimate_collapse.c index 1f92a8f9227..f8b1a638558 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/intern/bmesh_decimate_collapse.c @@ -52,6 +52,7 @@ #define BOUNDARY_PRESERVE_WEIGHT 100.0f #define OPTIMIZE_EPS 0.01f /* FLT_EPSILON is too small, see [#33106] */ +#define COST_INVALID FLT_MAX typedef enum CD_UseFlag { CD_DO_VERT = (1 << 0), @@ -200,6 +201,16 @@ static void bm_decim_build_edge_cost_single(BMEdge *e, eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, cost, e); } + +/* use this for degenerate cases - add back to the heap with an invalid cost, + * this way it may be calculated again if surrounding geometry changes */ +static void bm_decim_invalid_edge_cost_single(BMEdge *e, + Heap *eheap, HeapNode **eheap_table) +{ + BLI_assert(eheap_table[BM_elem_index_get(e)] == NULL); + eheap_table[BM_elem_index_get(e)] = BLI_heap_insert(eheap, COST_INVALID, e); +} + static void bm_decim_build_edge_cost(BMesh *bm, const Quadric *vquadrics, const float *vweights, Heap *eheap, HeapNode **eheap_table) @@ -525,7 +536,7 @@ BLI_INLINE int bm_edge_is_manifold_or_boundary(BMLoop *l) #endif } -static int bm_edge_collapse_is_degenerate(BMEdge *e_first) +static int bm_edge_collapse_is_degenerate_topology(BMEdge *e_first) { /* simply check that there is no overlap between faces and edges of each vert, * (excluding the 2 faces attached to 'e' and 'e' its self) */ @@ -629,11 +640,6 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e { BMVert *v_other; - /* disallow collapsing which results in degenerate cases */ - if (bm_edge_collapse_is_degenerate(e_clear)) { - return FALSE; - } - v_other = BM_edge_other_vert(e_clear, v_clear); BLI_assert(v_other != NULL); @@ -781,12 +787,17 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, copy_v3_v3(v_clear_no, e->v2->no); #endif + /* disallow collapsing which results in degenerate cases */ + if (UNLIKELY(bm_edge_collapse_is_degenerate_topology(e))) { + bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */ + return; + } + bm_decim_calc_target_co(e, optimize_co, vquadrics); /* use for customdata merging */ if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) { customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co); - #if 0 /* simple test for stupid collapse */ if (customdata_fac < 0.0 - FLT_EPSILON || customdata_fac > 1.0f + FLT_EPSILON) { @@ -870,6 +881,10 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, /* end optional update */ #endif } + else { + /* add back with a high cost */ + bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); + } } @@ -925,7 +940,10 @@ void BM_mesh_decimate_collapse(BMesh *bm, const float factor, float *vweights, c #endif /* iterative edge collapse and maintain the eheap */ - while ((bm->totface > face_tot_target) && (BLI_heap_is_empty(eheap) == FALSE)) { + while ((bm->totface > face_tot_target) && + (BLI_heap_is_empty(eheap) == FALSE) && + (BLI_heap_node_value(BLI_heap_top(eheap)) != COST_INVALID)) + { // const float value = BLI_heap_node_value(BLI_heap_top(eheap)); BMEdge *e = BLI_heap_popmin(eheap); BLI_assert(BM_elem_index_get(e) < tot_edge_orig); /* handy to detect corruptions elsewhere */ From c0fb605a04d64d8efd5176ea1e7b217e7d2d768d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 7 Nov 2012 22:39:47 +0000 Subject: [PATCH 004/118] fix [#26472] Decimate overlaps polygons --- .../bmesh/intern/bmesh_decimate_collapse.c | 63 ++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/intern/bmesh_decimate_collapse.c index f8b1a638558..15f774e50a8 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/intern/bmesh_decimate_collapse.c @@ -133,6 +133,56 @@ static void bm_decim_calc_target_co(BMEdge *e, float optimize_co[3], } } +static int bm_edge_collapse_is_degenerate_flip(BMEdge *e, const float optimize_co[3]) +{ + BMIter liter; + BMLoop *l; + unsigned int i; + + for (i = 0; i < 2; i++) { + /* loop over both verts */ + BMVert *v = *((&e->v1) + i); + + BM_ITER_ELEM (l, &liter, v, BM_LOOPS_OF_VERT) { + if (l->e != e && l->prev->e != e) { + float *co_prev = l->prev->v->co; + float *co_next = l->next->v->co; + float cross_exist[3]; + float cross_optim[3]; + +#if 1 + float vec_other[3]; /* line between the two outer verts, re-use for both cross products */ + float vec_exist[3]; /* before collapse */ + float vec_optim[3]; /* after collapse */ + + sub_v3_v3v3(vec_other, co_prev, co_next); + sub_v3_v3v3(vec_exist, co_prev, v->co); + sub_v3_v3v3(vec_optim, co_prev, optimize_co); + + cross_v3_v3v3(cross_exist, vec_other, vec_exist); + cross_v3_v3v3(cross_optim, vec_other, vec_optim); + + /* normalize isn't really needed, but ensures the value at a unit we can compare against */ + normalize_v3(cross_exist); + normalize_v3(cross_optim); +#else + normal_tri_v3(cross_exist, v->co, co_prev, co_next); + normal_tri_v3(cross_optim, optimize_co, co_prev, co_next); +#endif + + /* use a small value rather then zero so we don't flip a face in multiple steps + * (first making it zero area, then flipping again)*/ + if (dot_v3v3(cross_exist, cross_optim) <= FLT_EPSILON) { + //printf("no flip\n"); + return TRUE; + } + } + } + } + + return FALSE; +} + static void bm_decim_build_edge_cost_single(BMEdge *e, const Quadric *vquadrics, const float *vweights, Heap *eheap, HeapNode **eheap_table) @@ -795,6 +845,12 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, bm_decim_calc_target_co(e, optimize_co, vquadrics); + /* check if this would result in an overlapping face */ + if (UNLIKELY(bm_edge_collapse_is_degenerate_flip(e, optimize_co))) { + bm_decim_invalid_edge_cost_single(e, eheap, eheap_table); /* add back with a high cost */ + return; + } + /* use for customdata merging */ if (LIKELY(compare_v3v3(e->v1->co, e->v2->co, FLT_EPSILON) == FALSE)) { customdata_fac = line_point_factor_v3(optimize_co, e->v1->co, e->v2->co); @@ -859,7 +915,10 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, } while ((e_iter = bmesh_disk_edge_next(e_iter, v_other)) != e_first); } -#if 0 + /* this block used to be disabled, + * but enable now since surrounding faces may have been + * set to COST_INVALID because of a face overlap that no longer occurs */ +#if 1 /* optional, update edges around the vertex face fan */ { BMIter liter; @@ -874,7 +933,7 @@ static void bm_decim_edge_collapse(BMesh *bm, BMEdge *e, BLI_assert(BM_vert_in_edge(e_outer, l->v) == FALSE); - bm_decim_build_edge_cost_single(e_outer, vquadrics, eheap, eheap_table); + bm_decim_build_edge_cost_single(e_outer, vquadrics, vweights, eheap, eheap_table); } } } From 353ad46e105909a3c9217e24bcde0411da916fcc Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 7 Nov 2012 23:52:33 +0000 Subject: [PATCH 005/118] code cleanup: quiet double promotion warnings --- intern/cycles/device/device_task.cpp | 2 +- intern/cycles/kernel/svm/svm_geometry.h | 2 +- intern/cycles/render/session.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/intern/cycles/device/device_task.cpp b/intern/cycles/device/device_task.cpp index c85e182d629..b3f02deaf6f 100644 --- a/intern/cycles/device/device_task.cpp +++ b/intern/cycles/device/device_task.cpp @@ -101,7 +101,7 @@ void DeviceTask::update_progress(RenderTile &rtile) if(update_tile_sample) { double current_time = time_dt(); - if (current_time - last_update_time >= 1.0f) { + if (current_time - last_update_time >= 1.0) { update_tile_sample(rtile); last_update_time = current_time; diff --git a/intern/cycles/kernel/svm/svm_geometry.h b/intern/cycles/kernel/svm/svm_geometry.h index 68177493f4e..c4d03c1f948 100644 --- a/intern/cycles/kernel/svm/svm_geometry.h +++ b/intern/cycles/kernel/svm/svm_geometry.h @@ -34,7 +34,7 @@ __device void svm_node_geometry(KernelGlobals *kg, ShaderData *sd, float *stack, if(attr_offset != ATTR_STD_NOT_FOUND) { data = triangle_attribute_float3(kg, sd, ATTR_ELEMENT_VERTEX, attr_offset, NULL, NULL); - data = make_float3(-(data.y - 0.5), (data.x - 0.5), 0.0f); + data = make_float3(-(data.y - 0.5f), (data.x - 0.5f), 0.0f); object_normal_transform(kg, sd, &data); data = cross(sd->N, normalize(cross(data, sd->N)));; } diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 024af8dede8..7f6b43c1e00 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -818,7 +818,7 @@ bool Session::update_progressive_refine(bool cancel) double current_time = time_dt(); - if (current_time - last_update_time < 1.0f) { + if (current_time - last_update_time < 1.0) { /* if last sample was processed, we need to write buffers anyway */ if (!write) return false; From a9132591e6d75e650e1508b796800c50b4f2f87f Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Wed, 7 Nov 2012 23:55:52 +0000 Subject: [PATCH 006/118] code cleanup: linearrgb_to_srgb_ushort4_predivide() was calling `linearrgb_to_srgb(t) * alpha` twice in the FTOUSHORT macro, which gcc didn't optimize out. --- source/blender/blenlib/intern/math_color_inline.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/blenlib/intern/math_color_inline.c b/source/blender/blenlib/intern/math_color_inline.c index f520b2318e5..4c8bd43ef73 100644 --- a/source/blender/blenlib/intern/math_color_inline.c +++ b/source/blender/blenlib/intern/math_color_inline.c @@ -164,7 +164,11 @@ MINLINE void linearrgb_to_srgb_ushort4_predivide(unsigned short srgb[4], const f for (i = 0; i < 3; ++i) { t = linear[i] * inv_alpha; - srgb[i] = (t < 1.0f) ? (unsigned short) (to_srgb_table_lookup(t) * alpha) : FTOUSHORT(linearrgb_to_srgb(t) * alpha); + srgb[i] = (t <= 1.0f) ? + /* warning - converts: float -> short -> float -> short */ + (unsigned short) (to_srgb_table_lookup(t) * alpha) : + /* if FTOUSHORT was an inline function this could be done less confusingly */ + ((t = linearrgb_to_srgb(t) * alpha), FTOUSHORT(t)); } srgb[3] = FTOUSHORT(linear[3]); From 374238b7ef1c4c6df8e87b0d33bd8dce9dc71dc0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Nov 2012 02:12:31 +0000 Subject: [PATCH 007/118] code improvements for selecting the shortest path for mesh editmode, this will give some speedup but its mainly to simplify the function. - use bmesh adjacency data, was building its own data, left over from pre-bmesh. - use a flag to store visited edges rather then a hash. - store edge pointers in the heap rather then index values (was converting back and fourth a lot). --- source/blender/editors/mesh/editmesh_select.c | 131 +++++++----------- 1 file changed, 51 insertions(+), 80 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 0379068afd9..88f8113f1c6 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1186,8 +1186,7 @@ static float edgetag_cut_cost(BMEditMesh *UNUSED(em), BMEdge *e1, BMEdge *e2, BM /* The cost is based on the simple sum of the length of the two edgees... */ sub_v3_v3v3(d1, v->co, v1->co); sub_v3_v3v3(d2, v2->co, v->co); - cost = len_v3(d1); - cost += len_v3(d2); + cost = len_v3(d1) + len_v3(d2); /* but is biased to give higher values to sharp turns, so that it will take * paths with fewer "turns" when selecting between equal-weighted paths between @@ -1197,29 +1196,26 @@ static float edgetag_cut_cost(BMEditMesh *UNUSED(em), BMEdge *e1, BMEdge *e2, BM return cost; } -static void edgetag_add_adjacent(BMEditMesh *em, SmallHash *visithash, Heap *heap, int mednum, int vertnum, - int *nedges, int *edges, int *prevedge, float *cost) +static void edgetag_add_adjacent(BMEditMesh *em, Heap *heap, + BMEdge *e1, BMVert *v, + int *prevedge, float *cost) { - BMEdge *e1 = EDBM_edge_at_index(em, mednum); - BMVert *v = EDBM_vert_at_index(em, vertnum); - int startadj, endadj = nedges[vertnum + 1]; + BMIter eiter; + BMEdge *e2; - for (startadj = nedges[vertnum]; startadj < endadj; startadj++) { - int adjnum = edges[startadj]; - BMEdge *e2 = EDBM_edge_at_index(em, adjnum); - float newcost; - float cutcost; + const int e1_index = BM_elem_index_get(e1); - if (BLI_smallhash_haskey(visithash, (uintptr_t)e2)) - continue; + BM_ITER_ELEM (e2, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e2, BM_ELEM_TAG)) { + const int e2_index = BM_elem_index_get(e2); + const float cost_cut = edgetag_cut_cost(em, e1, e2, v); + const float cost_new = cost[e1_index] + cost_cut; - cutcost = edgetag_cut_cost(em, e1, e2, v); - newcost = cost[mednum] + cutcost; - - if (cost[adjnum] > newcost) { - cost[adjnum] = newcost; - prevedge[adjnum] = mednum; - BLI_heap_insert(heap, newcost, SET_INT_IN_POINTER(adjnum)); + if (cost[e2_index] > cost_new) { + cost[e2_index] = cost_new; + prevedge[e2_index] = e1_index; + BLI_heap_insert(heap, cost_new, e2); + } } } } @@ -1269,67 +1265,44 @@ static int edgetag_context_check(Scene *scene, BMEditMesh *em, BMEdge *e) return 0; } -static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, BMEdge *target) +static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *e_src, BMEdge *e_dst) { + /* BM_ELEM_TAG flag is used to store visited edges */ BMEdge *e; - BMIter iter; + BMIter eiter; Heap *heap; - SmallHash visithash; float *cost; - int i, totvert = 0, totedge = 0, *nedges, *edges, *prevedge, mednum = -1, nedgeswap = 0; - int targetnum; - - BLI_smallhash_init(&visithash); + int *prevedge; + int i, totedge; /* note, would pass BM_EDGE except we are looping over all edges anyway */ BM_mesh_elem_index_ensure(em->bm, BM_VERT /* | BM_EDGE */); - BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) { - BLI_smallhash_insert(&visithash, (uintptr_t)e, NULL); + BM_ITER_MESH_INDEX (e, &eiter, em->bm, BM_EDGES_OF_MESH, i) { + if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == FALSE) { + BM_elem_flag_disable(e, BM_ELEM_TAG); + } + else { + BM_elem_flag_enable(e, BM_ELEM_TAG); } - BM_elem_index_set(e, totedge); /* set_inline */ - totedge++; + BM_elem_index_set(e, i); /* set_inline */ } em->bm->elem_index_dirty &= ~BM_EDGE; /* alloc */ - totvert = em->bm->totvert; - nedges = MEM_callocN(sizeof(*nedges) * totvert + 1, "SeamPathNEdges"); - edges = MEM_mallocN(sizeof(*edges) * totedge * 2, "SeamPathEdges"); + totedge = em->bm->totedge; prevedge = MEM_mallocN(sizeof(*prevedge) * totedge, "SeamPathPrevious"); cost = MEM_mallocN(sizeof(*cost) * totedge, "SeamPathCost"); - /* count edges, compute adjacent edges offsets and fill adjacent */ - BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - nedges[BM_elem_index_get(e->v1) + 1]++; - nedges[BM_elem_index_get(e->v2) + 1]++; - } - - for (i = 1; i < totvert; i++) { - int newswap = nedges[i + 1]; - nedges[i + 1] = nedgeswap + nedges[i]; - nedgeswap = newswap; - } - nedges[0] = nedges[1] = 0; - - i = 0; - BM_ITER_MESH (e, &iter, em->bm, BM_EDGES_OF_MESH) { - edges[nedges[BM_elem_index_get(e->v1) + 1]++] = i; - edges[nedges[BM_elem_index_get(e->v2) + 1]++] = i; - + for (i = 0; i < totedge; i++) { cost[i] = 1e20f; prevedge[i] = -1; - i++; } /* * Arrays are now filled as follows: * - * nedges[n] = sum of the # of edges incident to all vertices numbered 0 through n - 1 - * edges[edges[n]..edges[n - 1]] = the indices of of the edges incident to vertex n - * * As the search continues, prevedge[n] will be the previous edge on the shortest * path found so far to edge n. The visitedhash will of course contain entries * for edges that have been visited, cost[n] will contain the length of the shortest @@ -1340,61 +1313,59 @@ static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *source, B /* regular dijkstra shortest path, but over edges instead of vertices */ heap = BLI_heap_new(); - BLI_heap_insert(heap, 0.0f, SET_INT_IN_POINTER(BM_elem_index_get(source))); - cost[BM_elem_index_get(source)] = 0.0f; + BLI_heap_insert(heap, 0.0f, e_src); + cost[BM_elem_index_get(e_src)] = 0.0f; EDBM_index_arrays_init(em, 1, 1, 0); - targetnum = BM_elem_index_get(target); + e = NULL; while (!BLI_heap_is_empty(heap)) { - mednum = GET_INT_FROM_POINTER(BLI_heap_popmin(heap)); - e = EDBM_edge_at_index(em, mednum); + e = BLI_heap_popmin(heap); - if (mednum == targetnum) + if (e == e_dst) break; - if (BLI_smallhash_haskey(&visithash, (uintptr_t)e)) + if (BM_elem_flag_test(e, BM_ELEM_TAG)) { continue; + } - BLI_smallhash_insert(&visithash, (uintptr_t)e, NULL); + BM_elem_flag_enable(e, BM_ELEM_TAG); - edgetag_add_adjacent(em, &visithash, heap, mednum, BM_elem_index_get(e->v1), nedges, edges, prevedge, cost); - edgetag_add_adjacent(em, &visithash, heap, mednum, BM_elem_index_get(e->v2), nedges, edges, prevedge, cost); + edgetag_add_adjacent(em, heap, e, e->v1, prevedge, cost); + edgetag_add_adjacent(em, heap, e, e->v2, prevedge, cost); } - if (mednum == targetnum) { + if (e == e_dst) { short allseams = 1; + int e_index; /* Check whether the path is already completely tagged. * if it is, the tags will be cleared instead of set. */ - mednum = targetnum; + e_index = BM_elem_index_get(e_dst); do { - e = EDBM_edge_at_index(em, mednum); + e = EDBM_edge_at_index(em, e_index); if (!edgetag_context_check(scene, em, e)) { allseams = 0; break; } - mednum = prevedge[mednum]; - } while (mednum != BM_elem_index_get(source)); + e_index = prevedge[e_index]; + } while (e != e_src); /* Follow path back and source and add or remove tags */ - mednum = targetnum; + e_index = BM_elem_index_get(e_dst); do { - e = EDBM_edge_at_index(em, mednum); + e = EDBM_edge_at_index(em, e_index); if (allseams) edgetag_context_set(em, scene, e, 0); else edgetag_context_set(em, scene, e, 1); - mednum = prevedge[mednum]; - } while (mednum != -1); + e_index = prevedge[e_index]; + } while (e_index != -1); } EDBM_index_arrays_free(em); - MEM_freeN(nedges); - MEM_freeN(edges); MEM_freeN(prevedge); MEM_freeN(cost); BLI_heap_free(heap, NULL); - BLI_smallhash_release(&visithash); return 1; } From 5b0ee040a3f35584da9c553d8f25cb715314d087 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Nov 2012 02:33:26 +0000 Subject: [PATCH 008/118] further cleanup for selecting the shortest path, remove the need for EDBM_index_arrays_* functions. --- source/blender/editors/mesh/editmesh_select.c | 95 +++++++------------ 1 file changed, 36 insertions(+), 59 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 88f8113f1c6..55a2abb1c45 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1177,7 +1177,7 @@ void MESH_OT_edgering_select(wmOperatorType *ot) /* ******************* edgetag_shortest_path and helpers ****************** */ -static float edgetag_cut_cost(BMEditMesh *UNUSED(em), BMEdge *e1, BMEdge *e2, BMVert *v) +static float edgetag_cut_cost(BMEdge *e1, BMEdge *e2, BMVert *v) { BMVert *v1 = (e1->v1 == v) ? e1->v2 : e1->v1; BMVert *v2 = (e2->v1 == v) ? e2->v2 : e2->v1; @@ -1196,9 +1196,7 @@ static float edgetag_cut_cost(BMEditMesh *UNUSED(em), BMEdge *e1, BMEdge *e2, BM return cost; } -static void edgetag_add_adjacent(BMEditMesh *em, Heap *heap, - BMEdge *e1, BMVert *v, - int *prevedge, float *cost) +static void edgetag_add_adjacent(Heap *heap, BMEdge *e1, BMVert *v, BMEdge **edges_prev, float *cost) { BMIter eiter; BMEdge *e2; @@ -1208,24 +1206,24 @@ static void edgetag_add_adjacent(BMEditMesh *em, Heap *heap, BM_ITER_ELEM (e2, &eiter, v, BM_EDGES_OF_VERT) { if (!BM_elem_flag_test(e2, BM_ELEM_TAG)) { const int e2_index = BM_elem_index_get(e2); - const float cost_cut = edgetag_cut_cost(em, e1, e2, v); + const float cost_cut = edgetag_cut_cost(e1, e2, v); const float cost_new = cost[e1_index] + cost_cut; if (cost[e2_index] > cost_new) { cost[e2_index] = cost_new; - prevedge[e2_index] = e1_index; + edges_prev[e2_index] = e1; BLI_heap_insert(heap, cost_new, e2); } } } } -static void edgetag_context_set(BMEditMesh *em, Scene *scene, BMEdge *e, int val) +static void edgetag_context_set(BMesh *bm, Scene *scene, BMEdge *e, int val) { switch (scene->toolsettings->edge_mode) { case EDGE_MODE_SELECT: - BM_edge_select_set(em->bm, e, val); + BM_edge_select_set(bm, e, val); break; case EDGE_MODE_TAG_SEAM: BM_elem_flag_set(e, BM_ELEM_SEAM, val); @@ -1234,51 +1232,45 @@ static void edgetag_context_set(BMEditMesh *em, Scene *scene, BMEdge *e, int val BM_elem_flag_set(e, BM_ELEM_SMOOTH, !val); break; case EDGE_MODE_TAG_CREASE: - { - float *crease = CustomData_bmesh_get(&em->bm->edata, e->head.data, CD_CREASE); - *crease = (val) ? 1.0f : 0.0f; + BM_elem_float_data_set(&bm->edata, e, CD_CREASE, (val) ? 1.0f : 0.0f); break; - } case EDGE_MODE_TAG_BEVEL: - { - float *bweight = CustomData_bmesh_get(&em->bm->edata, e->head.data, CD_BWEIGHT); - *bweight = (val) ? 1.0f : 0.0f; + BM_elem_float_data_set(&bm->edata, e, CD_BWEIGHT, (val) ? 1.0f : 0.0f); break; - } } } -static int edgetag_context_check(Scene *scene, BMEditMesh *em, BMEdge *e) +static int edgetag_context_check(Scene *scene, BMesh *bm, BMEdge *e) { switch (scene->toolsettings->edge_mode) { case EDGE_MODE_SELECT: - return BM_elem_flag_test(e, BM_ELEM_SELECT) ? 1 : 0; + return BM_elem_flag_test(e, BM_ELEM_SELECT) ? TRUE : FALSE; case EDGE_MODE_TAG_SEAM: return BM_elem_flag_test(e, BM_ELEM_SEAM); case EDGE_MODE_TAG_SHARP: return !BM_elem_flag_test(e, BM_ELEM_SMOOTH); case EDGE_MODE_TAG_CREASE: - return BM_elem_float_data_get(&em->bm->edata, e, CD_CREASE) ? 1 : 0; + return BM_elem_float_data_get(&bm->edata, e, CD_CREASE) ? TRUE : FALSE; case EDGE_MODE_TAG_BEVEL: - return BM_elem_float_data_get(&em->bm->edata, e, CD_BWEIGHT) ? 1 : 0; + return BM_elem_float_data_get(&bm->edata, e, CD_BWEIGHT) ? TRUE : FALSE; } return 0; } -static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *e_src, BMEdge *e_dst) +static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge *e_dst) { /* BM_ELEM_TAG flag is used to store visited edges */ BMEdge *e; BMIter eiter; Heap *heap; float *cost; - int *prevedge; + BMEdge **edges_prev; int i, totedge; /* note, would pass BM_EDGE except we are looping over all edges anyway */ - BM_mesh_elem_index_ensure(em->bm, BM_VERT /* | BM_EDGE */); + BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); - BM_ITER_MESH_INDEX (e, &eiter, em->bm, BM_EDGES_OF_MESH, i) { + BM_ITER_MESH_INDEX (e, &eiter, bm, BM_EDGES_OF_MESH, i) { if (BM_elem_flag_test(e, BM_ELEM_HIDDEN) == FALSE) { BM_elem_flag_disable(e, BM_ELEM_TAG); } @@ -1288,17 +1280,14 @@ static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *e_src, BM BM_elem_index_set(e, i); /* set_inline */ } - em->bm->elem_index_dirty &= ~BM_EDGE; + bm->elem_index_dirty &= ~BM_EDGE; /* alloc */ - totedge = em->bm->totedge; - prevedge = MEM_mallocN(sizeof(*prevedge) * totedge, "SeamPathPrevious"); + totedge = bm->totedge; + edges_prev = MEM_callocN(sizeof(*edges_prev) * totedge, "SeamPathPrevious"); cost = MEM_mallocN(sizeof(*cost) * totedge, "SeamPathCost"); - for (i = 0; i < totedge; i++) { - cost[i] = 1e20f; - prevedge[i] = -1; - } + fill_vn_fl(cost, totedge, 1e20f); /* * Arrays are now filled as follows: @@ -1315,55 +1304,43 @@ static int edgetag_shortest_path(Scene *scene, BMEditMesh *em, BMEdge *e_src, BM heap = BLI_heap_new(); BLI_heap_insert(heap, 0.0f, e_src); cost[BM_elem_index_get(e_src)] = 0.0f; - EDBM_index_arrays_init(em, 1, 1, 0); e = NULL; + while (!BLI_heap_is_empty(heap)) { e = BLI_heap_popmin(heap); if (e == e_dst) break; - if (BM_elem_flag_test(e, BM_ELEM_TAG)) { - continue; + if (!BM_elem_flag_test(e, BM_ELEM_TAG)) { + BM_elem_flag_enable(e, BM_ELEM_TAG); + edgetag_add_adjacent(heap, e, e->v1, edges_prev, cost); + edgetag_add_adjacent(heap, e, e->v2, edges_prev, cost); } - - BM_elem_flag_enable(e, BM_ELEM_TAG); - - edgetag_add_adjacent(em, heap, e, e->v1, prevedge, cost); - edgetag_add_adjacent(em, heap, e, e->v2, prevedge, cost); } if (e == e_dst) { short allseams = 1; - int e_index; /* Check whether the path is already completely tagged. * if it is, the tags will be cleared instead of set. */ - e_index = BM_elem_index_get(e_dst); + e = e_dst; do { - e = EDBM_edge_at_index(em, e_index); - if (!edgetag_context_check(scene, em, e)) { + if (!edgetag_context_check(scene, bm, e)) { allseams = 0; break; } - e_index = prevedge[e_index]; - } while (e != e_src); + } while ((e = edges_prev[BM_elem_index_get(e)])); /* Follow path back and source and add or remove tags */ - e_index = BM_elem_index_get(e_dst); + e = e_dst; do { - e = EDBM_edge_at_index(em, e_index); - if (allseams) - edgetag_context_set(em, scene, e, 0); - else - edgetag_context_set(em, scene, e, 1); - e_index = prevedge[e_index]; - } while (e_index != -1); + edgetag_context_set(bm, scene, e, !allseams); + } while ((e = edges_prev[BM_elem_index_get(e)])); } - EDBM_index_arrays_free(em); - MEM_freeN(prevedge); + MEM_freeN(edges_prev); MEM_freeN(cost); BLI_heap_free(heap, NULL); @@ -1397,7 +1374,7 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) BMEdge *e_act; e_act = (BMEdge *)ese->ele; if (e_act != e) { - if (edgetag_shortest_path(vc.scene, em, e_act, e)) { + if (edgetag_shortest_path(vc.scene, em->bm, e_act, e)) { BM_select_history_remove(em->bm, e_act); path = 1; } @@ -1405,14 +1382,14 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) } } if (path == 0) { - int act = (edgetag_context_check(vc.scene, em, e) == 0); - edgetag_context_set(em, vc.scene, e, act); /* switch the edge option */ + int act = (edgetag_context_check(vc.scene, em->bm, e) == 0); + edgetag_context_set(em->bm, vc.scene, e, act); /* switch the edge option */ } EDBM_selectmode_flush(em); /* even if this is selected it may not be in the selection list */ - if (edgetag_context_check(vc.scene, em, e) == 0) + if (edgetag_context_check(vc.scene, em->bm, e) == 0) BM_select_history_remove(em->bm, e); else BM_select_history_store(em->bm, e); From 9bdfb82f05fab6ef626756d989229db4de8bae98 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Nov 2012 03:19:21 +0000 Subject: [PATCH 009/118] add mesh editmode Ctrl+RMB to select the shortest path between faces, works the same as for edges. Request from Kjartan. --- source/blender/editors/mesh/editmesh_select.c | 264 ++++++++++++++++-- 1 file changed, 241 insertions(+), 23 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 55a2abb1c45..17c6ebb8801 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1350,21 +1350,15 @@ static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge /* ******************* mesh shortest path select, uses prev-selected edge ****************** */ /* since you want to create paths with multiple selects, it doesn't have extend option */ -static int mouse_mesh_shortest_path(bContext *C, int mval[2]) +static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc) { - ViewContext vc; - BMEditMesh *em; + BMEditMesh *em = vc->em; BMEdge *e; float dist = 75.0f; - em_setup_viewcontext(C, &vc); - vc.mval[0] = mval[0]; - vc.mval[1] = mval[1]; - em = vc.em; - - e = EDBM_edge_find_nearest(&vc, &dist); + e = EDBM_edge_find_nearest(vc, &dist); if (e) { - Mesh *me = vc.obedit->data; + Mesh *me = vc->obedit->data; int path = 0; if (em->bm->selected.last) { @@ -1374,7 +1368,7 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) BMEdge *e_act; e_act = (BMEdge *)ese->ele; if (e_act != e) { - if (edgetag_shortest_path(vc.scene, em->bm, e_act, e)) { + if (edgetag_shortest_path(vc->scene, em->bm, e_act, e)) { BM_select_history_remove(em->bm, e_act); path = 1; } @@ -1382,14 +1376,14 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) } } if (path == 0) { - int act = (edgetag_context_check(vc.scene, em->bm, e) == 0); - edgetag_context_set(em->bm, vc.scene, e, act); /* switch the edge option */ + int act = (edgetag_context_check(vc->scene, em->bm, e) == 0); + edgetag_context_set(em->bm, vc->scene, e, act); /* switch the edge option */ } EDBM_selectmode_flush(em); /* even if this is selected it may not be in the selection list */ - if (edgetag_context_check(vc.scene, em->bm, e) == 0) + if (edgetag_context_check(vc->scene, em->bm, e) == 0) BM_select_history_remove(em->bm, e); else BM_select_history_store(em->bm, e); @@ -1399,7 +1393,7 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) case EDGE_MODE_TAG_SEAM: me->drawflag |= ME_DRAWSEAMS; - ED_uvedit_live_unwrap(vc.scene, vc.obedit); + ED_uvedit_live_unwrap(vc->scene, vc->obedit); break; case EDGE_MODE_TAG_SHARP: me->drawflag |= ME_DRAWSHARP; @@ -1422,25 +1416,249 @@ static int mouse_mesh_shortest_path(bContext *C, int mval[2]) } -static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) -{ - - view3d_operator_needs_opengl(C); +/* ******************* facetag_shortest_path and helpers ****************** */ - if (mouse_mesh_shortest_path(C, event->mval)) { - return OPERATOR_FINISHED; + +static float facetag_cut_cost(BMFace *f1, BMFace *f2, BMEdge *e) +{ + float cost, d1[3], d2[3]; + + float f1_cent[3]; + float f2_cent[3]; + float e_cent[3]; + + BM_face_calc_center_mean(f1, f1_cent); + BM_face_calc_center_mean(f2, f2_cent); + mid_v3_v3v3(e_cent, e->v1->co, e->v2->co); + + /* The cost is based on the simple sum of the length of the two edgees... */ + sub_v3_v3v3(d1, e_cent, f1_cent); + sub_v3_v3v3(d2, f2_cent, e_cent); + cost = len_v3(d1) + len_v3(d2); + + /* but is biased to give higher values to sharp turns, so that it will take + * paths with fewer "turns" when selecting between equal-weighted paths between + * the two edges */ + cost = cost + 0.5f * cost * (2.0f - sqrtf(fabsf(dot_v3v3(d1, d2)))); + + return cost; +} + +static void facetag_add_adjacent(Heap *heap, BMFace *f1, BMFace **faces_prev, float *cost) +{ + BMIter liter; + BMLoop *l2; + BMFace *f2; + + const int f1_index = BM_elem_index_get(f1); + + /* loop over faces of face, but do so by first looping over loops */ + BM_ITER_ELEM (l2, &liter, f1, BM_LOOPS_OF_FACE) { + BMLoop *l_first; + BMLoop *l_iter; + + l_iter = l_first = l2; + do { + f2 = l_iter->f; + if (!BM_elem_flag_test(f2, BM_ELEM_TAG)) { + /* we know 'f2' is not visited, check it out! */ + const int f2_index = BM_elem_index_get(f2); + const float cost_cut = facetag_cut_cost(f1, f2, l_iter->e); + const float cost_new = cost[f1_index] + cost_cut; + + if (cost[f2_index] > cost_new) { + cost[f2_index] = cost_new; + faces_prev[f2_index] = f1; + BLI_heap_insert(heap, cost_new, f2); + } + } + } while ((l_iter = l_iter->radial_next) != l_first); + } +} + +static void facetag_context_set(BMesh *bm, Scene *UNUSED(scene), BMFace *f, int val) +{ + BM_face_select_set(bm, f, val); +} + +static int facetag_context_check(Scene *UNUSED(scene), BMesh *UNUSED(bm), BMFace *f) +{ + return BM_elem_flag_test(f, BM_ELEM_SELECT) ? 1 : 0; +} + +static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace *f_dst) +{ + /* BM_ELEM_TAG flag is used to store visited edges */ + BMFace *f; + BMIter fiter; + Heap *heap; + float *cost; + BMFace **faces_prev; + int i, totface; + + /* note, would pass BM_EDGE except we are looping over all faces anyway */ + // BM_mesh_elem_index_ensure(bm, BM_VERT /* | BM_EDGE */); // NOT NEEDED FOR FACETAG + + BM_ITER_MESH_INDEX (f, &fiter, bm, BM_FACES_OF_MESH, i) { + if (BM_elem_flag_test(f, BM_ELEM_HIDDEN) == FALSE) { + BM_elem_flag_disable(f, BM_ELEM_TAG); + } + else { + BM_elem_flag_enable(f, BM_ELEM_TAG); + } + + BM_elem_index_set(f, i); /* set_inline */ + } + bm->elem_index_dirty &= ~BM_FACE; + + /* alloc */ + totface = bm->totface; + faces_prev = MEM_callocN(sizeof(*faces_prev) * totface, "SeamPathPrevious"); + cost = MEM_mallocN(sizeof(*cost) * totface, "SeamPathCost"); + + fill_vn_fl(cost, totface, 1e20f); + + /* + * Arrays are now filled as follows: + * + * As the search continues, faces_prev[n] will be the previous face on the shortest + * path found so far to face n. The visitedhash will of course contain entries + * for faces that have been visited, cost[n] will contain the length of the shortest + * path to face n found so far, Finally, heap is a priority heap which is built on the + * the same data as the cost array, but inverted: it is a worklist of faces prioritized + * by the shortest path found so far to the face. + */ + + /* regular dijkstra shortest path, but over faces instead of vertices */ + heap = BLI_heap_new(); + BLI_heap_insert(heap, 0.0f, f_src); + cost[BM_elem_index_get(f_src)] = 0.0f; + + f = NULL; + + while (!BLI_heap_is_empty(heap)) { + f = BLI_heap_popmin(heap); + + if (f == f_dst) + break; + + if (!BM_elem_flag_test(f, BM_ELEM_TAG)) { + BM_elem_flag_enable(f, BM_ELEM_TAG); + facetag_add_adjacent(heap, f, faces_prev, cost); + } + } + + if (f == f_dst) { + short allseams = 1; + + /* Check whether the path is already completely tagged. + * if it is, the tags will be cleared instead of set. */ + f = f_dst; + do { + if (!facetag_context_check(scene, bm, f)) { + allseams = 0; + break; + } + } while ((f = faces_prev[BM_elem_index_get(f)])); + + /* Follow path back and source and add or remove tags */ + f = f_dst; + do { + facetag_context_set(bm, scene, f, !allseams); + } while ((f = faces_prev[BM_elem_index_get(f)])); + } + + MEM_freeN(faces_prev); + MEM_freeN(cost); + BLI_heap_free(heap, NULL); + + return 1; +} + +static int mouse_mesh_shortest_path_face(bContext *C, ViewContext *vc) +{ + BMEditMesh *em = vc->em; + BMFace *f; + float dist = 75.0f; + + f = EDBM_face_find_nearest(vc, &dist); + if (f) { + int path = 0; + BMFace *f_act = BM_active_face_get(em->bm, FALSE, TRUE); + + if (f_act) { + if (f_act != f) { + if (facetag_shortest_path(vc->scene, em->bm, f_act, f)) { + BM_select_history_remove(em->bm, f_act); + path = 1; + } + } + } + if (path == 0) { + int act = (facetag_context_check(vc->scene, em->bm, f) == 0); + facetag_context_set(em->bm, vc->scene, f, act); /* switch the face option */ + } + + EDBM_selectmode_flush(em); + + /* even if this is selected it may not be in the selection list */ + if (facetag_context_check(vc->scene, em->bm, f) == 0) + BM_select_history_remove(em->bm, f); + else + BM_select_history_store(em->bm, f); + + BM_active_face_set(em->bm, f); + + EDBM_update_generic(C, em, FALSE); + + return TRUE; } else { - return OPERATOR_PASS_THROUGH; + return FALSE; } } + +/* ******************* operator for edge and face tag ****************** */ + +static int edbm_shortest_path_select_invoke(bContext *C, wmOperator *UNUSED(op), wmEvent *event) +{ + ViewContext vc; + BMEditMesh *em; + + view3d_operator_needs_opengl(C); + + em_setup_viewcontext(C, &vc); + vc.mval[0] = event->mval[0]; + vc.mval[1] = event->mval[1]; + em = vc.em; + + if (em->selectmode & SCE_SELECT_EDGE) { + if (mouse_mesh_shortest_path_edge(C, &vc)) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_PASS_THROUGH; + } + } + else if (em->selectmode & SCE_SELECT_FACE) { + if (mouse_mesh_shortest_path_face(C, &vc)) { + return OPERATOR_FINISHED; + } + else { + return OPERATOR_PASS_THROUGH; + } + } + + return OPERATOR_PASS_THROUGH; +} + static int edbm_shortest_path_select_poll(bContext *C) { if (ED_operator_editmesh_region_view3d(C)) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); - return (em->selectmode & SCE_SELECT_EDGE) != 0; + return (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE)) != 0; } return 0; } From 718550878b847dc4779250be9b9776b89d32e2ef Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Nov 2012 03:39:15 +0000 Subject: [PATCH 010/118] minor cleanup to to selecting the shortest path, change some variable names and make edge/face modes share the cost calculation function. --- source/blender/editors/mesh/editmesh_select.c | 117 +++++++++--------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index 17c6ebb8801..ca4f0688f86 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1175,17 +1175,16 @@ void MESH_OT_edgering_select(wmOperatorType *ot) RNA_def_boolean(ot->srna, "ring", 1, "Select Ring", "Select ring"); } -/* ******************* edgetag_shortest_path and helpers ****************** */ +/* ******************* generic tag_shortest_path and helpers ****************** */ -static float edgetag_cut_cost(BMEdge *e1, BMEdge *e2, BMVert *v) +static float step_cost_3_v3(const float v1[3], const float v2[3], const float v3[3]) { - BMVert *v1 = (e1->v1 == v) ? e1->v2 : e1->v1; - BMVert *v2 = (e2->v1 == v) ? e2->v2 : e2->v1; float cost, d1[3], d2[3]; + /* The cost is based on the simple sum of the length of the two edgees... */ - sub_v3_v3v3(d1, v->co, v1->co); - sub_v3_v3v3(d2, v2->co, v->co); + sub_v3_v3v3(d1, v2, v1); + sub_v3_v3v3(d2, v3, v2); cost = len_v3(d1) + len_v3(d2); /* but is biased to give higher values to sharp turns, so that it will take @@ -1196,23 +1195,38 @@ static float edgetag_cut_cost(BMEdge *e1, BMEdge *e2, BMVert *v) return cost; } -static void edgetag_add_adjacent(Heap *heap, BMEdge *e1, BMVert *v, BMEdge **edges_prev, float *cost) +/* ******************* edgetag_shortest_path and helpers ****************** */ + +static float edgetag_cut_cost(BMEdge *e1, BMEdge *e2, BMVert *v) { + BMVert *v1 = (e1->v1 == v) ? e1->v2 : e1->v1; + BMVert *v2 = (e2->v1 == v) ? e2->v2 : e2->v1; + return step_cost_3_v3(v1->co, v->co, v2->co); +} + +static void edgetag_add_adjacent(Heap *heap, BMEdge *e1, BMEdge **edges_prev, float *cost) +{ + BMIter viter; + BMVert *v; + BMIter eiter; BMEdge *e2; const int e1_index = BM_elem_index_get(e1); - BM_ITER_ELEM (e2, &eiter, v, BM_EDGES_OF_VERT) { - if (!BM_elem_flag_test(e2, BM_ELEM_TAG)) { - const int e2_index = BM_elem_index_get(e2); - const float cost_cut = edgetag_cut_cost(e1, e2, v); - const float cost_new = cost[e1_index] + cost_cut; + BM_ITER_ELEM (v, &viter, e1, BM_VERTS_OF_EDGE) { + BM_ITER_ELEM (e2, &eiter, v, BM_EDGES_OF_VERT) { + if (!BM_elem_flag_test(e2, BM_ELEM_TAG)) { + /* we know 'e2' is not visited, check it out! */ + const int e2_index = BM_elem_index_get(e2); + const float cost_cut = edgetag_cut_cost(e1, e2, v); + const float cost_new = cost[e1_index] + cost_cut; - if (cost[e2_index] > cost_new) { - cost[e2_index] = cost_new; - edges_prev[e2_index] = e1; - BLI_heap_insert(heap, cost_new, e2); + if (cost[e2_index] > cost_new) { + cost[e2_index] = cost_new; + edges_prev[e2_index] = e1; + BLI_heap_insert(heap, cost_new, e2); + } } } } @@ -1315,20 +1329,19 @@ static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge if (!BM_elem_flag_test(e, BM_ELEM_TAG)) { BM_elem_flag_enable(e, BM_ELEM_TAG); - edgetag_add_adjacent(heap, e, e->v1, edges_prev, cost); - edgetag_add_adjacent(heap, e, e->v2, edges_prev, cost); + edgetag_add_adjacent(heap, e, edges_prev, cost); } } if (e == e_dst) { - short allseams = 1; + short all_set = TRUE; /* Check whether the path is already completely tagged. * if it is, the tags will be cleared instead of set. */ e = e_dst; do { if (!edgetag_context_check(scene, bm, e)) { - allseams = 0; + all_set = FALSE; break; } } while ((e = edges_prev[BM_elem_index_get(e)])); @@ -1336,7 +1349,7 @@ static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge /* Follow path back and source and add or remove tags */ e = e_dst; do { - edgetag_context_set(bm, scene, e, !allseams); + edgetag_context_set(bm, scene, e, !all_set); } while ((e = edges_prev[BM_elem_index_get(e)])); } @@ -1353,11 +1366,11 @@ static int edgetag_shortest_path(Scene *scene, BMesh *bm, BMEdge *e_src, BMEdge static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc) { BMEditMesh *em = vc->em; - BMEdge *e; + BMEdge *e_dst; float dist = 75.0f; - e = EDBM_edge_find_nearest(vc, &dist); - if (e) { + e_dst = EDBM_edge_find_nearest(vc, &dist); + if (e_dst) { Mesh *me = vc->obedit->data; int path = 0; @@ -1367,8 +1380,8 @@ static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc) if (ese && ese->htype == BM_EDGE) { BMEdge *e_act; e_act = (BMEdge *)ese->ele; - if (e_act != e) { - if (edgetag_shortest_path(vc->scene, em->bm, e_act, e)) { + if (e_act != e_dst) { + if (edgetag_shortest_path(vc->scene, em->bm, e_act, e_dst)) { BM_select_history_remove(em->bm, e_act); path = 1; } @@ -1376,17 +1389,17 @@ static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc) } } if (path == 0) { - int act = (edgetag_context_check(vc->scene, em->bm, e) == 0); - edgetag_context_set(em->bm, vc->scene, e, act); /* switch the edge option */ + int act = (edgetag_context_check(vc->scene, em->bm, e_dst) == 0); + edgetag_context_set(em->bm, vc->scene, e_dst, act); /* switch the edge option */ } EDBM_selectmode_flush(em); /* even if this is selected it may not be in the selection list */ - if (edgetag_context_check(vc->scene, em->bm, e) == 0) - BM_select_history_remove(em->bm, e); + if (edgetag_context_check(vc->scene, em->bm, e_dst) == 0) + BM_select_history_remove(em->bm, e_dst); else - BM_select_history_store(em->bm, e); + BM_select_history_store(em->bm, e_dst); /* force drawmode for mesh */ switch (CTX_data_tool_settings(C)->edge_mode) { @@ -1421,8 +1434,6 @@ static int mouse_mesh_shortest_path_edge(bContext *C, ViewContext *vc) static float facetag_cut_cost(BMFace *f1, BMFace *f2, BMEdge *e) { - float cost, d1[3], d2[3]; - float f1_cent[3]; float f2_cent[3]; float e_cent[3]; @@ -1431,17 +1442,7 @@ static float facetag_cut_cost(BMFace *f1, BMFace *f2, BMEdge *e) BM_face_calc_center_mean(f2, f2_cent); mid_v3_v3v3(e_cent, e->v1->co, e->v2->co); - /* The cost is based on the simple sum of the length of the two edgees... */ - sub_v3_v3v3(d1, e_cent, f1_cent); - sub_v3_v3v3(d2, f2_cent, e_cent); - cost = len_v3(d1) + len_v3(d2); - - /* but is biased to give higher values to sharp turns, so that it will take - * paths with fewer "turns" when selecting between equal-weighted paths between - * the two edges */ - cost = cost + 0.5f * cost * (2.0f - sqrtf(fabsf(dot_v3v3(d1, d2)))); - - return cost; + return step_cost_3_v3(f1_cent, e_cent, f2_cent); } static void facetag_add_adjacent(Heap *heap, BMFace *f1, BMFace **faces_prev, float *cost) @@ -1549,14 +1550,14 @@ static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace } if (f == f_dst) { - short allseams = 1; + short all_set = TRUE; /* Check whether the path is already completely tagged. * if it is, the tags will be cleared instead of set. */ f = f_dst; do { if (!facetag_context_check(scene, bm, f)) { - allseams = 0; + all_set = FALSE; break; } } while ((f = faces_prev[BM_elem_index_get(f)])); @@ -1564,7 +1565,7 @@ static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace /* Follow path back and source and add or remove tags */ f = f_dst; do { - facetag_context_set(bm, scene, f, !allseams); + facetag_context_set(bm, scene, f, !all_set); } while ((f = faces_prev[BM_elem_index_get(f)])); } @@ -1578,36 +1579,36 @@ static int facetag_shortest_path(Scene *scene, BMesh *bm, BMFace *f_src, BMFace static int mouse_mesh_shortest_path_face(bContext *C, ViewContext *vc) { BMEditMesh *em = vc->em; - BMFace *f; + BMFace *f_dst; float dist = 75.0f; - f = EDBM_face_find_nearest(vc, &dist); - if (f) { + f_dst = EDBM_face_find_nearest(vc, &dist); + if (f_dst) { int path = 0; BMFace *f_act = BM_active_face_get(em->bm, FALSE, TRUE); if (f_act) { - if (f_act != f) { - if (facetag_shortest_path(vc->scene, em->bm, f_act, f)) { + if (f_act != f_dst) { + if (facetag_shortest_path(vc->scene, em->bm, f_act, f_dst)) { BM_select_history_remove(em->bm, f_act); path = 1; } } } if (path == 0) { - int act = (facetag_context_check(vc->scene, em->bm, f) == 0); - facetag_context_set(em->bm, vc->scene, f, act); /* switch the face option */ + int act = (facetag_context_check(vc->scene, em->bm, f_dst) == 0); + facetag_context_set(em->bm, vc->scene, f_dst, act); /* switch the face option */ } EDBM_selectmode_flush(em); /* even if this is selected it may not be in the selection list */ - if (facetag_context_check(vc->scene, em->bm, f) == 0) - BM_select_history_remove(em->bm, f); + if (facetag_context_check(vc->scene, em->bm, f_dst) == 0) + BM_select_history_remove(em->bm, f_dst); else - BM_select_history_store(em->bm, f); + BM_select_history_store(em->bm, f_dst); - BM_active_face_set(em->bm, f); + BM_active_face_set(em->bm, f_dst); EDBM_update_generic(C, em, FALSE); From cb41fbef8e8b3050dab363af6db241cf6903fa07 Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Thu, 8 Nov 2012 05:50:02 +0000 Subject: [PATCH 011/118] CMake: Since Audaspace now requires Boost, auto enable Boost if WITH_AUDASPACE is enabled. --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c33f4384a76..d8ae92d59d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -372,8 +372,8 @@ if(WITH_CYCLES) set(WITH_OPENIMAGEIO ON) endif() -# auto enable boost for cycles and booleans -if(WITH_CYCLES OR WITH_MOD_BOOLEAN) +# auto enable boost for cycles, booleans or audaspace +if(WITH_CYCLES OR WITH_MOD_BOOLEAN OR WITH_AUDASPACE) set(WITH_BOOST ON) endif() From b0e2218093a1daac03361b9454006bcdba67b725 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Nov 2012 06:44:14 +0000 Subject: [PATCH 012/118] code cleanup: avoid doing multiplications within macro FTOCHAR() per pixel when applying brush color. --- .../editors/sculpt_paint/paint_image.c | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c index bd6852c4344..4b400623920 100644 --- a/source/blender/editors/sculpt_paint/paint_image.c +++ b/source/blender/editors/sculpt_paint/paint_image.c @@ -109,19 +109,25 @@ #include "paint_intern.h" /* Defines and Structs */ +/* FTOCHAR as inline function */ +BLI_INLINE unsigned char f_to_char(const float val) +{ + return FTOCHAR(val); +} + #define IMAPAINT_CHAR_TO_FLOAT(c) ((c) / 255.0f) #define IMAPAINT_FLOAT_RGB_TO_CHAR(c, f) { \ - (c)[0] = FTOCHAR((f)[0]); \ - (c)[1] = FTOCHAR((f)[1]); \ - (c)[2] = FTOCHAR((f)[2]); \ + (c)[0] = f_to_char((f)[0]); \ + (c)[1] = f_to_char((f)[1]); \ + (c)[2] = f_to_char((f)[2]); \ } (void)0 #define IMAPAINT_FLOAT_RGBA_TO_CHAR(c, f) { \ - (c)[0] = FTOCHAR((f)[0]); \ - (c)[1] = FTOCHAR((f)[1]); \ - (c)[2] = FTOCHAR((f)[2]); \ - (c)[3] = FTOCHAR((f)[3]); \ + (c)[0] = f_to_char((f)[0]); \ + (c)[1] = f_to_char((f)[1]); \ + (c)[2] = f_to_char((f)[2]); \ + (c)[3] = f_to_char((f)[3]); \ } (void)0 #define IMAPAINT_CHAR_RGB_TO_FLOAT(f, c) { \ (f)[0] = IMAPAINT_CHAR_TO_FLOAT((c)[0]); \ @@ -3905,16 +3911,20 @@ static void do_projectpaint_soften(ProjPaintState *ps, ProjPixel *projPixel, flo } } +BLI_INLINE void rgba_float_to_uchar__mul_v3(unsigned char rgba_ub[4], const float rgba[4], const float rgb[3]) +{ + rgba_ub[0] = f_to_char(rgba[0] * rgb[0]); + rgba_ub[1] = f_to_char(rgba[1] * rgb[1]); + rgba_ub[2] = f_to_char(rgba[2] * rgb[3]); + rgba_ub[3] = f_to_char(rgba[3]); +} static void do_projectpaint_draw(ProjPaintState *ps, ProjPixel *projPixel, const float rgba[4], float alpha, float mask) { unsigned char rgba_ub[4]; if (ps->is_texbrush) { - rgba_ub[0] = FTOCHAR(rgba[0] * ps->brush->rgb[0]); - rgba_ub[1] = FTOCHAR(rgba[1] * ps->brush->rgb[1]); - rgba_ub[2] = FTOCHAR(rgba[2] * ps->brush->rgb[2]); - rgba_ub[3] = FTOCHAR(rgba[3]); + rgba_float_to_uchar__mul_v3(rgba_ub, rgba, ps->brush->rgb); } else { IMAPAINT_FLOAT_RGB_TO_CHAR(rgba_ub, ps->brush->rgb); From 617a73c573c209155a2f5734030d1cc41e0d6a3d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Nov 2012 06:46:10 +0000 Subject: [PATCH 013/118] code cleanup: unused defines & some formatting. --- intern/container/CTR_HashedPtr.h | 6 ++-- .../blender/blenkernel/intern/cdderivedmesh.c | 3 +- source/blender/bmesh/intern/bmesh_queries.c | 1 + .../bmesh/operators/bmo_smooth_laplacian.c | 4 +-- source/blender/bmesh/operators/bmo_utils.c | 2 +- source/blender/editors/mesh/editmesh_select.c | 4 +-- source/blender/imbuf/intern/dds/BlockDXT.h | 36 +++++++++---------- source/blender/imbuf/intern/dds/Stream.h | 2 +- source/blender/imbuf/intern/jp2.c | 2 +- source/blender/imbuf/intern/radiance_hdr.c | 1 - .../nodes/node_composite_colorSpill.c | 7 ++-- .../Network/NG_NetworkDeviceInterface.h | 4 +-- source/gameengine/Rasterizer/RAS_ICanvas.h | 2 +- source/gameengine/SceneGraph/SG_IObject.h | 6 ++-- 14 files changed, 39 insertions(+), 41 deletions(-) diff --git a/intern/container/CTR_HashedPtr.h b/intern/container/CTR_HashedPtr.h index b7ac460f270..ee832eee153 100644 --- a/intern/container/CTR_HashedPtr.h +++ b/intern/container/CTR_HashedPtr.h @@ -46,13 +46,13 @@ class CTR_HashedPtr void *m_valptr; public: CTR_HashedPtr(void *val) : m_valptr(val) { - }; + } unsigned int hash() const { return CTR_Hash(m_valptr); - }; + } inline friend bool operator ==(const CTR_HashedPtr & rhs, const CTR_HashedPtr & lhs) { return rhs.m_valptr == lhs.m_valptr; - }; + } void *getValue() const { return m_valptr; } diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index 2e0b3a3c64a..a0a402cc061 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -1956,12 +1956,11 @@ static DerivedMesh *cddm_from_bmesh_ex(struct BMesh *bm, int use_mdisps, /* avoid this where possiblem, takes extra memory */ if (use_tessface) { - int *polyindex; BM_mesh_elem_index_ensure(bm, BM_FACE); index = dm->getTessFaceDataArray(dm, CD_ORIGINDEX); - for (i = 0; i < dm->numTessFaceData; i++, index++, polyindex++) { + for (i = 0; i < dm->numTessFaceData; i++, index++) { MFace *mf = &mface[i]; const BMLoop **l = em_looptris[i]; efa = l[0]->f; diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 4b07dd74eef..ed36a86274c 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -401,6 +401,7 @@ BMLoop *BM_vert_step_fan_loop(BMLoop *l, BMEdge **e_step) } else { BLI_assert(0); + return NULL; } if (BM_edge_is_manifold(e_next)) { diff --git a/source/blender/bmesh/operators/bmo_smooth_laplacian.c b/source/blender/bmesh/operators/bmo_smooth_laplacian.c index 51b9adb5de3..362123e412d 100644 --- a/source/blender/bmesh/operators/bmo_smooth_laplacian.c +++ b/source/blender/bmesh/operators/bmo_smooth_laplacian.c @@ -43,8 +43,8 @@ #include "intern/bmesh_operators_private.h" /* own include */ -#define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f -#define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f +// #define SMOOTH_LAPLACIAN_AREA_FACTOR 4.0f /* UNUSED */ +// #define SMOOTH_LAPLACIAN_EDGE_FACTOR 2.0f /* UNUSED */ #define SMOOTH_LAPLACIAN_MAX_EDGE_PERCENTAGE 1.8f #define SMOOTH_LAPLACIAN_MIN_EDGE_PERCENTAGE 0.15f diff --git a/source/blender/bmesh/operators/bmo_utils.c b/source/blender/bmesh/operators/bmo_utils.c index e311b383b86..aa514a5c0a7 100644 --- a/source/blender/bmesh/operators/bmo_utils.c +++ b/source/blender/bmesh/operators/bmo_utils.c @@ -282,7 +282,7 @@ void bmo_region_extend_exec(BMesh *bm, BMOperator *op) #define FACE_VIS 1 #define FACE_FLAG 2 -#define FACE_MARK 4 +// #define FACE_MARK 4 /* UNUSED */ #define FACE_FLIP 8 /* NOTE: these are the original recalc_face_normals comment in editmesh_mods.c, diff --git a/source/blender/editors/mesh/editmesh_select.c b/source/blender/editors/mesh/editmesh_select.c index ca4f0688f86..92ad0742ec9 100644 --- a/source/blender/editors/mesh/editmesh_select.c +++ b/source/blender/editors/mesh/editmesh_select.c @@ -1199,8 +1199,8 @@ static float step_cost_3_v3(const float v1[3], const float v2[3], const float v3 static float edgetag_cut_cost(BMEdge *e1, BMEdge *e2, BMVert *v) { - BMVert *v1 = (e1->v1 == v) ? e1->v2 : e1->v1; - BMVert *v2 = (e2->v1 == v) ? e2->v2 : e2->v1; + BMVert *v1 = BM_edge_other_vert(e1, v); + BMVert *v2 = BM_edge_other_vert(e2, v); return step_cost_3_v3(v1->co, v->co, v2->co); } diff --git a/source/blender/imbuf/intern/dds/BlockDXT.h b/source/blender/imbuf/intern/dds/BlockDXT.h index 9b90b744b67..0291816cd03 100644 --- a/source/blender/imbuf/intern/dds/BlockDXT.h +++ b/source/blender/imbuf/intern/dds/BlockDXT.h @@ -173,24 +173,24 @@ struct AlphaBlockDXT5 }; */ uint64 u; - uint8 alpha0() const { return u & 0xffLL; }; - uint8 alpha1() const { return (u >> 8) & 0xffLL; }; - uint8 bits0() const { return (u >> 16) & 0x7LL; }; - uint8 bits1() const { return (u >> 19) & 0x7LL; }; - uint8 bits2() const { return (u >> 22) & 0x7LL; }; - uint8 bits3() const { return (u >> 25) & 0x7LL; }; - uint8 bits4() const { return (u >> 28) & 0x7LL; }; - uint8 bits5() const { return (u >> 31) & 0x7LL; }; - uint8 bits6() const { return (u >> 34) & 0x7LL; }; - uint8 bits7() const { return (u >> 37) & 0x7LL; }; - uint8 bits8() const { return (u >> 40) & 0x7LL; }; - uint8 bits9() const { return (u >> 43) & 0x7LL; }; - uint8 bitsA() const { return (u >> 46) & 0x7LL; }; - uint8 bitsB() const { return (u >> 49) & 0x7LL; }; - uint8 bitsC() const { return (u >> 52) & 0x7LL; }; - uint8 bitsD() const { return (u >> 55) & 0x7LL; }; - uint8 bitsE() const { return (u >> 58) & 0x7LL; }; - uint8 bitsF() const { return (u >> 61) & 0x7LL; }; + uint8 alpha0() const { return u & 0xffLL; } + uint8 alpha1() const { return (u >> 8) & 0xffLL; } + uint8 bits0() const { return (u >> 16) & 0x7LL; } + uint8 bits1() const { return (u >> 19) & 0x7LL; } + uint8 bits2() const { return (u >> 22) & 0x7LL; } + uint8 bits3() const { return (u >> 25) & 0x7LL; } + uint8 bits4() const { return (u >> 28) & 0x7LL; } + uint8 bits5() const { return (u >> 31) & 0x7LL; } + uint8 bits6() const { return (u >> 34) & 0x7LL; } + uint8 bits7() const { return (u >> 37) & 0x7LL; } + uint8 bits8() const { return (u >> 40) & 0x7LL; } + uint8 bits9() const { return (u >> 43) & 0x7LL; } + uint8 bitsA() const { return (u >> 46) & 0x7LL; } + uint8 bitsB() const { return (u >> 49) & 0x7LL; } + uint8 bitsC() const { return (u >> 52) & 0x7LL; } + uint8 bitsD() const { return (u >> 55) & 0x7LL; } + uint8 bitsE() const { return (u >> 58) & 0x7LL; } + uint8 bitsF() const { return (u >> 61) & 0x7LL; } void evaluatePalette(uint8 alpha[8]) const; void evaluatePalette8(uint8 alpha[8]) const; diff --git a/source/blender/imbuf/intern/dds/Stream.h b/source/blender/imbuf/intern/dds/Stream.h index 7fed4ca89e7..a1ac49b58da 100644 --- a/source/blender/imbuf/intern/dds/Stream.h +++ b/source/blender/imbuf/intern/dds/Stream.h @@ -35,7 +35,7 @@ struct Stream unsigned char *mem; // location in memory unsigned int size; // size unsigned int pos; // current position - Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {}; + Stream(unsigned char *m, unsigned int s) : mem(m), size(s), pos(0) {} unsigned int seek(unsigned int p); }; diff --git a/source/blender/imbuf/intern/jp2.c b/source/blender/imbuf/intern/jp2.c index 692ba3c49ea..d94f6368298 100644 --- a/source/blender/imbuf/intern/jp2.c +++ b/source/blender/imbuf/intern/jp2.c @@ -41,7 +41,7 @@ #include "openjpeg.h" -#define JP2_FILEHEADER_SIZE 14 +// #define JP2_FILEHEADER_SIZE 14 /* UNUSED */ static char JP2_HEAD[] = {0x0, 0x0, 0x0, 0x0C, 0x6A, 0x50, 0x20, 0x20, 0x0D, 0x0A, 0x87, 0x0A}; static char J2K_HEAD[] = {0xFF, 0x4F, 0xFF, 0x51, 0x00}; diff --git a/source/blender/imbuf/intern/radiance_hdr.c b/source/blender/imbuf/intern/radiance_hdr.c index 72cec0e3749..03ed1bb8008 100644 --- a/source/blender/imbuf/intern/radiance_hdr.c +++ b/source/blender/imbuf/intern/radiance_hdr.c @@ -65,7 +65,6 @@ #define BLU 2 #define EXP 3 #define COLXS 128 -#define STR_MAX 540 typedef unsigned char RGBE[4]; typedef float fCOLOR[3]; diff --git a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c index e8965d50b47..44a5ac9e968 100644 --- a/source/blender/nodes/composite/nodes/node_composite_colorSpill.c +++ b/source/blender/nodes/composite/nodes/node_composite_colorSpill.c @@ -29,12 +29,8 @@ * \ingroup cmpnodes */ - - #include "node_composite_util.h" -#define AVG(a, b) ((a + b) / 2) - /* ******************* Color Spill Supression ********************************* */ static bNodeSocketTemplate cmp_node_color_spill_in[] = { {SOCK_RGBA, 1, N_("Image"), 1.0f, 1.0f, 1.0f, 1.0f}, @@ -49,6 +45,9 @@ static bNodeSocketTemplate cmp_node_color_spill_out[] = { #ifdef WITH_COMPOSITOR_LEGACY +#define AVG(a, b) ((a + b) / 2) + + static void do_simple_spillmap_red(bNode *node, float* out, float *in) { NodeColorspill *ncs; diff --git a/source/gameengine/Network/NG_NetworkDeviceInterface.h b/source/gameengine/Network/NG_NetworkDeviceInterface.h index 48edbdfc7fe..6da478ecda5 100644 --- a/source/gameengine/Network/NG_NetworkDeviceInterface.h +++ b/source/gameengine/Network/NG_NetworkDeviceInterface.h @@ -43,8 +43,8 @@ private: // candidates for shared/common implementation class bool m_online; public: - NG_NetworkDeviceInterface() {}; - virtual ~NG_NetworkDeviceInterface() {}; + NG_NetworkDeviceInterface() {} + virtual ~NG_NetworkDeviceInterface() {} virtual void NextFrame()=0; diff --git a/source/gameengine/Rasterizer/RAS_ICanvas.h b/source/gameengine/Rasterizer/RAS_ICanvas.h index 53195d79768..60b9f052075 100644 --- a/source/gameengine/Rasterizer/RAS_ICanvas.h +++ b/source/gameengine/Rasterizer/RAS_ICanvas.h @@ -59,7 +59,7 @@ public: virtual ~RAS_ICanvas( ) { - }; + } virtual void diff --git a/source/gameengine/SceneGraph/SG_IObject.h b/source/gameengine/SceneGraph/SG_IObject.h index 885eb8e1e90..6b57db1a467 100644 --- a/source/gameengine/SceneGraph/SG_IObject.h +++ b/source/gameengine/SceneGraph/SG_IObject.h @@ -127,8 +127,8 @@ struct SG_Callbacks m_schedulefunc(NULL), m_reschedulefunc(NULL) { - }; - + } + SG_Callbacks( SG_ReplicationNewCallback repfunc, SG_DestructionNewCallback destructfunc, @@ -142,7 +142,7 @@ struct SG_Callbacks m_schedulefunc(schedulefunc), m_reschedulefunc(reschedulefunc) { - }; + } SG_ReplicationNewCallback m_replicafunc; SG_DestructionNewCallback m_destructionfunc; From 09cce17d847b3bddc4f82189e93002f131d0bec2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Nov 2012 07:06:08 +0000 Subject: [PATCH 014/118] decimator - merge flags when collapsing edges / verts, so seams and edges draw flags are kept. --- source/blender/bmesh/intern/bmesh_decimate_collapse.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/bmesh/intern/bmesh_decimate_collapse.c b/source/blender/bmesh/intern/bmesh_decimate_collapse.c index 15f774e50a8..74792d1d558 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_collapse.c +++ b/source/blender/bmesh/intern/bmesh_decimate_collapse.c @@ -760,8 +760,11 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e BM_edge_kill(bm, e_clear); + v_other->head.hflag |= v_clear->head.hflag; BM_vert_splice(bm, v_clear, v_other); + e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag; + e_b_other[1]->head.hflag |= e_b_other[0]->head.hflag; BM_edge_splice(bm, e_a_other[0], e_a_other[1]); BM_edge_splice(bm, e_b_other[0], e_b_other[1]); @@ -806,8 +809,10 @@ static int bm_edge_collapse(BMesh *bm, BMEdge *e_clear, BMVert *v_clear, int r_e BM_edge_kill(bm, e_clear); + v_other->head.hflag |= v_clear->head.hflag; BM_vert_splice(bm, v_clear, v_other); + e_a_other[1]->head.hflag |= e_a_other[0]->head.hflag; BM_edge_splice(bm, e_a_other[0], e_a_other[1]); // BM_mesh_validate(bm); From 529209ff832a8737ad26115d9cd7ff21fd5eb698 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 8 Nov 2012 08:16:44 +0000 Subject: [PATCH 015/118] Added Map Taper option which if enabled maps affect of taper object on actually beveled part of curve (previously affect of taper would have been clamped by start/end bevel factor) Here's an illustration: http://wiki.blender.org/uploads/5/5d/Blender2.65_CurveMapTaper.png --- .../startup/bl_ui/properties_data_curve.py | 7 +- source/blender/blenkernel/intern/displist.c | 109 ++++++++++++------ source/blender/makesdna/DNA_curve_types.h | 5 +- source/blender/makesrna/intern/rna_curve.c | 5 + 4 files changed, 87 insertions(+), 39 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_curve.py b/release/scripts/startup/bl_ui/properties_data_curve.py index a8f4aa30e95..7747ef45c4d 100644 --- a/release/scripts/startup/bl_ui/properties_data_curve.py +++ b/release/scripts/startup/bl_ui/properties_data_curve.py @@ -174,11 +174,14 @@ class DATA_PT_geometry_curve(CurveButtonsPanel, Panel): col.prop(curve, "bevel_object", text="") col = layout.column(align=True) - col.active = (curve.bevel_object is not None) - col.prop(curve, "use_fill_caps") col.prop(curve, "bevel_factor_start") col.prop(curve, "bevel_factor_end") + row = col.row() + row.active = (curve.bevel_object is not None) + row.prop(curve, "use_fill_caps") + row.prop(curve, "use_map_taper") + class DATA_PT_pathanim(CurveButtonsPanelCurve, Panel): bl_label = "Path Animation" diff --git a/source/blender/blenkernel/intern/displist.c b/source/blender/blenkernel/intern/displist.c index e13d05d0a2f..a78a9af54ae 100644 --- a/source/blender/blenkernel/intern/displist.c +++ b/source/blender/blenkernel/intern/displist.c @@ -630,7 +630,7 @@ static void curve_to_filledpoly(Curve *cu, ListBase *UNUSED(nurb), ListBase *dis * - first point left, last point right * - based on subdivided points in original curve, not on points in taper curve (still) */ -float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) +static float displist_calc_taper(Scene *scene, Object *taperobj, float fac) { DispList *dl; @@ -643,7 +643,6 @@ float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) dl = taperobj->disp.first; } if (dl) { - float fac = ((float)cur) / (float)(tot - 1); float minx, dx, *fp; int a; @@ -671,6 +670,13 @@ float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) return 1.0; } +float BKE_displist_calc_taper(Scene *scene, Object *taperobj, int cur, int tot) +{ + float fac = ((float)cur) / (float)(tot - 1); + + return displist_calc_taper(scene, taperobj, fac); +} + void BKE_displist_make_mball(Scene *scene, Object *ob) { if (!ob || ob->type != OB_MBALL) @@ -1240,7 +1246,7 @@ void BKE_displist_make_surf(Scene *scene, Object *ob, ListBase *dispbase, } } -static void rotateBevelPiece(Curve *cu, BevPoint *bevp, DispList *dlb, float widfac, float fac, float **data_r) +static void rotateBevelPiece(Curve *cu, BevPoint *bevp, BevPoint *nbevp, DispList *dlb, float bev_blend, float widfac, float fac, float **data_r) { float *fp, *data = *data_r; int b; @@ -1248,22 +1254,48 @@ static void rotateBevelPiece(Curve *cu, BevPoint *bevp, DispList *dlb, float wid fp = dlb->verts; for (b = 0; b < dlb->nr; b++, fp += 3, data += 3) { if (cu->flag & CU_3D) { - float vec[3]; + float vec[3], quat[4]; vec[0] = fp[1] + widfac; vec[1] = fp[2]; vec[2] = 0.0; - mul_qt_v3(bevp->quat, vec); + if (nbevp == NULL) { + copy_v3_v3(data, bevp->vec); + copy_qt_qt(quat, bevp->quat); + } + else { + interp_v3_v3v3(data, bevp->vec, nbevp->vec, bev_blend); + interp_qt_qtqt(quat, bevp->quat, nbevp->quat, bev_blend); + } - data[0] = bevp->vec[0] + fac * vec[0]; - data[1] = bevp->vec[1] + fac * vec[1]; - data[2] = bevp->vec[2] + fac * vec[2]; + mul_qt_v3(quat, vec); + + data[0] += fac * vec[0]; + data[1] += fac * vec[1]; + data[2] += fac * vec[2]; } else { - data[0] = bevp->vec[0] + fac * (widfac + fp[1]) * bevp->sina; - data[1] = bevp->vec[1] + fac * (widfac + fp[1]) * bevp->cosa; - data[2] = bevp->vec[2] + fac * fp[2]; + float sina, cosa; + + if (nbevp == NULL) { + copy_v3_v3(data, bevp->vec); + sina = bevp->sina; + cosa = bevp->cosa; + } + else { + interp_v3_v3v3(data, bevp->vec, nbevp->vec, bev_blend); + + /* perhaps we need to interpolate angles instead. but the thing is + * cosa and sina are not actually sine and cosine + */ + sina = nbevp->sina * bev_blend + bevp->sina * (1.0f - bev_blend); + cosa = nbevp->cosa * bev_blend + bevp->cosa * (1.0f - bev_blend); + } + + data[0] += fac * (widfac + fp[1]) * sina; + data[1] += fac * (widfac + fp[1]) * cosa; + data[2] += fac * fp[2]; } } @@ -1399,8 +1431,8 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba firstblend = 1.0f - (bevfac1 * (bl->nr - 1) - (int)(bevfac1 * (bl->nr - 1))); lastblend = bevfac2 * (bl->nr - 1) - (int)(bevfac2 * (bl->nr - 1)); - if (steps > bl->nr) { - steps = bl->nr; + if (start + steps > bl->nr) { + steps = bl->nr - start; lastblend = 1.0f; } @@ -1438,7 +1470,29 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba fac = bevp->radius; } else { - fac = BKE_displist_calc_taper(scene, cu->taperobj, i, bl->nr); + float len, taper_fac; + + if (cu->flag & CU_MAP_TAPER) { + len = (steps - 3) + firstblend + lastblend; + + if (a == 0) + taper_fac = 0.0f; + else if (a == steps - 1) + taper_fac = 1.0f; + else + taper_fac = ((float) a - (1.0f - firstblend)) / len; + } + else { + len = bl->nr - 1; + taper_fac = (float) i / len; + + if (a == 0) + taper_fac += (1.0f - firstblend) / len; + else if (a == steps - 1) + taper_fac -= (1.0f - lastblend) / len; + } + + fac = displist_calc_taper(scene, cu->taperobj, taper_fac); } if (bevp->split_tag) { @@ -1446,27 +1500,12 @@ static void do_makeDispListCurveTypes(Scene *scene, Object *ob, ListBase *dispba } /* rotate bevel piece and write in data */ - rotateBevelPiece(cu, bevp, dlb, widfac, fac, &data); - - if (a == 1 || a == steps - 1) { - float *cur_fp = cur_data, *prev_fp = cur_data - 3 * dlb->nr; - int b; - - for (b = 0; b < dlb->nr; b++, prev_fp += 3, cur_fp += 3) { - float cur[3], prev[3]; - - copy_v3_v3(cur, cur_fp); - copy_v3_v3(prev, prev_fp); - - if (a == 1) - interp_v3_v3v3(prev, cur_fp, prev_fp, firstblend); - if (a == steps - 1) - interp_v3_v3v3(cur, prev_fp, cur_fp, lastblend); - - copy_v3_v3(cur_fp, cur); - copy_v3_v3(prev_fp, prev); - } - } + if (a == 0) + rotateBevelPiece(cu, bevp, bevp + 1, dlb, 1.0f - firstblend, widfac, fac, &data); + else if (a == steps - 1) + rotateBevelPiece(cu, bevp, bevp - 1, dlb, 1.0f - lastblend, widfac, fac, &data); + else + rotateBevelPiece(cu, bevp, NULL, dlb, 0.0f, widfac, fac, &data); if (cu->bevobj && (cu->flag & CU_FILL_CAPS)) { if (a == 1) diff --git a/source/blender/makesdna/DNA_curve_types.h b/source/blender/makesdna/DNA_curve_types.h index 3cf84648ea6..deb9902c35d 100644 --- a/source/blender/makesdna/DNA_curve_types.h +++ b/source/blender/makesdna/DNA_curve_types.h @@ -201,8 +201,8 @@ typedef struct Curve { float twist_smooth, smallcaps_scale; int pathlen; - short pad, totcol; - short flag, bevresol; + short bevresol, totcol; + int flag; float width, ext1, ext2; /* default */ @@ -269,6 +269,7 @@ typedef struct Curve { #define CU_PATH_RADIUS 4096 /* make use of the path radius if this is enabled (default for new curves) */ #define CU_DEFORM_FILL 8192 /* fill 2d curve after deformation */ #define CU_FILL_CAPS 16384 /* fill bevel caps */ +#define CU_MAP_TAPER 32768 /* map taper object to bevelled area */ /* twist mode */ #define CU_TWIST_Z_UP 0 diff --git a/source/blender/makesrna/intern/rna_curve.c b/source/blender/makesrna/intern/rna_curve.c index a3cff99ddc8..1e1a8c82b8e 100644 --- a/source/blender/makesrna/intern/rna_curve.c +++ b/source/blender/makesrna/intern/rna_curve.c @@ -1422,6 +1422,11 @@ static void rna_def_curve(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Fill Caps", "Fill caps for beveled curves"); RNA_def_property_update(prop, 0, "rna_Curve_update_data"); + prop = RNA_def_property(srna, "use_map_taper", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", CU_MAP_TAPER); + RNA_def_property_ui_text(prop, "Map Taper", "Map effect of taper object on actually bevelled curve"); + RNA_def_property_update(prop, 0, "rna_Curve_update_data"); + /* texture space */ prop = RNA_def_property(srna, "use_auto_texspace", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "texflag", CU_AUTOSPACE); From 03d0040fe7936239c8f51988cb9fd36c8a5d05dd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Nov 2012 09:38:18 +0000 Subject: [PATCH 016/118] patch [#32874] Fixed the property path calculation in situations where the link.index variable gets set during the search. From Florian K?\246berle --- source/blender/makesrna/intern/rna_access.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 1fe46342819..69332dcd250 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -4011,12 +4011,15 @@ static char *rna_idp_path(PointerRNA *ptr, IDProperty *haystack, IDProperty *nee BLI_assert(haystack->type == IDP_GROUP); link.up = parent_link; + /* always set both name and index, + * else a stale value might get used */ link.name = NULL; link.index = -1; for (i = 0, iter = haystack->data.group.first; iter; iter = iter->next, i++) { if (needle == iter) { /* found! */ link.name = iter->name; + link.index = -1; path = rna_idp_path_create(&link); break; } @@ -4026,6 +4029,7 @@ static char *rna_idp_path(PointerRNA *ptr, IDProperty *haystack, IDProperty *nee PointerRNA child_ptr = RNA_pointer_get(ptr, iter->name); if (child_ptr.type) { link.name = iter->name; + link.index = -1; if ((path = rna_idp_path(&child_ptr, iter, needle, &link))) { break; } From ae06e2cf9b932dc2b9d182aba8b7d1c62cc7f235 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Nov 2012 10:32:11 +0000 Subject: [PATCH 017/118] fix [#33000] bmesh.ops.create_* either crash blender or do nothing --- source/blender/bmesh/intern/bmesh_operators.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_operators.c b/source/blender/bmesh/intern/bmesh_operators.c index 4cc946a3a40..9d1054dc042 100644 --- a/source/blender/bmesh/intern/bmesh_operators.c +++ b/source/blender/bmesh/intern/bmesh_operators.c @@ -354,7 +354,7 @@ void BMO_slot_mat_set(BMOperator *op, const char *slot_name, const float *mat, i else { fprintf(stderr, "%s: invalid size argument %d (bmesh internal error)\n", __func__, size); - memset(slot->data.p, 0, sizeof(float) * 4 * 4); + zero_m4(slot->data.p); } } @@ -365,7 +365,12 @@ void BMO_slot_mat4_get(BMOperator *op, const char *slot_name, float r_mat[4][4]) if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; - copy_m4_m4(r_mat, (float (*)[4])slot->data.p); + if (slot->data.p) { + copy_m4_m4(r_mat, (float (*)[4])slot->data.p); + } + else { + unit_m4(r_mat); + } } void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3]) @@ -375,7 +380,12 @@ void BMO_slot_mat3_set(BMOperator *op, const char *slot_name, float r_mat[3][3]) if (!(slot->slot_type == BMO_OP_SLOT_MAT)) return; - copy_m3_m4(r_mat, slot->data.p); + if (slot->data.p) { + copy_m3_m4(r_mat, slot->data.p); + } + else { + unit_m3(r_mat); + } } void BMO_slot_ptr_set(BMOperator *op, const char *slot_name, void *p) From 6da6c9922176cc9bf07b57ec5d70fd509a739fce Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Thu, 8 Nov 2012 11:31:15 +0000 Subject: [PATCH 018/118] Small fix: Pressing ESC for renders now checks for modifier keys, and doesn't escape renders when a modifier key is held. In Windows, SHIFT+CTRL+ESC brings up task manager, and it seems to pass on the event. --- source/blender/windowmanager/intern/wm_event_system.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 7cfa3ce9396..236ab264f8c 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2978,9 +2978,10 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U if (event.keymodifier == UNKNOWNKEY) event.keymodifier = 0; - /* if test_break set, it catches this. XXX Keep global for now? */ - if (event.type == ESCKEY && event.val == KM_PRESS) - G.is_break = TRUE; + /* if test_break set, it catches this. Do not set with modifier presses. XXX Keep global for now? */ + if (event.type == ESCKEY && event.val == KM_PRESS && + event.shift == 0 && event.ctrl == 0 && event.alt == 0) + G.is_break = TRUE; /* double click test - only for press */ if (event.val == KM_PRESS) { From 2e52bdbbee3e0e6a501c625e6a0271097d911b27 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Thu, 8 Nov 2012 12:57:01 +0000 Subject: [PATCH 019/118] OSX/cmake: workaround for getting right LC_VERSION_MIN_MACOSX with makefiles --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index d8ae92d59d1..7da2da4d61f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -312,6 +312,10 @@ if(APPLE) execute_process(COMMAND xcodebuild -version OUTPUT_VARIABLE XCODE_VERS_BUILD_NR) string(SUBSTRING "${XCODE_VERS_BUILD_NR}" 6 3 XCODE_VERSION) # truncate away build-nr unset(XCODE_VERS_BUILD_NR) + # force CMAKE_OSX_DEPLOYMENT_TARGET for makefiles, will not work else ( cmake bug ? ) + set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}" ) + set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}" ) + add_definitions ("-DMACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}") endif() message(STATUS "Detected Xcode-version: " ${XCODE_VERSION}) From eacc74ef1bdb331cba34817db298f36c957d06d8 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 8 Nov 2012 14:01:47 +0000 Subject: [PATCH 020/118] Fix #33116: Blender Crashes when saving inside Sculpt Mode with with GLSL and textured view enabled. Issue was caused by call ED_sculpt_force_update from WM_file_write which frees derived mesh and pBVH and forces them to be re-created. After this sculpt session wasn't repairing properly. Freeing data from WM_file_write is not nice by itself, but it exposed possible real issue when sculpting on modifiers. Made it so BLI_pbvh_grids_update will update pointers to material flags and hidden grids as well. This isn't idea solution for particular circumstances from the report, since pBVH would be rebuilt after save which ends up with small interface lags for while pBVH is rebuilding. Would be nice to have multires displacement propagation to higher levels without freeing data. --- source/blender/blenkernel/intern/subsurf_ccg.c | 3 ++- source/blender/blenlib/BLI_pbvh.h | 4 +++- source/blender/blenlib/intern/pbvh.c | 5 ++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 8a669b89907..be8b572417e 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -3025,7 +3025,8 @@ static struct PBVH *ccgDM_getPBVH(Object *ob, DerivedMesh *dm) * when the ccgdm gets remade, the assumption is that the topology * does not change. */ ccgdm_create_grids(dm); - BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces); + BLI_pbvh_grids_update(ob->sculpt->pbvh, ccgdm->gridData, ccgdm->gridAdjacency, (void **)ccgdm->gridFaces, + ccgdm->gridFlagMats, ccgdm->gridHidden); } ccgdm->pbvh = ob->sculpt->pbvh; diff --git a/source/blender/blenlib/BLI_pbvh.h b/source/blender/blenlib/BLI_pbvh.h index 9483d068bb9..3445522eb7c 100644 --- a/source/blender/blenlib/BLI_pbvh.h +++ b/source/blender/blenlib/BLI_pbvh.h @@ -28,6 +28,7 @@ #include "BLI_bitmap.h" +struct BLI_bitmap; struct CCGElem; struct CCGKey; struct CustomData; @@ -153,7 +154,8 @@ void BLI_pbvh_update(PBVH *bvh, int flags, float (*face_nors)[3]); void BLI_pbvh_redraw_BB(PBVH * bvh, float bb_min[3], float bb_max[3]); void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface); void BLI_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems, - struct DMGridAdjacency *gridadj, void **gridfaces); + struct DMGridAdjacency *gridadj, void **gridfaces, + struct DMFlagMat *flagmats, struct BLI_bitmap *grid_hidden); /* vertex deformer */ float (*BLI_pbvh_get_vertCos(struct PBVH *pbvh))[3]; diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c index 7637c60ec16..8e9f0bfef10 100644 --- a/source/blender/blenlib/intern/pbvh.c +++ b/source/blender/blenlib/intern/pbvh.c @@ -1707,11 +1707,14 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], } } -void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces) +void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces, + DMFlagMat *flagmats, BLI_bitmap *grid_hidden) { bvh->grids = grids; bvh->gridadj = gridadj; bvh->gridfaces = gridfaces; + bvh->grid_flag_mats = flagmats; + bvh->grid_hidden = grid_hidden; } float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3] From ff1e337bb47ce801e99afeec3d5ccdab5a5a3212 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 8 Nov 2012 14:22:05 +0000 Subject: [PATCH 021/118] Correction to previous commit pBVH nodes buffers could share some pointers from pBVH itself, and after updating pointers in pBVH we need to recreate this buffers. This starts looking a bit awkward and seems it's mainly because of assumptions made when was working on sculpting on deformed mesh. Would revision such a sculpting and would try to make it more clear later. --- source/blender/blenlib/intern/pbvh.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/blender/blenlib/intern/pbvh.c b/source/blender/blenlib/intern/pbvh.c index 8e9f0bfef10..e21ce0716d2 100644 --- a/source/blender/blenlib/intern/pbvh.c +++ b/source/blender/blenlib/intern/pbvh.c @@ -1710,11 +1710,16 @@ void BLI_pbvh_draw(PBVH *bvh, float (*planes)[4], float (*face_nors)[3], void BLI_pbvh_grids_update(PBVH *bvh, CCGElem **grids, DMGridAdjacency *gridadj, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap *grid_hidden) { + int a; + bvh->grids = grids; bvh->gridadj = gridadj; bvh->gridfaces = gridfaces; bvh->grid_flag_mats = flagmats; bvh->grid_hidden = grid_hidden; + + for (a = 0; a < bvh->totnode; ++a) + BLI_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]); } float (*BLI_pbvh_get_vertCos(PBVH * pbvh))[3] From 7681488f974a52d74d37c2a173bd2c6a3cdfe1a5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Thu, 8 Nov 2012 14:34:42 +0000 Subject: [PATCH 022/118] Attempt to fix OSX compilation issue. BLI_bitmap is not a sctruct, so that should be culptrit. --- source/blender/blenlib/BLI_pbvh.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/blender/blenlib/BLI_pbvh.h b/source/blender/blenlib/BLI_pbvh.h index 3445522eb7c..59ecdb359c9 100644 --- a/source/blender/blenlib/BLI_pbvh.h +++ b/source/blender/blenlib/BLI_pbvh.h @@ -28,7 +28,6 @@ #include "BLI_bitmap.h" -struct BLI_bitmap; struct CCGElem; struct CCGKey; struct CustomData; @@ -155,7 +154,7 @@ void BLI_pbvh_redraw_BB(PBVH * bvh, float bb_min[3], float bb_max[3]); void BLI_pbvh_get_grid_updates(PBVH *bvh, int clear, void ***gridfaces, int *totface); void BLI_pbvh_grids_update(PBVH *bvh, struct CCGElem **grid_elems, struct DMGridAdjacency *gridadj, void **gridfaces, - struct DMFlagMat *flagmats, struct BLI_bitmap *grid_hidden); + struct DMFlagMat *flagmats, unsigned int **grid_hidden); /* vertex deformer */ float (*BLI_pbvh_get_vertCos(struct PBVH *pbvh))[3]; From da4441f7c525ccfe88626eaa255a8bc179821d5a Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Thu, 8 Nov 2012 15:12:21 +0000 Subject: [PATCH 023/118] Merge gsoc Bevel (with rounding) into trunk. --- source/blender/bmesh/intern/bmesh_opdefines.c | 8 + source/blender/bmesh/operators/bmo_bevel.c | 1435 ++++++++++++++++- source/blender/editors/mesh/editmesh_tools.c | 71 +- 3 files changed, 1511 insertions(+), 3 deletions(-) diff --git a/source/blender/bmesh/intern/bmesh_opdefines.c b/source/blender/bmesh/intern/bmesh_opdefines.c index 31698f0abc1..398e6bbedcf 100644 --- a/source/blender/bmesh/intern/bmesh_opdefines.c +++ b/source/blender/bmesh/intern/bmesh_opdefines.c @@ -1064,6 +1064,7 @@ static BMOpDefine bmo_create_cube_def = { 0, }; +#define NEW_BEVEL 1 /* * Bevel * @@ -1071,6 +1072,12 @@ static BMOpDefine bmo_create_cube_def = { */ static BMOpDefine bmo_bevel_def = { "bevel", +#ifdef NEW_BEVEL + {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ + {BMO_OP_SLOT_FLT, "offset"}, /* amount to offset beveled edge */ + {BMO_OP_SLOT_INT, "segments"}, /* number of segments in bevel */ + {0} /* null-terminating sentinel */}, +#else {{BMO_OP_SLOT_ELEMENT_BUF, "geom"}, /* input edges and vertices */ {BMO_OP_SLOT_ELEMENT_BUF, "face_spans"}, /* new geometry */ {BMO_OP_SLOT_ELEMENT_BUF, "face_holes"}, /* new geometry */ @@ -1081,6 +1088,7 @@ static BMOpDefine bmo_bevel_def = { {BMO_OP_SLOT_INT, "lengthlayer"}, /* which PROP_FLT layer to us */ {BMO_OP_SLOT_FLT, "percent"}, /* percentage to expand beveled edge */ {0} /* null-terminating sentinel */}, +#endif bmo_bevel_exec, BMO_OP_FLAG_UNTAN_MULTIRES }; diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index c5120571755..dbb8bb43c64 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -15,7 +15,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * - * Contributor(s): Joseph Eagar. + * Contributor(s): Joseph Eagar, Aleksandr Mokhov, Howard Trickey * * ***** END GPL LICENSE BLOCK ***** */ @@ -26,6 +26,7 @@ #include "MEM_guardedalloc.h" +#include "BLI_listbase.h" #include "BLI_array.h" #include "BLI_math.h" #include "BLI_smallhash.h" @@ -36,6 +37,1437 @@ #include "intern/bmesh_operators_private.h" /* own include */ +#define NEW_BEVEL 1 + +#ifdef NEW_BEVEL +#define BEVEL_FLAG 1 +#define EDGE_SELECTED 2 + +#define BEVEL_EPSILON 1e-6 + +/* Constructed vertex, sometimes later instantiated as BMVert */ +typedef struct NewVert { + float co[3]; + BMVert *v; +} NewVert; + +struct BoundVert; + +/* Data for one end of an edge involved in a bevel */ +typedef struct EdgeHalf { + struct EdgeHalf *next, *prev; /* in CCW order */ + BMEdge *e; /* original mesh edge */ + int isbev; /* is this edge beveled? */ + int isrev; /* is e->v2 the vertex at this end? */ + int seg; /* how many segments for the bevel */ + float offset; /* offset for this edge */ + BMFace *fprev; /* face between this edge and previous, if any */ + BMFace *fnext; /* face between this edge and next, if any */ + struct BoundVert *leftv; /* left boundary vert (looking along edge to end) */ + struct BoundVert *rightv; /* right boundary vert, if beveled */ +} EdgeHalf; + +/* An element in a cyclic boundary of a Vertex Mesh (VMesh) */ +typedef struct BoundVert { + struct BoundVert *next, *prev; /* in CCW order */ + int index; /* used for vmesh indexing */ + NewVert nv; + EdgeHalf *efirst; /* first of edges attached here: in CCW order */ + EdgeHalf *elast; + EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */ +} BoundVert; + +/* Mesh structure replacing a vertex */ +typedef struct VMesh { + enum { + M_NONE, /* no polygon mesh needed */ + M_POLY, /* a simple polygon */ + M_ADJ, /* "adjacent edges" mesh pattern */ + M_CROSS, /* "cross edges" mesh pattern */ + } mesh_kind; + int count; /* number of vertices in the boundary */ + int seg; /* common # of segments for segmented edges */ + BoundVert *boundstart; /* start of boundary double-linked list */ + NewVert *mesh; /* allocated array - size and structure depends on kind */ +} VMesh; + +/* Data for a vertex involved in a bevel */ +typedef struct BevVert { + struct BevVert *next, *prev; + BMVert *v; /* original mesh vertex */ + int edgecount; /* total number of edges around the vertex */ + int selcount; /* number of selected edges around the vertex */ + EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */ + VMesh *vmesh; /* mesh structure for replacing vertex */ +} BevVert; + +/* + * Bevel parameters and state + */ +typedef struct BevelParams { + ListBase vertList; /* list of BevVert for each vertex involved in bevel */ + float offset; /* blender units to offset each side of a beveled edge */ + int seg; /* number of segments in beveled edge profile */ + + BMOperator *op; +} BevelParams; + +/* Make a new BoundVert of the given kind, insert it at the end of the circular linked + * list with entry point bv->boundstart, and return it. */ +static BoundVert * add_new_bound_vert(VMesh *vm, float co[3]) +{ + BoundVert *ans = (BoundVert*) MEM_callocN(sizeof(BoundVert), "BoundVert"); + copy_v3_v3(ans->nv.co, co); + if (!vm->boundstart) { + ans->index = 0; + vm->boundstart = ans; + ans->next = ans->prev = ans; + } + else { + BoundVert *tail = vm->boundstart->prev; + ans->index = tail->index + 1; + ans->prev = tail; + ans->next = vm->boundstart; + tail->next = ans; + vm->boundstart->prev = ans; + } + vm->count++; + return ans; +} + +/* Mesh verts are indexed (i, j, k) where + * i = boundvert index (0 <= i < nv) + * j = ring index (0 <= j <= ns2) + * k = segment index (0 <= k <= ns) + * Not all of these are used, and some will share BMVerts */ +static NewVert* mesh_vert(VMesh* vm, int i, int j, int k) +{ + int nj = (vm -> seg / 2) + 1; + int nk = vm->seg + 1; + + return &vm->mesh[i * nk * nj + j * nk + k]; +} + +static void create_mesh_bmvert(BMesh* bm, VMesh *vm, int i, int j, int k, BMVert *eg) +{ + NewVert *nv = mesh_vert(vm, i, j, k); + nv->v = BM_vert_create(bm, nv->co, eg); +} + +static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, + int ifrom, int jfrom, int kfrom) +{ + NewVert *nvto, *nvfrom; + + nvto = mesh_vert(vm, ito, jto, kto); + nvfrom = mesh_vert(vm, ifrom, jfrom, kfrom); + nvto->v = nvfrom->v; + copy_v3_v3(nvto->co, nvfrom->co); +} + +/* find the EdgeHalf in bv's array that has edge bme */ +static EdgeHalf* find_edge_half(BevVert *bv, BMEdge *bme) +{ + int i; + + for (i = 0; i < bv->edgecount; i++) { + if (bv->edges[i].e == bme) + return &bv->edges[i]; + } + return NULL; +} + +/* Return the next EdgeHalf after from_e that is beveled. + * If from_e is NULL, find the first beveled edge. */ +static EdgeHalf* next_bev(BevVert *bv, EdgeHalf *from_e) +{ + EdgeHalf *e; + + if (from_e == NULL) + from_e = &bv->edges[bv->edgecount -1]; + e = from_e; + do { + if (e->isbev) + return e; + e = e->next; + } while (e != from_e); + return NULL; +} + +/* find the BevVert corresponding to BMVert bmv */ +static BevVert* find_bevvert(BevelParams *bp, BMVert *bmv) +{ + BevVert *bv; + + for (bv = bp->vertList.first; bv; bv = bv->next) { + if (bv->v == bmv) + return bv; + } + return NULL; +} + +/* Return a good respresentative face (for materials, etc.) for faces + * created around/near BoundVert v */ +static BMFace* boundvert_rep_face(BoundVert *v) +{ + BMFace *fans = NULL; + BMFace *firstf = NULL; + BMEdge *e1, *e2; + BMFace *f1, *f2; + BMIter iter1, iter2; + + BLI_assert(v->efirst != NULL && v->elast != NULL); + e1 = v->efirst->e; + e2 = v->elast->e; + BM_ITER_ELEM(f1, &iter1, e1, BM_FACES_OF_EDGE) { + if (!firstf) + firstf = f1; + BM_ITER_ELEM(f2, &iter2, e2, BM_FACES_OF_EDGE) { + if (f1 == f2) { + fans = f1; + break; + } + } + } + if (!fans) + fans = firstf; + + return fans; +} + +/* Make ngon from verts alone. + * Make sure to properly copy face attributes and do custom data interpolation from + * example face, facerep. */ +static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, int totv, BMFace *facerep) +{ + BMIter iter; + BMLoop *l; + BMFace *f; + + if (totv == 3) { + f = BM_face_create_quad_tri(bm, + vert_arr[0], vert_arr[1], vert_arr[2], NULL, facerep, 0); + } + else if (totv == 4) { + f = BM_face_create_quad_tri(bm, + vert_arr[0], vert_arr[1], vert_arr[2], vert_arr[3], facerep, 0); + } + else { + int i; + BMEdge *e; + BMEdge **ee = NULL; + BLI_array_staticdeclare(ee, 30); + + for (i = 0; i < totv; i++) { + e = BM_edge_create(bm, vert_arr[i], vert_arr[(i + 1) % totv], NULL, TRUE); + BLI_array_append(ee, e); + } + f = BM_face_create_ngon(bm, vert_arr[0], vert_arr[1], ee, totv, FALSE); + BLI_array_free(ee); + } + if (facerep && f) { + int has_mdisps = CustomData_has_layer(&bm->ldata, CD_MDISPS); + BM_elem_attrs_copy(bm, bm, facerep, f); + BM_ITER_ELEM(l, &iter, f, BM_LOOPS_OF_FACE) { + BM_loop_interp_from_face(bm, l, facerep, TRUE, TRUE); + if (has_mdisps) + BM_loop_interp_multires(bm, l, facerep); + } + } + return f; +} + +static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, + BMFace *facerep) +{ + BMVert *varr[4]; + + varr[0] = v1; + varr[1] = v2; + varr[2] = v3; + varr[3] = v4; + return bev_create_ngon(bm, varr, v4 ? 4 : 3, facerep); +} + +/* + * Calculate the meeting point between the offset edges for e1 and e2, putting answer in meetco. + * e1 and e2 share vertex v and face f (may be NULL) and viewed from the normal side of + * the bevel vertex, e1 precedes e2 in CCW order. + * If on_right is true, offset edge is on right of both edges, where e1 enters v and + * e2 leave it. If on_right is false, then the offset edge is on the left. + * When offsets are equal, the new point is on the edge bisector, with length offset/sin(angle/2), + * but if the offsets are not equal (allowing for this, as bevel modifier has edge weights that may + * lead to different offsets) then meeting point can be found be intersecting offset lines. + */ +static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, + int on_right, float meetco[3]) +{ + float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3], + off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; + + /* get direction vectors for two offset lines */ + sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); + sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); + + /* get normal to plane where meet point should be */ + cross_v3_v3v3(norm_v, dir2, dir1); + normalize_v3(norm_v); + if (!on_right) + negate_v3(norm_v); + if (is_zero_v3(norm_v)) { + /* special case: e1 and e2 are parallel; put offset point perp to both, from v. + * need to find a suitable plane. + * if offsets are different, we're out of luck: just use e1->offset */ + if (f) + copy_v3_v3(norm_v, f->no); + else + copy_v3_v3(norm_v, v->no); + cross_v3_v3v3(norm_perp1, dir1, norm_v); + normalize_v3(norm_perp1); + copy_v3_v3(off1a, v->co); + madd_v3_v3fl(off1a, norm_perp1, e1->offset); + copy_v3_v3(meetco, off1a); + } + else { + /* get vectors perp to each edge, perp to norm_v, and pointing into face */ + if (f) { + copy_v3_v3(norm_v, f->no); + normalize_v3(norm_v); + } + cross_v3_v3v3(norm_perp1, dir1, norm_v); + cross_v3_v3v3(norm_perp2, dir2, norm_v); + normalize_v3(norm_perp1); + normalize_v3(norm_perp2); + + /* get points that are offset distances from each line, then another point on each line */ + copy_v3_v3(off1a, v->co); + madd_v3_v3fl(off1a, norm_perp1, e1->offset); + add_v3_v3v3(off1b, off1a, dir1); + copy_v3_v3(off2a, v->co); + madd_v3_v3fl(off2a, norm_perp2, e2->offset); + add_v3_v3v3(off2b, off2a, dir2); + + /* intersect the lines; by construction they should be on the same plane and not parallel */ + if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) { + BLI_assert(!"offset_meet failure"); + copy_v3_v3(meetco, off1a); /* just to do something */ + } + } +} + +/* Like offset_meet, but here f1 and f2 must not be NULL and give the + * planes in which to run the offset lines. They may not meet exactly, + * but the line intersection routine will find the closest approach point. */ +static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, + BMFace *f1, BMFace *f2, float meetco[3]) +{ + float dir1[3], dir2[3], norm_perp1[3], norm_perp2[3], + off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; + + BLI_assert(f1 != NULL && f2 != NULL); + + /* get direction vectors for two offset lines */ + sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); + sub_v3_v3v3(dir2, BM_edge_other_vert(e2->e, v)->co, v->co); + + /* get directions into offset planes */ + cross_v3_v3v3(norm_perp1, dir1, f1->no); + normalize_v3(norm_perp1); + cross_v3_v3v3(norm_perp2, dir2, f2->no); + normalize_v3(norm_perp2); + + /* get points that are offset distances from each line, then another point on each line */ + copy_v3_v3(off1a, v->co); + madd_v3_v3fl(off1a, norm_perp1, e1->offset); + add_v3_v3v3(off1b, off1a, dir1); + copy_v3_v3(off2a, v->co); + madd_v3_v3fl(off2a, norm_perp2, e2->offset); + add_v3_v3v3(off2b, off2a, dir2); + + /* intersect the lines; by construction they should be on the same plane and not parallel */ + if (!isect_line_line_v3(off1a, off1b, off2a, off2b, meetco, isect2)) { + BLI_assert(!"offset_meet failure"); + copy_v3_v3(meetco, off1a); /* just to do something */ + } +} + +/* Offset by e->offset in plane with normal plane_no, on left if left==TRUE, + * else on right. If no is NULL, choose an arbitrary plane different + * from eh's direction. */ +static void offset_in_plane(EdgeHalf *e, float plane_no[3], int left, float r[3]) +{ + float dir[3], no[3]; + BMVert *v; + + v = e->isrev? e->e->v1 : e->e->v2; + + sub_v3_v3v3(dir,BM_edge_other_vert(e->e, v)->co, v->co); + normalize_v3(dir); + if (plane_no) { + copy_v3_v3(no, plane_no); + } + else { + zero_v3(no); + if (fabs(dir[0]) < fabs(dir[1])) + no[0] = 1.0f; + else + no[1] = 1.0f; + } + if (left) + cross_v3_v3v3(r, no, dir); + else + cross_v3_v3v3(r, dir, no); + normalize_v3(r); + mul_v3_fl(r, e->offset); +} + +/* Calculate coordinates of a point a distance d from v on e->e and return it in slideco */ +static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3]) +{ + float dir[3], len; + + sub_v3_v3v3(dir, v->co, BM_edge_other_vert(e->e, v)->co); + len = len_v3(dir); + normalize_v3(dir); + if (d > len) + d = len - 50 * BEVEL_EPSILON; + copy_v3_v3(slideco, v->co); + madd_v3_v3fl(slideco, dir, -d); +} + +/* Calculate the point on e where line (co_a, co_b) comes closest to and return it in projco */ +static void project_to_edge(BMEdge *e, float co_a[3], float co_b[3], float projco[3]) +{ + float otherco[3]; + + if (!isect_line_line_v3(e->v1->co, e->v2->co, co_a, co_b, + projco, otherco)) { + BLI_assert(!"project meet failure"); + copy_v3_v3(projco, e->v1->co); + } +} + + +/* return 1 if a and b are in CCW order on the normal side of f, + * and -1 if they are reversed, and 0 if there is no shared face f */ +static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f) +{ + BMLoop *la, *lb; + + if (!f) + return 0; + la = BM_face_edge_share_loop(f, a); + lb = BM_face_edge_share_loop(f, b); + if (!la || !lb) + return 0; + return lb->next == la ? 1 : -1; +} + +/* +* Search for crossing the line and line +* a1-a2 lineA +* b1-b2 line B +* r - result, coordinate of crossing point +*/ +static int find_intersection_point(float r[3], float a1[3], float a2[3], float b1[3], float b2[3]) +{ + double s, t, z1, z2; + double mx, my, nx, ny; + int flag =0; + + mx = a2[0] - a1[0]; + my = a2[1] - a1[1]; + + nx = b2[0] - b1[0]; + ny = b2[1] - b1[1]; + + s = ((b1[1] - a1[1]) / my + (a1[0] - b1[0])/ mx ) / (nx / mx - ny / my); + t = (b1[0] - a1[0] + s * nx) / mx; + + + z1 = a1[2] + t * (a2[2] -a1[2]); + z2 = b1[2] + s * (b2[2] -b1[2]); + + if ( fabs(z1-z2) < BEVEL_EPSILON ){ + flag = 1; + r[0] = a1[0] + t * mx; + r[1] = a1[1] + t * my; + r[2] = z1; + } + else + flag = 0; + + return flag; +} + +/* +* Search for crossing the line and plane +* p1, p2, p3 points which is given by the plane +* a - line vector +* m - point through which the line +* r - result; +*/ +static void find_intersection_point_plane(float r[3], float p1[3], float p2[3], float p3[3], + float a[3], float m[3]) +{ + float P[3], N[3], A[3], M[3]; + float vv1[3], vv2[3]; + double t; + double C, D, E; + float null = 1e-20; + + + /* calculation of the normal to the surface */ + sub_v3_v3v3(vv1, p1, p2); + sub_v3_v3v3(vv2, p3, p2); + cross_v3_v3v3(N, vv1, vv2); + + copy_v3_v3(A, a); + copy_v3_v3(P, p2); + copy_v3_v3(M, m); + + + if (fabs(N[0] * (A[0]-P[0]) + N[1] * (A[1]-P[1]) + N[2] * (A[2]-P[2])) < BEVEL_EPSILON) { + /* point located on plane */ + float tmp[3], line[3]; + add_v3_v3v3(line, a, m); + if (find_intersection_point(tmp, m, a, p1, p2)) + copy_v3_v3(r, tmp); + else { + if (find_intersection_point(tmp, m, a, p2, p3)) + copy_v3_v3(r, tmp); + } + + } + else { + C = N[0] * P[0] + N[1] * P[1] + N[2] * P[2]; + D = N[0] * M[0] + N[1] * M[1] + N[2] * M[2]; + E = (A[0] * N[0] + A[1] * N[1] + A[2] * N[2]); + + if (fabs(E)< null) + t = 0; + else + t = (C-D)/E; + + r[0] = m[0] + t * a [0]; + r[1] = m[1] + t * a [1]; + r[2] = m[2] + t * a [2]; + } + +} + +/* + * calculation of points on the round profile + * r - result, coordinate of point on round profile + * method: + * Inscribe a circle in angle va - v -vb + * such that it touches the arms at offset from v. + * Rotate the center-va segment by (i/n) of the + * angle va - center -vb, and put the endpoint + * of that segment in r. + */ +static void get_point_on_round_profile(float r[3], float offset, int i, int count, + float va[3], float v[3], float vb[3]) +{ + float vva[3], vvb[3], angle, center[3], rv[3], axis[3], co[3]; + + sub_v3_v3v3(vva, va, v); + sub_v3_v3v3(vvb, vb, v); + normalize_v3(vva); + normalize_v3(vvb); + angle = angle_v3v3(vva, vvb); + + add_v3_v3v3(center, vva, vvb); + normalize_v3(center); + mul_v3_fl(center, offset * (1.0 / cos(0.5 * angle))); + add_v3_v3(center, v); /* coordinates of the center of the inscribed circle */ + + + sub_v3_v3v3(rv, va, center); /* radius vector */ + + + sub_v3_v3v3(co, v, center); + cross_v3_v3v3(axis, rv, co); /* calculate axis */ + + sub_v3_v3v3(vva, va, center); + sub_v3_v3v3(vvb, vb, center); + angle = angle_v3v3(vva, vvb); + + rotate_v3_v3v3fl(co, rv, axis, angle * (float)(i) / (float)(count)); + + add_v3_v3(co, center); + copy_v3_v3(r, co); +} + +/* + * Find the point (i/n) of the way around the round profile for e, + * where start point is va, midarc point is vmid, and end point is vb. + * Return the answer in profileco. + * Method: + * Adjust va and vb (along edge direction) so that they are perpendicular + * to edge at v, then use get_point_on_round_profile, then project + * back onto original va - vmid - vb plane. + * If va, vmid, and vb are all on the same plane, just interpolate between va and vb. + */ +static void get_point_on_round_edge(EdgeHalf *e, int i, + float va[3], float vmid[3], float vb[3], float profileco[3]) +{ + float vva[3], vvb[3], point[3], dir[3], vaadj[3], vbadj[3]; + int n = e->seg; + + sub_v3_v3v3(vva, va, vmid); + sub_v3_v3v3(vvb, vb, vmid); + if (e->isrev) + sub_v3_v3v3(dir, e->e->v1->co, e->e->v2->co); + else + sub_v3_v3v3(dir, e->e->v2->co, e->e->v1->co); + normalize_v3(dir); + if (fabs(angle_v3v3(vva, vvb)- M_PI) > BEVEL_EPSILON) { + copy_v3_v3(vaadj, va); + madd_v3_v3fl(vaadj, dir, -len_v3(vva) * cosf(angle_v3v3(vva, dir))); + copy_v3_v3(vbadj, vb); + madd_v3_v3fl(vbadj, dir, -len_v3(vvb) * cosf(angle_v3v3(vvb, dir))); + + get_point_on_round_profile(point, e->offset, i, n, vaadj, vmid, vbadj); + + find_intersection_point_plane(profileco, va, vmid, vb, dir, point); + } + else { + /* planar case */ + interp_v3_v3v3(profileco, va, vb, (float) i / (float) n); + } +} + +static void mid_v3_v3v3v3(float v[3], const float v1[3], const float v2[3], const float v3[3]) +{ + v[0] = (v1[0] + v2[0] + v3[0]) / 3.0f; + v[1] = (v1[1] + v2[1] + v3[1]) / 3.0f; + v[2] = (v1[2] + v2[2] + v3[2]) / 3.0f; +} + +/* Make a circular list of BoundVerts for bv, each of which has the coordinates + * of a vertex on the the boundary of the beveled vertex bv->v. + * Also decide on the mesh pattern that will be used inside the boundary. + * Doesn't make the actual BMVerts */ +static void build_boundary(BevVert *bv) +{ + EdgeHalf *efirst, *e; + BoundVert *v; + VMesh *vm; + float co[3], *no; + float lastd; + + e = efirst = next_bev(bv, NULL); + vm = bv->vmesh; + + BLI_assert(bv->edgecount >= 2); /* since bevel edges incident to 2 faces */ + + if (bv->edgecount == 2 && bv->selcount == 1) { + /* special case: beveled edge meets non-beveled one at valence 2 vert */ + no = e->fprev ? e->fprev->no : (e->fnext? e->fnext->no : NULL); + offset_in_plane(e, no, TRUE, co); + v = add_new_bound_vert(vm, co); + v->efirst = v->elast = v->ebev = e; + e->leftv = v; + no = e->fnext ? e->fnext->no : (e->fprev? e->fprev->no : NULL); + offset_in_plane(e, no, FALSE, co); + v = add_new_bound_vert(vm, co); + v->efirst = v->elast = e; + e->rightv = v; + /* make artifical extra point along unbeveled edge, and form triangle */ + slide_dist(e->next, bv->v, e->offset, co); + v = add_new_bound_vert(vm, co); + v->efirst = v->elast = e->next; + vm->mesh_kind = M_POLY; + return; + } + + lastd = e->offset; + vm->boundstart = NULL; + do { + if (e->isbev) { + /* handle only left side of beveled edge e here: next iteration should do right side */ + if (e->prev->isbev) { + BLI_assert(e->prev != e); /* see: wire edge special case */ + offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); + v = add_new_bound_vert(vm, co); + v->efirst = e->prev; + v->elast = v->ebev = e; + e->leftv = v; + e->prev->rightv = v; + } + else { + /* e->prev is not beveled */ + if (e->prev->prev->isbev) { + BLI_assert(e->prev->prev != e); /* see: edgecount 2, selcount 1 case */ + /* find meet point between e->prev->prev and e and attach e->prev there */ + /* TODO: fix case when one or both faces in following are NULL */ + offset_in_two_planes(e->prev->prev, e, bv->v, + e->prev->prev->fnext, e->fprev, co); + v = add_new_bound_vert(vm, co); + v->efirst = e->prev->prev; + v->elast = v->ebev = e; + e->leftv = v; + e->prev->leftv = v; + e->prev->prev->rightv = v; + } + else { + /* neither e->prev nor e->prev->prev are beveled: make on-edge on e->prev */ + offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); + v = add_new_bound_vert(vm, co); + v->efirst = e->prev; + v->elast = v->ebev = e; + e->leftv = v; + e->prev->leftv = v; + } + } + lastd = len_v3v3(bv->v->co, v->nv.co); + } + else { + /* e is not beveled */ + if (e->next->isbev) { + /* next iteration will place e between beveled previous and next edges */ + e = e->next; + continue; + } + if (e->prev->isbev) { + /* on-edge meet between e->prev and e */ + offset_meet(e->prev, e, bv->v, e->fprev, TRUE, co); + v = add_new_bound_vert(vm, co); + v->efirst = e->prev; + v->elast = e; + e->leftv = v; + e->prev->rightv = v; + } + else { + /* None of e->prev, e, e->next are beveled. + * could either leave alone or add slide points to make + * one polygon around bv->v. For now, we choose latter. + * Could slide to make an even bevel plane but for now will + * just use last distance a meet point moved from bv->v. */ + slide_dist(e, bv->v, lastd, co); + v = add_new_bound_vert(vm, co); + v->efirst = v->elast = e; + e->leftv = v; + } + } + e = e->next; + } while (e != efirst); + + BLI_assert(vm->count >= 2); + if (vm->count == 2 && bv->edgecount == 3) + vm->mesh_kind = M_NONE; + else if (efirst->seg == 1 || bv->selcount < 3) + vm->mesh_kind = M_POLY; + else + vm->mesh_kind = M_ADJ; + /* TODO: if vm->count == 4 and bv->selcount == 4, use M_CROSS pattern */ +} + +/* + * Given that the boundary is built and the boundary BMVerts have been made, + * calculate the positions of the interior mesh points for the M_ADJ pattern, + * then make the BMVerts and the new faces. */ +static void bevel_build_rings(BMesh *bm, BevVert *bv) +{ + int k, ring, i, n, ns, ns2, nn; + VMesh *vm = bv->vmesh; + BoundVert *v, *vprev, *vnext; + NewVert *nv, *nvprev, *nvnext; + BMVert *bmv, *bmv1, *bmv2, *bmv3, *bmv4; + BMFace *f; + float co[3], coa[3], cob[3], midco[3]; + + n = vm->count; + ns = vm->seg; + ns2 = ns / 2; + BLI_assert(n > 2 && ns > 1); + + /* Make initial rings, going between points on neighbors */ + for (ring = 1; ring <= ns2; ring++) { + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + /* get points coords of points a and b, on outer rings + * of prev and next edges, k away from this edge */ + vprev = v->prev; + vnext = v->next; + + if (vprev->ebev) + nvprev = mesh_vert(vm, vprev->index, 0, ns - ring); + else + nvprev = mesh_vert(vm, vprev->index, 0, ns); + copy_v3_v3(coa, nvprev->co); + nv = mesh_vert(vm, i, ring, 0); + copy_v3_v3(nv->co, coa); + nv->v = nvprev->v; + + if (vnext->ebev) + nvnext = mesh_vert(vm, vnext->index, 0, ring); + else + nvnext = mesh_vert(vm, vnext->index, 0, 0); + copy_v3_v3(cob, nvnext->co); + nv = mesh_vert(vm, i, ring, ns); + copy_v3_v3(nv->co, cob); + nv->v = nvnext->v; + + /* TODO: better calculation of new midarc point? */ + project_to_edge(v->ebev->e, coa, cob, midco); + + for (k = 1; k < ns; k++) { + get_point_on_round_edge(v->ebev, k, coa, midco, cob, co); + copy_v3_v3(mesh_vert(vm, i, ring, k)->co, co); + } + } + v = v->next; + } while (v != vm->boundstart); + } + + /* Now make sure cross points of rings share coordinates and vertices */ + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + vprev = v->prev; + vnext = v->next; + if (vprev->ebev) { + for (ring = 1; ring <= ns2; ring++) { + for (k = 1; k <= ns2; k++) { + if (ns % 2 == 0 && (k == ns2 || ring == ns2)) + continue; /* center line is special case: do after the rest are done */ + nv = mesh_vert(vm, i, ring, k); + nvprev = mesh_vert(vm, vprev->index, k, ns - ring); + mid_v3_v3v3(co, nv->co, nvprev->co); + copy_v3_v3(nv->co, co); + BLI_assert(nv->v == NULL && nvprev->v == NULL); + create_mesh_bmvert(bm, vm, i, ring, k, bv->v); + copy_mesh_vert(vm, vprev->index, k, ns - ring, i, ring, k); + } + } + if (!vprev->prev->ebev) { + for (ring = 1; ring <= ns2; ring++) { + for (k = 1; k <= ns2; k++) { + if (ns % 2 == 0 && (k == ns2 || ring == ns2)) + continue; + create_mesh_bmvert(bm, vm, vprev->index, ring, k, bv->v); + } + } + } + if (!vnext->ebev) { + for (ring = 1; ring <= ns2; ring++) { + for (k = ns - ns2; k < ns; k++) { + if (ns % 2 == 0 && (k == ns2 || ring == ns2)) + continue; + create_mesh_bmvert(bm, vm, i, ring, k, bv->v); + } + } + } + } + } + v = v->next; + } while (v != vm->boundstart); + + if (ns % 2 == 0) { + /* do special case center lines */ + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + vprev = v->prev; + vnext = v->next; + for (k = 1; k < ns2; k++) { + nv = mesh_vert(vm, i, k, ns2); + if (vprev->ebev) + nvprev = mesh_vert(vm, vprev->index, ns2, ns - k); + if (vnext->ebev) + nvnext = mesh_vert(vm, vnext->index, ns2, k); + if (vprev->ebev && vnext->ebev) { + mid_v3_v3v3v3(co, nvprev->co, nv->co, nvnext->co); + copy_v3_v3(nv->co, co); + create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); + copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2); + copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2); + + } + else if (vprev->ebev) { + mid_v3_v3v3(co, nvprev->co, nv->co); + copy_v3_v3(nv->co, co); + create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); + copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2); + } + else if (vnext->ebev) { + mid_v3_v3v3(co, nv->co, nvnext->co); + copy_v3_v3(nv->co, co); + create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); + copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2); + } + } + } + v = v->next; + } while (v != vm->boundstart); + + /* center point need to be average of all centers of rings */ + /* TODO: this is wrong if not all verts have ebev: could hae + * several disconnected sections of mesh. */ + zero_v3(midco); + nn = 0; + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + nv = mesh_vert(vm, i, ns2, ns2); + add_v3_v3(midco, nv->co); + nn++; + } + v = v->next; + } while (v != vm->boundstart); + mul_v3_fl(midco, 1.0f/nn); + bmv = BM_vert_create(bm, midco, NULL); + v = vm->boundstart; + do { + i = v->index; + if (v->ebev) { + nv = mesh_vert(vm, i, ns2, ns2); + copy_v3_v3(nv->co, midco); + nv->v = bmv; + } + v = v->next; + } while (v != vm->boundstart); + } + + /* Make the ring quads */ + for (ring = 0; ring < ns2; ring++) { + v = vm->boundstart; + do { + i = v->index; + f = boundvert_rep_face(v); + if (v->ebev && (v->prev->ebev || v->next->ebev)) { + for (k = 0; k < ns2 + (ns % 2); k++) { + bmv1 = mesh_vert(vm, i, ring, k)->v; + bmv2 = mesh_vert(vm, i, ring, k + 1)->v; + bmv3 = mesh_vert(vm, i, ring + 1, k + 1)->v; + bmv4 = mesh_vert(vm, i, ring + 1, k)->v; + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + if (bmv3 == bmv4 || bmv1 == bmv4) + bmv4 = NULL; + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f); + } + } + else if (v->prev->ebev && v->prev->prev->ebev) { + /* finish off a sequence of beveled edges */ + i = v->prev->index; + f = boundvert_rep_face(v->prev); + for (k = ns2 + (ns % 2); k < ns; k++) { + bmv1 = mesh_vert(vm, i, ring + 1, k)->v; + bmv2 = mesh_vert(vm, i, ring, k)->v; + bmv3 = mesh_vert(vm, i, ring, k + 1)->v; + BLI_assert(bmv1 && bmv2 && bmv3); + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, NULL, f); + } + } + v = v->next; + } while (v != vm->boundstart); + } + + /* Make center ngon if odd number of segments and fully beveled */ + if (ns % 2 == 1 && vm->count == bv->selcount) { + BMVert **vv = NULL; + BLI_array_declare(vv); + + v = vm->boundstart; + do { + i = v->index; + BLI_assert(v->ebev); + BLI_array_append(vv, mesh_vert(vm, i, ns2, ns2)->v); + v = v->next; + } while (v != vm->boundstart); + f = boundvert_rep_face(vm->boundstart); + bev_create_ngon(bm, vv, BLI_array_count(vv), f); + + BLI_array_free(vv); + } + + /* Make 'rest-of-vmesh' polygon if not fully beveled */ + if (vm->count > bv->selcount) { + int j; + BMVert **vv = NULL; + BLI_array_declare(vv); + + v = vm->boundstart; + f = boundvert_rep_face(v); + j = 0; + do { + i = v->index; + if (v->ebev) { + if (!v->prev->ebev) { + for (k = 0; k < ns2; k++) { + bmv1 = mesh_vert(vm, i, ns2, k)->v; + if (!(j > 0 && bmv1 == vv[j-1])) { + BLI_array_append(vv, bmv1); + j++; + } + } + } + bmv1 = mesh_vert(vm, i, ns2, ns2)->v; + if (!(j > 0 && bmv1 == vv[j-1])) { + BLI_array_append(vv, bmv1); + j++; + } + if (!v->next->ebev) { + for (k = ns -ns2; k < ns; k++) { + bmv1 = mesh_vert(vm, i, ns2, k)->v; + if (!(j > 0 && bmv1 == vv[j-1])) { + BLI_array_append(vv, bmv1); + j++; + } + } + } + } + else { + BLI_array_append(vv, mesh_vert(vm, i, 0, 0)->v); + j++; + } + v = v->next; + } while (v != vm->boundstart); + if (vv[0] == vv[j-1]) + j--; + bev_create_ngon(bm, vv, j, f); + + BLI_array_free(vv); + } +} + +static void bevel_build_poly(BMesh *bm, BevVert *bv) +{ + int n, k; + VMesh *vm = bv->vmesh; + BoundVert *v; + BMVert **vv = NULL; + BLI_array_declare(vv); + + v = vm->boundstart; + n = 0; + do { + /* accumulate vertices for vertex ngon */ + BLI_array_append(vv, v->nv.v); + n++; + if (v->ebev && v->ebev->seg > 1) { + for (k = 1; k < v->ebev->seg; k++) { + BLI_array_append(vv, mesh_vert(vm, v->index, 0, k)->v); + n++; + } + } + v = v->next; + } while (v != vm->boundstart); + if (n > 2) + bev_create_ngon(bm, vv, n, boundvert_rep_face(v)); + BLI_array_free(vv); +} + +/* Given that the boundary is built, now make the actual BMVerts + * for the boundary and the interior of the vertex mesh. */ +static void build_vmesh(BMesh *bm, BevVert *bv) +{ + VMesh *vm = bv->vmesh; + BoundVert *v, *weld1, *weld2; + int n, ns, ns2, i, k, weld; + float *va, *vb, co[3], midco[3]; + + n = vm->count; + ns = vm->seg; + ns2 = ns / 2; + + vm->mesh = (NewVert*)MEM_callocN(n * (ns2 + 1) * (ns + 1) * sizeof(NewVert), "NewVert"); + + /* special case: two beveled ends welded together */ + weld = (bv->selcount == 2) && (vm->count == 2); + weld1 = weld2 = NULL; /* will hold two BoundVerts involved in weld */ + + /* make (i, 0, 0) mesh verts for all i */ + v = vm->boundstart; + do { + i = v->index; + copy_v3_v3(mesh_vert(vm, i, 0, 0)->co, v->nv.co); + create_mesh_bmvert(bm, vm, i, 0, 0, bv->v); + v->nv.v = mesh_vert(vm, i, 0, 0)->v; + if (weld && v->ebev) { + if (!weld1) + weld1 = v; + else + weld2 = v; + } + v = v->next; + } while (v != vm->boundstart); + + /* copy other ends to (i, 0, ns) for all i, and fill in profiles for beveled edges */ + v = vm->boundstart; + do { + i = v->index; + copy_mesh_vert(vm, i, 0, ns, v->next->index, 0, 0); + if (v->ebev) { + va = mesh_vert(vm, i, 0, 0)->co; + vb = mesh_vert(vm, i, 0, ns)->co; + project_to_edge(v->ebev->e, va, vb, midco); + for (k = 1; k < ns; k++) { + get_point_on_round_edge(v->ebev, k, va, midco, vb, co); + copy_v3_v3(mesh_vert(vm, i, 0, k)->co, co); + if (!weld) + create_mesh_bmvert(bm, vm, i, 0, k, bv->v); + } + } + v = v->next; + } while (v != vm->boundstart); + + if (weld) { + for (k = 1; k < ns; k++) { + mid_v3_v3v3(co, mesh_vert(vm, weld1->index, 0, k)->co, + mesh_vert(vm, weld2->index, 0, ns - k)->co); + copy_v3_v3(mesh_vert(vm, weld1->index, 0, k)->co, co); + create_mesh_bmvert(bm, vm, weld1->index, 0, k, bv->v); + } + for (k = 1; k < ns; k++) + copy_mesh_vert(vm, weld2->index, 0, ns - k, weld1->index, 0, k); + } + + if (vm->mesh_kind == M_ADJ) + bevel_build_rings(bm, bv); + else if (vm->mesh_kind == M_POLY) + bevel_build_poly(bm, bv); +} + +/* + * Construction around the vertex + */ +static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMOperator *op, BMVert *v) +{ + + BMOIter siter; + BMEdge *bme; + BevVert *bv; + BMEdge *bme2, *unflagged_bme; + BMFace *f; + BMIter iter, iter2; + EdgeHalf *e; + int i, ntot, found_shared_face, ccw_test_sum; + int nsel = 0; + + /* Gather input selected edges. + * Only bevel selected edges that have exactly two incident faces. */ + BMO_ITER (bme, &siter, bm, op, "geom", BM_EDGE) { + if ((bme->v1 == v)|| (BM_edge_other_vert(bme, bme->v1) == v)) + { + if (BM_edge_face_count(bme) == 2) { + BMO_elem_flag_enable (bm, bme, EDGE_SELECTED); + nsel++; + } + } + } + + if (nsel == 0) + return; + + ntot = BM_vert_edge_count(v); + bv = (BevVert*)MEM_callocN(sizeof(BevVert), "BevVert"); + bv->v = v; + bv->edgecount = ntot; + bv->selcount = nsel; + bv->edges = (EdgeHalf*)MEM_callocN(ntot * sizeof(EdgeHalf), "EdgeHalf"); + bv->vmesh = (VMesh *)MEM_callocN(sizeof(VMesh), "VMesh"); + bv->vmesh->seg = bp->seg; + BLI_addtail(&bp->vertList, bv); + + /* add edges to bv->edges in order that keeps adjacent edges sharing + * a face, if possible */ + i = 0; + bme = v->e; + BMO_elem_flag_enable(bm, bme, BEVEL_FLAG); + e = &bv->edges[0]; + e->e = bme; + for (i = 0; i < ntot; i++) { + if (i > 0) { + /* find an unflagged edge bme2 that shares a face f with previous bme */ + found_shared_face = 0; + unflagged_bme = NULL; + BM_ITER_ELEM(bme2, &iter, v, BM_EDGES_OF_VERT) { + if (BMO_elem_flag_test(bm, bme2, BEVEL_FLAG)) + continue; + if (!unflagged_bme) + unflagged_bme = bme2; + BM_ITER_ELEM(f, &iter2, bme2, BM_FACES_OF_EDGE) { + if (BM_face_edge_share_loop(f, bme)) { + found_shared_face = 1; + break; + } + } + if (found_shared_face) + break; + } + e = &bv->edges[i]; + if (found_shared_face) { + e->e = bme2; + e->fprev = f; + bv->edges[i-1].fnext = f; + } else { + e->e = unflagged_bme; + } + } + bme = e->e; + BMO_elem_flag_enable(bm, bme, BEVEL_FLAG); + if (BMO_elem_flag_test(bm, bme, EDGE_SELECTED)) { + e->isbev = 1; + e->seg = bp->seg; + } else { + e->isbev = 0; + e->seg = 0; + } + e->isrev = (bme->v2 == v); + e->offset = e->isbev ? bp->offset : 0.0f; + } + /* find wrap-around shared face */ + BM_ITER_ELEM(f, &iter2, bme, BM_FACES_OF_EDGE) { + if (BM_face_edge_share_loop(f, bv->edges[0].e)) { + if (bv->edges[0].fnext == f) + continue; /* if two shared faces, want the other one now */ + bv->edges[ntot-1].fnext = f; + bv->edges[0].fprev = f; + break; + } + } + + /* remove BEVEL_FLAG now that we are finished with it*/ + for (i = 0; i < ntot; i++) + BMO_elem_flag_disable(bm, bv->edges[i].e, BEVEL_FLAG); + + /* if edge array doesn't go CCW around vertex from average normal side, + * reverse the array, being careful to reverse face pointers too */ + if (ntot > 1) { + ccw_test_sum = 0; + for (i = 0; i < ntot; i++) + ccw_test_sum += bev_ccw_test(bv->edges[i].e, bv->edges[(i + 1) % ntot].e, + bv->edges[i].fnext); + if (ccw_test_sum < 0) { + for (i = 0; i <= (ntot / 2) - 1; i++ ) { + SWAP(EdgeHalf, bv->edges[i], bv->edges[ntot - i - 1]); + SWAP(BMFace*, bv->edges[i].fprev, bv->edges[i].fnext); + SWAP(BMFace*, bv->edges[ntot - i - 1].fprev, bv->edges[ntot - i - 1].fnext); + } + if (ntot % 2 == 1) { + i = ntot / 2; + SWAP(BMFace*, bv->edges[i].fprev, bv->edges[i].fnext); + } + } + } + + for (i = 0; i < ntot; i++) { + e = &bv->edges[i]; + e->next = &bv->edges[(i + 1) % ntot]; + e->prev = &bv->edges[(i + ntot -1) % ntot]; + } + + build_boundary(bv); + build_vmesh(bm, bv); +} + +/* Face f has at least one beveled vertex. Rebuild f */ +static void rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) +{ + BMIter liter; + BMLoop *l, *lprev; + BevVert *bv; + BoundVert *v, *vstart, *vend; + EdgeHalf *e, *eprev; + VMesh *vm; + int i, k; + BMVert *bmv; + BMVert **vv = NULL; + BLI_array_declare(vv); + + BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) { + bv = find_bevvert(bp, l->v); + if (bv) { + lprev = l->prev; + e = find_edge_half(bv, l->e); + eprev = find_edge_half(bv, lprev->e); + BLI_assert(e != NULL && eprev != NULL); + vstart = eprev->leftv; + if (e->isbev) + vend = e->rightv; + else + vend = e->leftv; + v = vstart; + vm = bv->vmesh; + BLI_array_append(vv, v->nv.v); + while (v != vend) { + if (vm->mesh_kind == M_NONE && v->ebev && v->ebev->seg > 1 && v->ebev != e && v->ebev != eprev) { + /* case of 3rd face opposite a beveled edge, with no vmesh */ + i = v->index; + e = v->ebev; + for (k = 1; k < e->seg; k++) { + bmv = mesh_vert(vm, i, 0, k)->v; + BLI_array_append(vv, bmv); + } + } + v = v->prev; + BLI_array_append(vv, v->nv.v); + } + } + else { + BLI_array_append(vv, l->v); + } + } + bev_create_ngon(bm, vv, BLI_array_count(vv), f); + BLI_array_free(vv); +} + +/* All polygons touching v need rebuilding because beveling v has made new vertices */ +static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert *v) +{ + BMFace *f; + BMIter iter; + + /* TODO: don't iterate through all faces, but just local geometry around v */ + BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) { + BMLoop *l = f->l_first; + do { + if (l->v == v) { + rebuild_polygon (bm, bp, f); + BM_face_kill(bm,f); + } + l = l->next; + } while (l != f->l_first); + } +} + + + +/* +* Build the polygons along the selected Edge +*/ +static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) +{ + BevVert *bv1, *bv2; + BMVert *bmv1, *bmv2, *bmv3, *bmv4, *bmv1i, *bmv2i, *bmv3i, *bmv4i; + VMesh *vm1, *vm2; + EdgeHalf *e1, *e2; + BMFace *f1, *f2, *f; + int k, nseg, i1, i2; + + if (BM_edge_face_count(bme) != 2) + return; + + bv1 = find_bevvert(bp, bme->v1); + bv2 = find_bevvert(bp, bme->v2); + + BLI_assert(bv1 && bv2); + + e1 = find_edge_half(bv1, bme); + e2 = find_edge_half(bv2, bme); + + BLI_assert(e1 && e2); + + /* v4 v3 + * \ / + * e->v1 - e->v2 + * / \ + * v1 v2 */ + + nseg = e1->seg; + BLI_assert(nseg > 0 && nseg == e2->seg); + + bmv1 = e1->leftv->nv.v; + bmv4 = e1->rightv->nv.v; + bmv2 = e2->rightv->nv.v; + bmv3 = e2->leftv->nv.v; + + BLI_assert(bmv1 && bmv2 && bmv3 && bmv4); + + f1 = boundvert_rep_face(e1->leftv); + f2 = boundvert_rep_face(e1->rightv); + + if (nseg == 1) { + bev_create_quad_tri(bm, bmv1, bmv2, bmv3, bmv4, f1); + } + else { + i1 = e1->leftv->index; + i2 = e2->leftv->index; + vm1 = bv1->vmesh; + vm2 = bv2->vmesh; + bmv1i = bmv1; + bmv2i = bmv2; + for (k = 1; k <= nseg; k++) { + bmv4i = mesh_vert(vm1, i1, 0, k)->v; + bmv3i = mesh_vert(vm2, i2, 0, nseg - k)->v; + f = (k <= nseg / 2 + (nseg % 2)) ? f1 : f2; + bev_create_quad_tri(bm, bmv1i, bmv2i, bmv3i, bmv4i, f); + bmv1i = bmv4i; + bmv2i = bmv3i; + } + } +} + + +static void free_bevel_params(BevelParams *bp) +{ + BevVert *bv; + VMesh *vm; + BoundVert *v, *vnext; + + for (bv = bp->vertList.first; bv ; bv = bv->next) { + MEM_freeN(bv->edges); + vm = bv->vmesh; + v = vm->boundstart; + if (v) { + do { + vnext = v->next; + MEM_freeN(v); + v = vnext; + } while (v != vm->boundstart); + } + if (vm->mesh) + MEM_freeN(vm->mesh); + MEM_freeN(vm); + } + BLI_freelistN(&bp->vertList); +} + +void bmo_bevel_exec(BMesh *bm, BMOperator *op) +{ + BMOIter siter; + BMVert *v; + BMEdge *e; + BevelParams bp; + + bp.offset = BMO_slot_float_get(op, "offset"); + bp.op = op; + bp.seg = BMO_slot_int_get(op, "segments"); + + if (bp.offset > 0 ) { + bp.vertList.first = bp.vertList.last = NULL; + + /* The analysis of the input vertices and execution additional constructions */ + BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { + bevel_vert_construct(bm, &bp, op, v); + } + /* Build polygons for edges */ + BMO_ITER(e, &siter, bm, op, "geom", BM_EDGE) { + bevel_build_edge_polygons(bm, &bp, e); + } + + BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { + bevel_rebuild_existing_polygons(bm, &bp,v); + } + + BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { + if (find_bevvert(&bp, v)) + BM_vert_kill(bm, v); + } + free_bevel_params(&bp); + } + +} + +#else #define BEVEL_FLAG 1 #define BEVEL_DEL 2 #define FACE_NEW 4 @@ -886,3 +2318,4 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) BMO_slot_buffer_from_enabled_flag(bm, op, "face_spans", BM_FACE, FACE_SPAN); BMO_slot_buffer_from_enabled_flag(bm, op, "face_holes", BM_FACE, FACE_HOLE); } +#endif /* NEW_BEVEL */ diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index f10faddc169..80057ba04be 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4602,11 +4602,15 @@ void MESH_OT_noise(wmOperatorType *ot) RNA_def_float(ot->srna, "factor", 0.1f, -FLT_MAX, FLT_MAX, "Factor", "", 0.0f, 1.0f); } +#define NEW_BEVEL 1 + typedef struct { BMEditMesh *em; BMBackup mesh_backup; +#ifndef NEW_BEVEL float *weights; int li; +#endif int mcenter[2]; float initial_length; float pixel_size; /* use when mouse input is interpreted as spatial distance */ @@ -4619,13 +4623,28 @@ typedef struct { static void edbm_bevel_update_header(wmOperator *op, bContext *C) { +#ifdef NEW_BEVEL + static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), offset: %s, segments: %d"; +#else static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), factor: %s, Use Dist (D): %s: Use Even (E): %s"; +#endif char msg[HEADER_LENGTH]; ScrArea *sa = CTX_wm_area(C); BevelData *opdata = op->customdata; if (sa) { +#ifdef NEW_BEVEL + char offset_str[NUM_STR_REP_LEN]; + if (hasNumInput(&opdata->num_input)) + outputNumInput(&opdata->num_input, offset_str); + else + BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset")); + BLI_snprintf(msg, HEADER_LENGTH, str, + offset_str, + RNA_int_get(op->ptr, "segments") + ); +#else char factor_str[NUM_STR_REP_LEN]; if (hasNumInput(&opdata->num_input)) outputNumInput(&opdata->num_input, factor_str); @@ -4636,11 +4655,13 @@ static void edbm_bevel_update_header(wmOperator *op, bContext *C) RNA_boolean_get(op->ptr, "use_dist") ? "On" : "Off", RNA_boolean_get(op->ptr, "use_even") ? "On" : "Off" ); +#endif ED_area_headerprint(sa, msg); } } +#ifndef NEW_BEVEL static void edbm_bevel_recalc_weights(wmOperator *op) { float df, s, ftot; @@ -4668,15 +4689,20 @@ static void edbm_bevel_recalc_weights(wmOperator *op) mul_vn_fl(opdata->weights, recursion, 1.0f / (float)ftot); } +#endif static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); +#ifdef NEW_BEVEL + BevelData *opdata; +#else BMIter iter; BMEdge *eed; BevelData *opdata; int li; +#endif if (em == NULL) { return 0; @@ -4684,6 +4710,7 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) op->customdata = opdata = MEM_mallocN(sizeof(BevelData), "beveldata_mesh_operator"); +#ifndef NEW_BEVEL BM_data_layer_add(em->bm, &em->bm->edata, CD_PROP_FLT); li = CustomData_number_of_layers(&em->bm->edata, CD_PROP_FLT) - 1; @@ -4693,10 +4720,12 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) *dv = d; } - - opdata->em = em; + opdata->li = li; opdata->weights = NULL; +#endif + + opdata->em = em; opdata->is_modal = is_modal; opdata->shift_factor = -1.0f; @@ -4706,7 +4735,9 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) /* avoid the cost of allocating a bm copy */ if (is_modal) opdata->mesh_backup = EDBM_redo_state_store(em); +#ifndef NEW_BEVEL edbm_bevel_recalc_weights(op); +#endif return 1; } @@ -4716,6 +4747,26 @@ static int edbm_bevel_calc(bContext *C, wmOperator *op) BevelData *opdata = op->customdata; BMEditMesh *em = opdata->em; BMOperator bmop; +#ifdef NEW_BEVEL + float offset = RNA_float_get(op->ptr, "offset"); + int segments = RNA_int_get(op->ptr, "segments"); + + /* revert to original mesh */ + if (opdata->is_modal) { + EDBM_redo_state_restore(opdata->mesh_backup, em, FALSE); + } + + if (!EDBM_op_init(em, &bmop, op, + "bevel geom=%hev offset=%f segments=%i", + BM_ELEM_SELECT, offset, segments)) + { + return 0; + } + + BMO_op_exec(em->bm, &bmop); + if (!EDBM_op_finish(em, &bmop, op, TRUE)) + return 0; +#else int i; float factor = RNA_float_get(op->ptr, "percent") /*, dfac */ /* UNUSED */; @@ -4743,6 +4794,7 @@ static int edbm_bevel_calc(bContext *C, wmOperator *op) if (!EDBM_op_finish(em, &bmop, op, TRUE)) return 0; } +#endif EDBM_mesh_normals_update(opdata->em); @@ -4760,10 +4812,12 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op) if (sa) { ED_area_headerprint(sa, NULL); } +#ifndef NEW_BEVEL BM_data_layer_free_n(opdata->em->bm, &opdata->em->bm->edata, CD_PROP_FLT, opdata->li); if (opdata->weights) MEM_freeN(opdata->weights); +#endif if (opdata->is_modal) { EDBM_redo_state_free(&opdata->mesh_backup, NULL, FALSE); } @@ -4844,7 +4898,11 @@ static int edbm_bevel_invoke(bContext *C, wmOperator *op, wmEvent *event) static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event) { BevelData *opdata = op->customdata; +#ifdef NEW_BEVEL + int use_dist = TRUE; +#else int use_dist = RNA_boolean_get(op->ptr, "use_dist"); +#endif float mdiff[2]; float factor; @@ -4907,7 +4965,11 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) case MOUSEMOVE: if (!hasNumInput(&opdata->num_input)) { const float factor = edbm_bevel_mval_factor(op, event); +#ifdef NEW_BEVEL + RNA_float_set(op->ptr, "offset", factor); +#else RNA_float_set(op->ptr, "percent", factor); +#endif edbm_bevel_calc(C, op); edbm_bevel_update_header(op, C); @@ -4967,6 +5029,10 @@ void MESH_OT_bevel(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO | OPTYPE_GRAB_POINTER | OPTYPE_BLOCKING; +#ifdef NEW_BEVEL + RNA_def_float(ot->srna, "offset", 0.0f, -FLT_MAX, FLT_MAX, "Offset", "", 0.0f, 1.0f); + RNA_def_int(ot->srna, "segments", 1, 1, 50, "Segments", "Segments for curved edge", 1, 8); +#else /* take note, used as a factor _and_ a distance depending on 'use_dist' */ RNA_def_float(ot->srna, "percent", 0.0f, -FLT_MAX, FLT_MAX, "Percentage", "", 0.0f, 1.0f); /* XXX, disabled for 2.63 release, needs to work much better without overlap before we can give to users. */ @@ -4974,6 +5040,7 @@ void MESH_OT_bevel(wmOperatorType *ot) RNA_def_boolean(ot->srna, "use_even", FALSE, "Even", "Calculate evenly spaced bevel"); RNA_def_boolean(ot->srna, "use_dist", FALSE, "Distance", "Interpret the percent in blender units"); +#endif } From 365935bfdd7dea321591ea78c7673dfc23772da0 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Thu, 8 Nov 2012 16:00:18 +0000 Subject: [PATCH 024/118] style cleanup --- source/blender/bmesh/operators/bmo_bevel.c | 278 +++++++++++---------- 1 file changed, 140 insertions(+), 138 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index dbb8bb43c64..ee8d0d7f9cd 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -40,8 +40,8 @@ #define NEW_BEVEL 1 #ifdef NEW_BEVEL -#define BEVEL_FLAG 1 -#define EDGE_SELECTED 2 +#define BEVEL_FLAG 1 +#define EDGE_SELECTED 2 #define BEVEL_EPSILON 1e-6 @@ -55,68 +55,68 @@ struct BoundVert; /* Data for one end of an edge involved in a bevel */ typedef struct EdgeHalf { - struct EdgeHalf *next, *prev; /* in CCW order */ - BMEdge *e; /* original mesh edge */ - int isbev; /* is this edge beveled? */ - int isrev; /* is e->v2 the vertex at this end? */ - int seg; /* how many segments for the bevel */ - float offset; /* offset for this edge */ - BMFace *fprev; /* face between this edge and previous, if any */ - BMFace *fnext; /* face between this edge and next, if any */ - struct BoundVert *leftv; /* left boundary vert (looking along edge to end) */ - struct BoundVert *rightv; /* right boundary vert, if beveled */ + struct EdgeHalf *next, *prev; /* in CCW order */ + BMEdge *e; /* original mesh edge */ + int isbev; /* is this edge beveled? */ + int isrev; /* is e->v2 the vertex at this end? */ + int seg; /* how many segments for the bevel */ + float offset; /* offset for this edge */ + BMFace *fprev; /* face between this edge and previous, if any */ + BMFace *fnext; /* face between this edge and next, if any */ + struct BoundVert *leftv; /* left boundary vert (looking along edge to end) */ + struct BoundVert *rightv; /* right boundary vert, if beveled */ } EdgeHalf; /* An element in a cyclic boundary of a Vertex Mesh (VMesh) */ typedef struct BoundVert { - struct BoundVert *next, *prev; /* in CCW order */ - int index; /* used for vmesh indexing */ + struct BoundVert *next, *prev; /* in CCW order */ + int index; /* used for vmesh indexing */ NewVert nv; - EdgeHalf *efirst; /* first of edges attached here: in CCW order */ + EdgeHalf *efirst; /* first of edges attached here: in CCW order */ EdgeHalf *elast; - EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */ + EdgeHalf *ebev; /* beveled edge whose left side is attached here, if any */ } BoundVert; /* Mesh structure replacing a vertex */ typedef struct VMesh { enum { - M_NONE, /* no polygon mesh needed */ - M_POLY, /* a simple polygon */ - M_ADJ, /* "adjacent edges" mesh pattern */ - M_CROSS, /* "cross edges" mesh pattern */ + M_NONE, /* no polygon mesh needed */ + M_POLY, /* a simple polygon */ + M_ADJ, /* "adjacent edges" mesh pattern */ + M_CROSS, /* "cross edges" mesh pattern */ } mesh_kind; - int count; /* number of vertices in the boundary */ - int seg; /* common # of segments for segmented edges */ - BoundVert *boundstart; /* start of boundary double-linked list */ - NewVert *mesh; /* allocated array - size and structure depends on kind */ + int count; /* number of vertices in the boundary */ + int seg; /* common # of segments for segmented edges */ + BoundVert *boundstart; /* start of boundary double-linked list */ + NewVert *mesh; /* allocated array - size and structure depends on kind */ } VMesh; /* Data for a vertex involved in a bevel */ typedef struct BevVert { struct BevVert *next, *prev; - BMVert *v; /* original mesh vertex */ - int edgecount; /* total number of edges around the vertex */ - int selcount; /* number of selected edges around the vertex */ - EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */ - VMesh *vmesh; /* mesh structure for replacing vertex */ + BMVert *v; /* original mesh vertex */ + int edgecount; /* total number of edges around the vertex */ + int selcount; /* number of selected edges around the vertex */ + EdgeHalf *edges; /* array of size edgecount; CCW order from vertex normal side */ + VMesh *vmesh; /* mesh structure for replacing vertex */ } BevVert; /* * Bevel parameters and state */ typedef struct BevelParams { - ListBase vertList; /* list of BevVert for each vertex involved in bevel */ - float offset; /* blender units to offset each side of a beveled edge */ - int seg; /* number of segments in beveled edge profile */ + ListBase vertList; /* list of BevVert for each vertex involved in bevel */ + float offset; /* blender units to offset each side of a beveled edge */ + int seg; /* number of segments in beveled edge profile */ BMOperator *op; } BevelParams; /* Make a new BoundVert of the given kind, insert it at the end of the circular linked * list with entry point bv->boundstart, and return it. */ -static BoundVert * add_new_bound_vert(VMesh *vm, float co[3]) +static BoundVert *add_new_bound_vert(VMesh *vm, float co[3]) { - BoundVert *ans = (BoundVert*) MEM_callocN(sizeof(BoundVert), "BoundVert"); + BoundVert *ans = (BoundVert *) MEM_callocN(sizeof(BoundVert), "BoundVert"); copy_v3_v3(ans->nv.co, co); if (!vm->boundstart) { ans->index = 0; @@ -140,22 +140,22 @@ static BoundVert * add_new_bound_vert(VMesh *vm, float co[3]) * j = ring index (0 <= j <= ns2) * k = segment index (0 <= k <= ns) * Not all of these are used, and some will share BMVerts */ -static NewVert* mesh_vert(VMesh* vm, int i, int j, int k) +static NewVert *mesh_vert(VMesh *vm, int i, int j, int k) { - int nj = (vm -> seg / 2) + 1; + int nj = (vm->seg / 2) + 1; int nk = vm->seg + 1; return &vm->mesh[i * nk * nj + j * nk + k]; } -static void create_mesh_bmvert(BMesh* bm, VMesh *vm, int i, int j, int k, BMVert *eg) +static void create_mesh_bmvert(BMesh *bm, VMesh *vm, int i, int j, int k, BMVert *eg) { NewVert *nv = mesh_vert(vm, i, j, k); nv->v = BM_vert_create(bm, nv->co, eg); } static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, - int ifrom, int jfrom, int kfrom) + int ifrom, int jfrom, int kfrom) { NewVert *nvto, *nvfrom; @@ -166,7 +166,7 @@ static void copy_mesh_vert(VMesh *vm, int ito, int jto, int kto, } /* find the EdgeHalf in bv's array that has edge bme */ -static EdgeHalf* find_edge_half(BevVert *bv, BMEdge *bme) +static EdgeHalf *find_edge_half(BevVert *bv, BMEdge *bme) { int i; @@ -179,12 +179,12 @@ static EdgeHalf* find_edge_half(BevVert *bv, BMEdge *bme) /* Return the next EdgeHalf after from_e that is beveled. * If from_e is NULL, find the first beveled edge. */ -static EdgeHalf* next_bev(BevVert *bv, EdgeHalf *from_e) +static EdgeHalf *next_bev(BevVert *bv, EdgeHalf *from_e) { EdgeHalf *e; if (from_e == NULL) - from_e = &bv->edges[bv->edgecount -1]; + from_e = &bv->edges[bv->edgecount - 1]; e = from_e; do { if (e->isbev) @@ -195,7 +195,7 @@ static EdgeHalf* next_bev(BevVert *bv, EdgeHalf *from_e) } /* find the BevVert corresponding to BMVert bmv */ -static BevVert* find_bevvert(BevelParams *bp, BMVert *bmv) +static BevVert *find_bevvert(BevelParams *bp, BMVert *bmv) { BevVert *bv; @@ -208,7 +208,7 @@ static BevVert* find_bevvert(BevelParams *bp, BMVert *bmv) /* Return a good respresentative face (for materials, etc.) for faces * created around/near BoundVert v */ -static BMFace* boundvert_rep_face(BoundVert *v) +static BMFace *boundvert_rep_face(BoundVert *v) { BMFace *fans = NULL; BMFace *firstf = NULL; @@ -219,10 +219,10 @@ static BMFace* boundvert_rep_face(BoundVert *v) BLI_assert(v->efirst != NULL && v->elast != NULL); e1 = v->efirst->e; e2 = v->elast->e; - BM_ITER_ELEM(f1, &iter1, e1, BM_FACES_OF_EDGE) { + BM_ITER_ELEM (f1, &iter1, e1, BM_FACES_OF_EDGE) { if (!firstf) firstf = f1; - BM_ITER_ELEM(f2, &iter2, e2, BM_FACES_OF_EDGE) { + BM_ITER_ELEM (f2, &iter2, e2, BM_FACES_OF_EDGE) { if (f1 == f2) { fans = f1; break; @@ -246,11 +246,11 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, int totv, BMFace *f if (totv == 3) { f = BM_face_create_quad_tri(bm, - vert_arr[0], vert_arr[1], vert_arr[2], NULL, facerep, 0); + vert_arr[0], vert_arr[1], vert_arr[2], NULL, facerep, 0); } else if (totv == 4) { f = BM_face_create_quad_tri(bm, - vert_arr[0], vert_arr[1], vert_arr[2], vert_arr[3], facerep, 0); + vert_arr[0], vert_arr[1], vert_arr[2], vert_arr[3], facerep, 0); } else { int i; @@ -268,7 +268,7 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, int totv, BMFace *f if (facerep && f) { int has_mdisps = CustomData_has_layer(&bm->ldata, CD_MDISPS); BM_elem_attrs_copy(bm, bm, facerep, f); - BM_ITER_ELEM(l, &iter, f, BM_LOOPS_OF_FACE) { + BM_ITER_ELEM (l, &iter, f, BM_LOOPS_OF_FACE) { BM_loop_interp_from_face(bm, l, facerep, TRUE, TRUE); if (has_mdisps) BM_loop_interp_multires(bm, l, facerep); @@ -278,7 +278,7 @@ static BMFace *bev_create_ngon(BMesh *bm, BMVert **vert_arr, int totv, BMFace *f } static BMFace *bev_create_quad_tri(BMesh *bm, BMVert *v1, BMVert *v2, BMVert *v3, BMVert *v4, - BMFace *facerep) + BMFace *facerep) { BMVert *varr[4]; @@ -303,7 +303,7 @@ static void offset_meet(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f, int on_right, float meetco[3]) { float dir1[3], dir2[3], norm_v[3], norm_perp1[3], norm_perp2[3], - off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; + off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; /* get direction vectors for two offset lines */ sub_v3_v3v3(dir1, v->co, BM_edge_other_vert(e1->e, v)->co); @@ -362,7 +362,7 @@ static void offset_in_two_planes(EdgeHalf *e1, EdgeHalf *e2, BMVert *v, BMFace *f1, BMFace *f2, float meetco[3]) { float dir1[3], dir2[3], norm_perp1[3], norm_perp2[3], - off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; + off1a[3], off1b[3], off2a[3], off2b[3], isect2[3]; BLI_assert(f1 != NULL && f2 != NULL); @@ -399,9 +399,9 @@ static void offset_in_plane(EdgeHalf *e, float plane_no[3], int left, float r[3] float dir[3], no[3]; BMVert *v; - v = e->isrev? e->e->v1 : e->e->v2; + v = e->isrev ? e->e->v1 : e->e->v2; - sub_v3_v3v3(dir,BM_edge_other_vert(e->e, v)->co, v->co); + sub_v3_v3v3(dir, BM_edge_other_vert(e->e, v)->co, v->co); normalize_v3(dir); if (plane_no) { copy_v3_v3(no, plane_no); @@ -441,7 +441,7 @@ static void project_to_edge(BMEdge *e, float co_a[3], float co_b[3], float projc float otherco[3]; if (!isect_line_line_v3(e->v1->co, e->v2->co, co_a, co_b, - projco, otherco)) { + projco, otherco)) { BLI_assert(!"project meet failure"); copy_v3_v3(projco, e->v1->co); } @@ -464,16 +464,16 @@ static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f) } /* -* Search for crossing the line and line -* a1-a2 lineA -* b1-b2 line B -* r - result, coordinate of crossing point -*/ + * Search for crossing the line and line + * a1-a2 lineA + * b1-b2 line B + * r - result, coordinate of crossing point + */ static int find_intersection_point(float r[3], float a1[3], float a2[3], float b1[3], float b2[3]) { double s, t, z1, z2; double mx, my, nx, ny; - int flag =0; + int flag = 0; mx = a2[0] - a1[0]; my = a2[1] - a1[1]; @@ -481,14 +481,14 @@ static int find_intersection_point(float r[3], float a1[3], float a2[3], float b nx = b2[0] - b1[0]; ny = b2[1] - b1[1]; - s = ((b1[1] - a1[1]) / my + (a1[0] - b1[0])/ mx ) / (nx / mx - ny / my); + s = ((b1[1] - a1[1]) / my + (a1[0] - b1[0]) / mx) / (nx / mx - ny / my); t = (b1[0] - a1[0] + s * nx) / mx; - z1 = a1[2] + t * (a2[2] -a1[2]); - z2 = b1[2] + s * (b2[2] -b1[2]); + z1 = a1[2] + t * (a2[2] - a1[2]); + z2 = b1[2] + s * (b2[2] - b1[2]); - if ( fabs(z1-z2) < BEVEL_EPSILON ){ + if (fabs(z1 - z2) < BEVEL_EPSILON) { flag = 1; r[0] = a1[0] + t * mx; r[1] = a1[1] + t * my; @@ -501,14 +501,14 @@ static int find_intersection_point(float r[3], float a1[3], float a2[3], float b } /* -* Search for crossing the line and plane -* p1, p2, p3 points which is given by the plane -* a - line vector -* m - point through which the line -* r - result; -*/ + * Search for crossing the line and plane + * p1, p2, p3 points which is given by the plane + * a - line vector + * m - point through which the line + * r - result; + */ static void find_intersection_point_plane(float r[3], float p1[3], float p2[3], float p3[3], - float a[3], float m[3]) + float a[3], float m[3]) { float P[3], N[3], A[3], M[3]; float vv1[3], vv2[3]; @@ -527,7 +527,7 @@ static void find_intersection_point_plane(float r[3], float p1[3], float p2[3], copy_v3_v3(M, m); - if (fabs(N[0] * (A[0]-P[0]) + N[1] * (A[1]-P[1]) + N[2] * (A[2]-P[2])) < BEVEL_EPSILON) { + if (fabs(N[0] * (A[0] - P[0]) + N[1] * (A[1] - P[1]) + N[2] * (A[2] - P[2])) < BEVEL_EPSILON) { /* point located on plane */ float tmp[3], line[3]; add_v3_v3v3(line, a, m); @@ -544,14 +544,14 @@ static void find_intersection_point_plane(float r[3], float p1[3], float p2[3], D = N[0] * M[0] + N[1] * M[1] + N[2] * M[2]; E = (A[0] * N[0] + A[1] * N[1] + A[2] * N[2]); - if (fabs(E)< null) + if (fabs(E) < null) t = 0; else - t = (C-D)/E; + t = (C - D) / E; - r[0] = m[0] + t * a [0]; - r[1] = m[1] + t * a [1]; - r[2] = m[2] + t * a [2]; + r[0] = m[0] + t * a[0]; + r[1] = m[1] + t * a[1]; + r[2] = m[2] + t * a[2]; } } @@ -567,7 +567,7 @@ static void find_intersection_point_plane(float r[3], float p1[3], float p2[3], * of that segment in r. */ static void get_point_on_round_profile(float r[3], float offset, int i, int count, - float va[3], float v[3], float vb[3]) + float va[3], float v[3], float vb[3]) { float vva[3], vvb[3], angle, center[3], rv[3], axis[3], co[3]; @@ -580,14 +580,14 @@ static void get_point_on_round_profile(float r[3], float offset, int i, int coun add_v3_v3v3(center, vva, vvb); normalize_v3(center); mul_v3_fl(center, offset * (1.0 / cos(0.5 * angle))); - add_v3_v3(center, v); /* coordinates of the center of the inscribed circle */ + add_v3_v3(center, v); /* coordinates of the center of the inscribed circle */ - sub_v3_v3v3(rv, va, center); /* radius vector */ + sub_v3_v3v3(rv, va, center); /* radius vector */ sub_v3_v3v3(co, v, center); - cross_v3_v3v3(axis, rv, co); /* calculate axis */ + cross_v3_v3v3(axis, rv, co); /* calculate axis */ sub_v3_v3v3(vva, va, center); sub_v3_v3v3(vvb, vb, center); @@ -610,7 +610,7 @@ static void get_point_on_round_profile(float r[3], float offset, int i, int coun * If va, vmid, and vb are all on the same plane, just interpolate between va and vb. */ static void get_point_on_round_edge(EdgeHalf *e, int i, - float va[3], float vmid[3], float vb[3], float profileco[3]) + float va[3], float vmid[3], float vb[3], float profileco[3]) { float vva[3], vvb[3], point[3], dir[3], vaadj[3], vbadj[3]; int n = e->seg; @@ -622,7 +622,7 @@ static void get_point_on_round_edge(EdgeHalf *e, int i, else sub_v3_v3v3(dir, e->e->v2->co, e->e->v1->co); normalize_v3(dir); - if (fabs(angle_v3v3(vva, vvb)- M_PI) > BEVEL_EPSILON) { + if (fabs(angle_v3v3(vva, vvb) - M_PI) > BEVEL_EPSILON) { copy_v3_v3(vaadj, va); madd_v3_v3fl(vaadj, dir, -len_v3(vva) * cosf(angle_v3v3(vva, dir))); copy_v3_v3(vbadj, vb); @@ -664,12 +664,12 @@ static void build_boundary(BevVert *bv) if (bv->edgecount == 2 && bv->selcount == 1) { /* special case: beveled edge meets non-beveled one at valence 2 vert */ - no = e->fprev ? e->fprev->no : (e->fnext? e->fnext->no : NULL); + no = e->fprev ? e->fprev->no : (e->fnext ? e->fnext->no : NULL); offset_in_plane(e, no, TRUE, co); v = add_new_bound_vert(vm, co); v->efirst = v->elast = v->ebev = e; e->leftv = v; - no = e->fnext ? e->fnext->no : (e->fprev? e->fprev->no : NULL); + no = e->fnext ? e->fnext->no : (e->fprev ? e->fprev->no : NULL); offset_in_plane(e, no, FALSE, co); v = add_new_bound_vert(vm, co); v->efirst = v->elast = e; @@ -703,7 +703,7 @@ static void build_boundary(BevVert *bv) /* find meet point between e->prev->prev and e and attach e->prev there */ /* TODO: fix case when one or both faces in following are NULL */ offset_in_two_planes(e->prev->prev, e, bv->v, - e->prev->prev->fnext, e->fprev, co); + e->prev->prev->fnext, e->fprev, co); v = add_new_bound_vert(vm, co); v->efirst = e->prev->prev; v->elast = v->ebev = e; @@ -775,7 +775,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) BoundVert *v, *vprev, *vnext; NewVert *nv, *nvprev, *nvnext; BMVert *bmv, *bmv1, *bmv2, *bmv3, *bmv4; - BMFace *f; + BMFace *f; float co[3], coa[3], cob[3], midco[3]; n = vm->count; @@ -888,7 +888,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) create_mesh_bmvert(bm, vm, i, k, ns2, bv->v); copy_mesh_vert(vm, vprev->index, ns2, ns - k, i, k, ns2); copy_mesh_vert(vm, vnext->index, ns2, k, i, k, ns2); - + } else if (vprev->ebev) { mid_v3_v3v3(co, nvprev->co, nv->co); @@ -922,7 +922,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) } v = v->next; } while (v != vm->boundstart); - mul_v3_fl(midco, 1.0f/nn); + mul_v3_fl(midco, 1.0f / nn); bmv = BM_vert_create(bm, midco, NULL); v = vm->boundstart; do { @@ -1003,21 +1003,21 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) if (!v->prev->ebev) { for (k = 0; k < ns2; k++) { bmv1 = mesh_vert(vm, i, ns2, k)->v; - if (!(j > 0 && bmv1 == vv[j-1])) { + if (!(j > 0 && bmv1 == vv[j - 1])) { BLI_array_append(vv, bmv1); j++; } } } bmv1 = mesh_vert(vm, i, ns2, ns2)->v; - if (!(j > 0 && bmv1 == vv[j-1])) { + if (!(j > 0 && bmv1 == vv[j - 1])) { BLI_array_append(vv, bmv1); j++; } if (!v->next->ebev) { - for (k = ns -ns2; k < ns; k++) { + for (k = ns - ns2; k < ns; k++) { bmv1 = mesh_vert(vm, i, ns2, k)->v; - if (!(j > 0 && bmv1 == vv[j-1])) { + if (!(j > 0 && bmv1 == vv[j - 1])) { BLI_array_append(vv, bmv1); j++; } @@ -1030,7 +1030,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) } v = v->next; } while (v != vm->boundstart); - if (vv[0] == vv[j-1]) + if (vv[0] == vv[j - 1]) j--; bev_create_ngon(bm, vv, j, f); @@ -1078,11 +1078,11 @@ static void build_vmesh(BMesh *bm, BevVert *bv) ns = vm->seg; ns2 = ns / 2; - vm->mesh = (NewVert*)MEM_callocN(n * (ns2 + 1) * (ns + 1) * sizeof(NewVert), "NewVert"); + vm->mesh = (NewVert *)MEM_callocN(n * (ns2 + 1) * (ns + 1) * sizeof(NewVert), "NewVert"); /* special case: two beveled ends welded together */ weld = (bv->selcount == 2) && (vm->count == 2); - weld1 = weld2 = NULL; /* will hold two BoundVerts involved in weld */ + weld1 = weld2 = NULL; /* will hold two BoundVerts involved in weld */ /* make (i, 0, 0) mesh verts for all i */ v = vm->boundstart; @@ -1122,7 +1122,7 @@ static void build_vmesh(BMesh *bm, BevVert *bv) if (weld) { for (k = 1; k < ns; k++) { mid_v3_v3v3(co, mesh_vert(vm, weld1->index, 0, k)->co, - mesh_vert(vm, weld2->index, 0, ns - k)->co); + mesh_vert(vm, weld2->index, 0, ns - k)->co); copy_v3_v3(mesh_vert(vm, weld1->index, 0, k)->co, co); create_mesh_bmvert(bm, vm, weld1->index, 0, k, bv->v); } @@ -1155,10 +1155,10 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMOperator *op, BMV /* Gather input selected edges. * Only bevel selected edges that have exactly two incident faces. */ BMO_ITER (bme, &siter, bm, op, "geom", BM_EDGE) { - if ((bme->v1 == v)|| (BM_edge_other_vert(bme, bme->v1) == v)) + if ((bme->v1 == v) || (BM_edge_other_vert(bme, bme->v1) == v)) { if (BM_edge_face_count(bme) == 2) { - BMO_elem_flag_enable (bm, bme, EDGE_SELECTED); + BMO_elem_flag_enable(bm, bme, EDGE_SELECTED); nsel++; } } @@ -1168,11 +1168,11 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMOperator *op, BMV return; ntot = BM_vert_edge_count(v); - bv = (BevVert*)MEM_callocN(sizeof(BevVert), "BevVert"); + bv = (BevVert *)MEM_callocN(sizeof(BevVert), "BevVert"); bv->v = v; bv->edgecount = ntot; bv->selcount = nsel; - bv->edges = (EdgeHalf*)MEM_callocN(ntot * sizeof(EdgeHalf), "EdgeHalf"); + bv->edges = (EdgeHalf *)MEM_callocN(ntot * sizeof(EdgeHalf), "EdgeHalf"); bv->vmesh = (VMesh *)MEM_callocN(sizeof(VMesh), "VMesh"); bv->vmesh->seg = bp->seg; BLI_addtail(&bp->vertList, bv); @@ -1189,12 +1189,12 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMOperator *op, BMV /* find an unflagged edge bme2 that shares a face f with previous bme */ found_shared_face = 0; unflagged_bme = NULL; - BM_ITER_ELEM(bme2, &iter, v, BM_EDGES_OF_VERT) { + BM_ITER_ELEM (bme2, &iter, v, BM_EDGES_OF_VERT) { if (BMO_elem_flag_test(bm, bme2, BEVEL_FLAG)) continue; if (!unflagged_bme) unflagged_bme = bme2; - BM_ITER_ELEM(f, &iter2, bme2, BM_FACES_OF_EDGE) { + BM_ITER_ELEM (f, &iter2, bme2, BM_FACES_OF_EDGE) { if (BM_face_edge_share_loop(f, bme)) { found_shared_face = 1; break; @@ -1207,8 +1207,9 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMOperator *op, BMV if (found_shared_face) { e->e = bme2; e->fprev = f; - bv->edges[i-1].fnext = f; - } else { + bv->edges[i - 1].fnext = f; + } + else { e->e = unflagged_bme; } } @@ -1217,7 +1218,8 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMOperator *op, BMV if (BMO_elem_flag_test(bm, bme, EDGE_SELECTED)) { e->isbev = 1; e->seg = bp->seg; - } else { + } + else { e->isbev = 0; e->seg = 0; } @@ -1225,11 +1227,11 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMOperator *op, BMV e->offset = e->isbev ? bp->offset : 0.0f; } /* find wrap-around shared face */ - BM_ITER_ELEM(f, &iter2, bme, BM_FACES_OF_EDGE) { + BM_ITER_ELEM (f, &iter2, bme, BM_FACES_OF_EDGE) { if (BM_face_edge_share_loop(f, bv->edges[0].e)) { if (bv->edges[0].fnext == f) - continue; /* if two shared faces, want the other one now */ - bv->edges[ntot-1].fnext = f; + continue; /* if two shared faces, want the other one now */ + bv->edges[ntot - 1].fnext = f; bv->edges[0].fprev = f; break; } @@ -1245,16 +1247,16 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMOperator *op, BMV ccw_test_sum = 0; for (i = 0; i < ntot; i++) ccw_test_sum += bev_ccw_test(bv->edges[i].e, bv->edges[(i + 1) % ntot].e, - bv->edges[i].fnext); + bv->edges[i].fnext); if (ccw_test_sum < 0) { - for (i = 0; i <= (ntot / 2) - 1; i++ ) { + for (i = 0; i <= (ntot / 2) - 1; i++) { SWAP(EdgeHalf, bv->edges[i], bv->edges[ntot - i - 1]); - SWAP(BMFace*, bv->edges[i].fprev, bv->edges[i].fnext); - SWAP(BMFace*, bv->edges[ntot - i - 1].fprev, bv->edges[ntot - i - 1].fnext); + SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext); + SWAP(BMFace *, bv->edges[ntot - i - 1].fprev, bv->edges[ntot - i - 1].fnext); } if (ntot % 2 == 1) { i = ntot / 2; - SWAP(BMFace*, bv->edges[i].fprev, bv->edges[i].fnext); + SWAP(BMFace *, bv->edges[i].fprev, bv->edges[i].fnext); } } } @@ -1262,7 +1264,7 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMOperator *op, BMV for (i = 0; i < ntot; i++) { e = &bv->edges[i]; e->next = &bv->edges[(i + 1) % ntot]; - e->prev = &bv->edges[(i + ntot -1) % ntot]; + e->prev = &bv->edges[(i + ntot - 1) % ntot]; } build_boundary(bv); @@ -1283,7 +1285,7 @@ static void rebuild_polygon(BMesh *bm, BevelParams *bp, BMFace *f) BMVert **vv = NULL; BLI_array_declare(vv); - BM_ITER_ELEM(l, &liter, f, BM_LOOPS_OF_FACE) { + BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) { bv = find_bevvert(bp, l->v); if (bv) { lprev = l->prev; @@ -1331,8 +1333,8 @@ static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert * BMLoop *l = f->l_first; do { if (l->v == v) { - rebuild_polygon (bm, bp, f); - BM_face_kill(bm,f); + rebuild_polygon(bm, bp, f); + BM_face_kill(bm, f); } l = l->next; } while (l != f->l_first); @@ -1342,8 +1344,8 @@ static void bevel_rebuild_existing_polygons(BMesh *bm, BevelParams *bp, BMVert * /* -* Build the polygons along the selected Edge -*/ + * Build the polygons along the selected Edge + */ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) { BevVert *bv1, *bv2; @@ -1367,10 +1369,10 @@ static void bevel_build_edge_polygons(BMesh *bm, BevelParams *bp, BMEdge *bme) BLI_assert(e1 && e2); /* v4 v3 - * \ / - * e->v1 - e->v2 - * / \ - * v1 v2 */ + * \ / + * e->v1 - e->v2 + * / \ + * v1 v2 */ nseg = e1->seg; BLI_assert(nseg > 0 && nseg == e2->seg); @@ -1413,7 +1415,7 @@ static void free_bevel_params(BevelParams *bp) VMesh *vm; BoundVert *v, *vnext; - for (bv = bp->vertList.first; bv ; bv = bv->next) { + for (bv = bp->vertList.first; bv; bv = bv->next) { MEM_freeN(bv->edges); vm = bv->vmesh; v = vm->boundstart; @@ -1442,7 +1444,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) bp.op = op; bp.seg = BMO_slot_int_get(op, "segments"); - if (bp.offset > 0 ) { + if (bp.offset > 0) { bp.vertList.first = bp.vertList.last = NULL; /* The analysis of the input vertices and execution additional constructions */ @@ -1450,12 +1452,12 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) bevel_vert_construct(bm, &bp, op, v); } /* Build polygons for edges */ - BMO_ITER(e, &siter, bm, op, "geom", BM_EDGE) { + BMO_ITER (e, &siter, bm, op, "geom", BM_EDGE) { bevel_build_edge_polygons(bm, &bp, e); } BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { - bevel_rebuild_existing_polygons(bm, &bp,v); + bevel_rebuild_existing_polygons(bm, &bp, v); } BMO_ITER (v, &siter, bm, op, "geom", BM_VERT) { @@ -1468,14 +1470,14 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) } #else -#define BEVEL_FLAG 1 -#define BEVEL_DEL 2 -#define FACE_NEW 4 -#define EDGE_OLD 8 -#define FACE_OLD 16 -#define VERT_OLD 32 -#define FACE_SPAN 64 -#define FACE_HOLE 128 +#define BEVEL_FLAG 1 +#define BEVEL_DEL 2 +#define FACE_NEW 4 +#define EDGE_OLD 8 +#define FACE_OLD 16 +#define VERT_OLD 32 +#define FACE_SPAN 64 +#define FACE_HOLE 128 typedef struct LoopTag { BMVert *newv; @@ -1488,7 +1490,7 @@ typedef struct EdgeTag { static void calc_corner_co(BMLoop *l, const float fac, float r_co[3], const short do_dist, const short do_even) { - float no[3], l_vec_prev[3], l_vec_next[3], l_co_prev[3], l_co[3], l_co_next[3], co_ofs[3]; + float no[3], l_vec_prev[3], l_vec_next[3], l_co_prev[3], l_co[3], l_co_next[3], co_ofs[3]; int is_concave; /* first get the prev/next verts */ @@ -1731,7 +1733,7 @@ void bmo_bevel_exec(BMesh *bm, BMOperator *op) /* find all faces surrounding e->v1 and, e->v2 */ for (i = 0; i < 2; i++) { - BM_ITER_ELEM (l, &liter, i ? e->v2:e->v1, BM_LOOPS_OF_VERT) { + BM_ITER_ELEM (l, &liter, i ? e->v2 : e->v1, BM_LOOPS_OF_VERT) { BMLoop *l2; BMIter liter2; From 4063db3f612d6cf0dc3fd63878c18d61bc51f066 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 8 Nov 2012 16:35:10 +0000 Subject: [PATCH 025/118] Render: make default lamp size smaller (10cm instead of 1m in typical units). --- source/blender/blenkernel/intern/lamp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 4782d09a7c8..576afe123c0 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -73,7 +73,7 @@ Lamp *BKE_lamp_add(const char *name) la->soft = 3.0f; la->compressthresh = 0.05f; la->ray_samp = la->ray_sampy = la->ray_sampz = 1; - la->area_size = la->area_sizey = la->area_sizez = 1.0f; + la->area_size = la->area_sizey = la->area_sizez = 0.1f; la->buffers = 1; la->buftype = LA_SHADBUF_HALFWAY; la->ray_samp_method = LA_SAMP_HALTON; From e73408f2474f7e6d9f1ff880f7f07c678f28e0ce Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 8 Nov 2012 16:35:20 +0000 Subject: [PATCH 026/118] Cycles: add strength input for normal map node. --- .../cycles/kernel/shaders/node_normal_map.osl | 4 ++++ intern/cycles/kernel/svm/svm_tex_coord.h | 23 +++++++++++++------ intern/cycles/render/nodes.cpp | 5 ++++ .../nodes/shader/nodes/node_shader_bump.c | 2 +- .../shader/nodes/node_shader_normal_map.c | 1 + 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/intern/cycles/kernel/shaders/node_normal_map.osl b/intern/cycles/kernel/shaders/node_normal_map.osl index e238313509e..d101ee870b7 100644 --- a/intern/cycles/kernel/shaders/node_normal_map.osl +++ b/intern/cycles/kernel/shaders/node_normal_map.osl @@ -20,6 +20,7 @@ shader node_normal_map( normal NormalIn = N, + float Strength = 1.0, color Color = color(0.5, 0.5, 1.0), string space = "Tangent", string attr_name = "geom:tangent", @@ -44,5 +45,8 @@ shader node_normal_map( Normal = normalize(transform("object", "world", vector(mcolor))); else if (space == "World") Normal = normalize(vector(mcolor)); + + if (Strength != 1.0) + Normal = normalize(NormalIn + (Normal - NormalIn)*max(Strength, 0.0)); } diff --git a/intern/cycles/kernel/svm/svm_tex_coord.h b/intern/cycles/kernel/svm/svm_tex_coord.h index a9449c0ded9..8ca7dff3970 100644 --- a/intern/cycles/kernel/svm/svm_tex_coord.h +++ b/intern/cycles/kernel/svm/svm_tex_coord.h @@ -227,12 +227,14 @@ __device void svm_node_tex_coord_bump_dy(KernelGlobals *kg, ShaderData *sd, floa __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) { - uint color_offset, normal_offset, space; - decode_node_uchar4(node.y, &color_offset, &normal_offset, &space, NULL); + uint color_offset, strength_offset, normal_offset, space; + decode_node_uchar4(node.y, &color_offset, &strength_offset, &normal_offset, &space); float3 color = stack_load_float3(stack, color_offset); color = 2.0f*make_float3(color.x - 0.5f, color.y - 0.5f, color.z - 0.5f); + float3 N; + if(space == NODE_NORMAL_MAP_TANGENT) { /* tangent space */ if(sd->object == ~0) { @@ -257,19 +259,26 @@ __device void svm_node_normal_map(KernelGlobals *kg, ShaderData *sd, float *stac tangent = cross(sd->N, normalize(cross(tangent, sd->N)));; float3 B = sign * cross(sd->N, tangent); - float3 N = color.x * tangent + color.y * B + color.z * sd->N; - - stack_store_float3(stack, normal_offset, normalize(N)); + N = normalize(color.x * tangent + color.y * B + color.z * sd->N); } else { /* object, world space */ - float3 N = color; + N = color; if(space == NODE_NORMAL_MAP_OBJECT) object_normal_transform(kg, sd, &N); - stack_store_float3(stack, normal_offset, normalize(N)); + N = normalize(N); } + + float strength = stack_load_float(stack, strength_offset); + + if(strength != 1.0f) { + strength = max(strength, 0.0f); + N = normalize(sd->N + (N - sd->N)*strength); + } + + stack_store_float3(stack, normal_offset, normalize(N)); } __device void svm_node_tangent(KernelGlobals *kg, ShaderData *sd, float *stack, uint4 node) diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 4f50de11edf..82afab4dc1a 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -3032,7 +3032,9 @@ NormalMapNode::NormalMapNode() attribute = ustring(""); add_input("NormalIn", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL, true); + add_input("Strength", SHADER_SOCKET_FLOAT, 1.0f); add_input("Color", SHADER_SOCKET_COLOR); + add_output("Normal", SHADER_SOCKET_NORMAL); } @@ -3055,6 +3057,7 @@ void NormalMapNode::attributes(AttributeRequestSet *attributes) void NormalMapNode::compile(SVMCompiler& compiler) { ShaderInput *color_in = input("Color"); + ShaderInput *strength_in = input("Strength"); ShaderOutput *normal_out = output("Normal"); int attr = 0, attr_sign = 0; @@ -3070,11 +3073,13 @@ void NormalMapNode::compile(SVMCompiler& compiler) } compiler.stack_assign(color_in); + compiler.stack_assign(strength_in); compiler.stack_assign(normal_out); compiler.add_node(NODE_NORMAL_MAP, compiler.encode_uchar4( color_in->stack_offset, + strength_in->stack_offset, normal_out->stack_offset, space_enum[space]), attr, attr_sign); diff --git a/source/blender/nodes/shader/nodes/node_shader_bump.c b/source/blender/nodes/shader/nodes/node_shader_bump.c index 24ed825c36e..b0605f9b248 100644 --- a/source/blender/nodes/shader/nodes/node_shader_bump.c +++ b/source/blender/nodes/shader/nodes/node_shader_bump.c @@ -36,7 +36,7 @@ /* **************** BUMP ******************** */ static bNodeSocketTemplate sh_node_bump_in[] = { - { SOCK_FLOAT, 1, "Strength", 0.1f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f}, + { SOCK_FLOAT, 1, "Strength", 0.1f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f}, { SOCK_FLOAT, 1, "Height", 1.0f, 1.0f, 1.0f, 1.0f, -1000.0f, 1000.0f, PROP_NONE, SOCK_HIDE_VALUE}, { -1, 0, "" } }; diff --git a/source/blender/nodes/shader/nodes/node_shader_normal_map.c b/source/blender/nodes/shader/nodes/node_shader_normal_map.c index 39fd8a5decc..ee83699abdb 100644 --- a/source/blender/nodes/shader/nodes/node_shader_normal_map.c +++ b/source/blender/nodes/shader/nodes/node_shader_normal_map.c @@ -30,6 +30,7 @@ /* **************** OUTPUT ******************** */ static bNodeSocketTemplate sh_node_normal_map_in[] = { + { SOCK_FLOAT, 1, N_("Strength"), 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 10.0f}, { SOCK_RGBA, 0, N_("Color"), 0.5f, 0.5f, 1.0f, 1.0f, 0.0f, 1.0f}, { -1, 0, "" } }; From 863291bc8e44eaed79946706b417944cdf9dfa4f Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 8 Nov 2012 16:35:28 +0000 Subject: [PATCH 027/118] Fix #33113: cycles not rendering motion blur correct with dying particles. There were a bunch of other issues with dupli motion blur and syncing, the problem being that there was no proper way to detect corresponding duplis between frames or updates. As a solution, a persistent_id was added to the DupliObject. It's an extension of the previous index value, with one index for each dupli level. This can be used to reliably find matching dupli objects between frames. Works with nested duplis, multiple particle systems, etc. --- intern/cycles/blender/blender_object.cpp | 75 ++++--- intern/cycles/blender/blender_particles.cpp | 206 ++++-------------- intern/cycles/blender/blender_sync.h | 11 +- intern/cycles/blender/blender_util.h | 44 +++- intern/cycles/render/particles.cpp | 3 +- source/blender/blenkernel/intern/anim.c | 106 +++++---- source/blender/editors/object/object_add.c | 4 +- source/blender/makesdna/DNA_object_types.h | 17 +- source/blender/makesrna/intern/rna_object.c | 21 +- .../render/intern/source/convertblender.c | 6 +- 10 files changed, 226 insertions(+), 267 deletions(-) diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 1b920249733..a18cb79c102 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -86,11 +86,11 @@ static uint object_ray_visibility(BL::Object b_ob) /* Light */ -void BlenderSync::sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm) +void BlenderSync::sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm) { /* test if we need to sync */ Light *light; - ObjectKey key(b_parent, b_index, b_ob); + ObjectKey key(b_parent, persistent_id, b_ob); if(!light_map.sync(&light, b_ob, b_parent, key)) return; @@ -196,23 +196,24 @@ void BlenderSync::sync_background_light() /* Object */ -void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion, int particle_id) +Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_ob, Transform& tfm, uint layer_flag, int motion) { BL::Object b_ob = (b_dupli_ob ? b_dupli_ob.object() : b_parent); /* light is handled separately */ if(object_is_light(b_ob)) { if(!motion) - sync_light(b_parent, b_index, b_ob, tfm); - return; + sync_light(b_parent, persistent_id, b_ob, tfm); + + return NULL; } /* only interested in object that we can create meshes from */ if(!object_is_mesh(b_ob)) - return; + return NULL; /* key to lookup object */ - ObjectKey key(b_parent, b_index, b_ob); + ObjectKey key(b_parent, persistent_id, b_ob); Object *object; /* motion vector case */ @@ -234,7 +235,7 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject sync_mesh_motion(b_ob, object->mesh, motion); } - return; + return object; } /* test if we need to sync */ @@ -248,13 +249,14 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject /* mesh sync */ object->mesh = sync_mesh(b_ob, object_updated); + /* sspecial case not tracked by object update flags */ if(use_holdout != object->use_holdout) { object->use_holdout = use_holdout; scene->object_manager->tag_update(scene); } - /* object sync */ - /* transform comparison should not be needed, but duplis don't work perfect + /* object sync + * transform comparison should not be needed, but duplis don't work perfect * in the depsgraph and may not signal changes, so this is a workaround */ if(object_updated || (object->mesh && object->mesh->need_update) || tfm != object->tfm) { object->name = b_ob.name().c_str(); @@ -264,7 +266,10 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject object->motion.post = tfm; object->use_motion = false; - object->random_id = hash_int_2d(hash_string(object->name.c_str()), b_index); + object->random_id = hash_string(object->name.c_str()); + if(persistent_id) + for(int i = 0; i < OBJECT_PERSISTENT_ID_SIZE; i++) + object->random_id = hash_int_2d(object->random_id, persistent_id[i]); /* visibility flags for both parent */ object->visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL; @@ -289,10 +294,10 @@ void BlenderSync::sync_object(BL::Object b_parent, int b_index, BL::DupliObject object->dupli_uv = make_float2(0.0f, 0.0f); } - object->particle_id = particle_id; - object->tag_update(scene); } + + return object; } /* Object Loop */ @@ -314,7 +319,9 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) /* object loop */ BL::Scene::objects_iterator b_ob; BL::Scene b_sce = b_scene; - int particle_offset = 1; /* first particle is dummy for regular, non-instanced objects */ + + /* global particle index counter */ + int particle_id = 1; bool cancel = false; @@ -327,16 +334,14 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) if(!hide) { progress.set_sync_status("Synchronizing object", (*b_ob).name()); - int num_particles = object_count_particles(*b_ob); - if(b_ob->is_duplicator()) { - hide = true; /* duplicators hidden by default */ + /* duplicators hidden by default */ + hide = true; /* dupli objects */ b_ob->dupli_list_create(b_scene, 2); BL::Object::dupli_list_iterator b_dup; - int b_index = 0; for(b_ob->dupli_list.begin(b_dup); b_dup != b_ob->dupli_list.end(); ++b_dup) { Transform tfm = get_transform(b_dup->matrix()); @@ -345,7 +350,8 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) bool emitter_hide = false; if(b_dup_ob.is_duplicator()) { - emitter_hide = true; /* duplicators hidden by default */ + /* duplicators hidden by default */ + emitter_hide = true; /* check if we should render or hide particle emitter */ BL::Object::particle_systems_iterator b_psys; @@ -355,21 +361,34 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) } if(!(b_dup->hide() || dup_hide || emitter_hide)) { - sync_object(*b_ob, b_index, *b_dup, tfm, ob_layer, motion, b_dup->particle_index() + particle_offset); + /* the persistent_id allows us to match dupli objects + * between frames and updates */ + BL::Array persistent_id = b_dup->persistent_id(); + + /* sync object and mesh or light data */ + Object *object = sync_object(*b_ob, persistent_id.data, *b_dup, tfm, ob_layer, motion); + + /* sync possible particle data, note particle_id + * starts counting at 1, first is dummy particle */ + if(!motion && object && sync_dupli_particle(*b_ob, *b_dup, object)) { + if(particle_id != object->particle_id) { + object->particle_id = particle_id; + scene->object_manager->tag_update(scene); + } + + particle_id++; + } + } - - ++b_index; } b_ob->dupli_list_clear(); } - /* sync particles and check if we should render or hide particle emitter */ + /* check if we should render or hide particle emitter */ BL::Object::particle_systems_iterator b_psys; - for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) { - if(!motion) - sync_particles(*b_ob, *b_psys); + for(b_ob->particle_systems.begin(b_psys); b_psys != b_ob->particle_systems.end(); ++b_psys) { if(b_psys->settings().use_render_emitter()) hide = false; } @@ -377,10 +396,8 @@ void BlenderSync::sync_objects(BL::SpaceView3D b_v3d, int motion) if(!hide) { /* object itself */ Transform tfm = get_transform(b_ob->matrix_world()); - sync_object(*b_ob, 0, PointerRNA_NULL, tfm, ob_layer, motion, 0); + sync_object(*b_ob, NULL, PointerRNA_NULL, tfm, ob_layer, motion); } - - particle_offset += num_particles; } cancel = progress.get_cancel(); diff --git a/intern/cycles/blender/blender_particles.cpp b/intern/cycles/blender/blender_particles.cpp index c4c6d2f79a3..769cd9f532d 100644 --- a/intern/cycles/blender/blender_particles.cpp +++ b/intern/cycles/blender/blender_particles.cpp @@ -17,6 +17,7 @@ */ #include "mesh.h" +#include "object.h" #include "particles.h" #include "blender_sync.h" @@ -28,170 +29,57 @@ CCL_NAMESPACE_BEGIN /* Utilities */ - -/* Particles Sync */ - -bool BlenderSync::psys_need_update(BL::ParticleSystem b_psys) +bool BlenderSync::sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object) { - /* Particle data is only needed for - * a) Billboard render mode if object's own material uses particle info - * b) object/group render mode if any dupli object's material uses particle info - * - * Note: Meshes have to be synced at this point! - */ - bool need_update = false; - - switch (b_psys.settings().render_type()) { - /* XXX not implemented yet! - * billboards/strands would become part of the mesh data (?), - * so the mesh attributes would store whether particle info is required. - */ - #if 0 - case BL::ParticleSettings::render_type_BILLBOARD: - case BL::ParticleSettings::render_type_PATH: { /* for strand rendering */ - BL::ID key = (BKE_object_is_modified(b_ob))? b_ob: b_ob.data(); - Mesh *mesh = mesh_map.find(key); - if(mesh) { - need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; - } - break; - } - #endif - - case BL::ParticleSettings::render_type_OBJECT: { - BL::Object b_dupli_ob = b_psys.settings().dupli_object(); - if(b_dupli_ob) { - BL::ID key = (BKE_object_is_modified(b_dupli_ob))? b_dupli_ob: b_dupli_ob.data(); - Mesh *mesh = mesh_map.find(key); - if(mesh) { - need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; - } - } - break; - } - - case BL::ParticleSettings::render_type_GROUP: { - BL::Group b_dupli_group = b_psys.settings().dupli_group(); - if(b_dupli_group) { - BL::Group::objects_iterator b_gob; - for (b_dupli_group.objects.begin(b_gob); b_gob != b_dupli_group.objects.end(); ++b_gob) { - BL::ID key = (BKE_object_is_modified(*b_gob))? *b_gob: b_gob->data(); - Mesh *mesh = mesh_map.find(key); - if(mesh) { - need_update |= mesh->need_attribute(scene, ATTR_STD_PARTICLE) && mesh->need_update; - } - } - } - break; - } - - default: - /* avoid compiler warning */ - break; + /* test if this dupli was generated from a particle sytem */ + BL::ParticleSystem b_psys = b_dup.particle_system(); + if(!b_psys) + return false; + + /* test if we need particle data */ + if(!object->mesh->need_attribute(scene, ATTR_STD_PARTICLE)) + return false; + + /* don't handle child particles yet */ + BL::Array persistent_id = b_dup.persistent_id(); + + if(persistent_id[0] >= b_psys.particles.length()) + return false; + + /* find particle system */ + ParticleSystemKey key(b_ob, persistent_id); + ParticleSystem *psys; + + bool first_use = !particle_system_map.is_used(key); + bool need_update = particle_system_map.sync(&psys, b_ob, b_dup.object(), key); + + /* no update needed? */ + if(!need_update && !object->mesh->need_update && !scene->object_manager->need_update) + return true; + + /* first time used in this sync loop? clear and tag update */ + if(first_use) { + psys->particles.clear(); + psys->tag_update(scene); } - - return need_update; -} -static bool use_particle_system(BL::ParticleSystem b_psys) -{ - /* only use duplicator particles? disabled particle info for - * halo and billboard to reduce particle count. - * Probably not necessary since particles don't contain a huge amount - * of data compared to other textures. - */ - #if 0 - int render_type = b_psys->settings().render_type(); - return (render_type == BL::ParticleSettings::render_type_OBJECT - || render_type == BL::ParticleSettings::render_type_GROUP); - #endif + /* add particle */ + BL::Particle b_pa = b_psys.particles[persistent_id[0]]; + Particle pa; + pa.index = persistent_id[0]; + pa.age = b_scene.frame_current() - b_pa.birth_time(); + pa.lifetime = b_pa.lifetime(); + pa.location = get_float3(b_pa.location()); + pa.rotation = get_float4(b_pa.rotation()); + pa.size = b_pa.size(); + pa.velocity = get_float3(b_pa.velocity()); + pa.angular_velocity = get_float3(b_pa.angular_velocity()); + + psys->particles.push_back(pa); + + /* return that this object has particle data */ return true; } -static bool use_particle(BL::Particle b_pa, bool preview, bool show_unborn, bool use_dead) -{ - return b_pa.is_exist() && (!preview || b_pa.is_visible()) && - (b_pa.alive_state() != BL::Particle::alive_state_UNBORN || show_unborn) && - (b_pa.alive_state() != BL::Particle::alive_state_DEAD || use_dead); -} - -static int psys_count_particles(BL::ParticleSystem b_psys, bool preview) -{ - BL::ParticleSystem::particles_iterator b_pa; - bool show_unborn = b_psys.settings().show_unborn(); - bool use_dead = b_psys.settings().use_dead(); - int num = 0; - - for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) - if(use_particle(*b_pa, preview, show_unborn, use_dead)) - ++num; - - return num; -} - -int BlenderSync::object_count_particles(BL::Object b_ob) -{ - BL::Object::particle_systems_iterator b_psys; - int num = 0; - - for(b_ob.particle_systems.begin(b_psys); b_psys != b_ob.particle_systems.end(); ++b_psys) - if(use_particle_system(*b_psys)) - num += psys_count_particles(*b_psys, preview); - - return num; -} - -void BlenderSync::sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys) -{ - /* depending on settings the psys may not even be rendered */ - if(!use_particle_system(b_psys)) - return; - - /* key to lookup particle system */ - ParticleSystemKey key(b_ob, b_psys); - ParticleSystem *psys; - - /* test if we need to sync */ - bool object_updated = false; - - if(particle_system_map.sync(&psys, b_ob, b_ob, key)) - object_updated = true; - - bool need_update = psys_need_update(b_psys); - - if(object_updated || need_update) { - bool show_unborn = b_psys.settings().show_unborn(); - bool use_dead = b_psys.settings().use_dead(); - - int num = psys_count_particles(b_psys, preview); - psys->particles.clear(); - psys->particles.reserve(num); - - BL::ParticleSystem::particles_iterator b_pa; - int index = 0; - - for(b_psys.particles.begin(b_pa); b_pa != b_psys.particles.end(); ++b_pa) { - if(use_particle(*b_pa, preview, show_unborn, use_dead)) { - Particle pa; - - pa.index = index; - pa.age = b_scene.frame_current() - b_pa->birth_time(); - pa.lifetime = b_pa->lifetime(); - pa.location = get_float3(b_pa->location()); - pa.rotation = get_float4(b_pa->rotation()); - pa.size = b_pa->size(); - pa.velocity = get_float3(b_pa->velocity()); - pa.angular_velocity = get_float3(b_pa->angular_velocity()); - - psys->particles.push_back(pa); - } - - ++index; - } - - psys->tag_update(scene); - } -} - CCL_NAMESPACE_END diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 36cd5e684a7..9a478118c04 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -42,6 +42,7 @@ class Film; class Light; class Mesh; class Object; +class ParticleSystem; class Scene; class Shader; class ShaderGraph; @@ -80,20 +81,20 @@ private: void sync_nodes(Shader *shader, BL::ShaderNodeTree b_ntree); Mesh *sync_mesh(BL::Object b_ob, bool object_updated); - void sync_object(BL::Object b_parent, int b_index, BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion, int particle_id); - void sync_light(BL::Object b_parent, int b_index, BL::Object b_ob, Transform& tfm); + Object *sync_object(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::DupliObject b_dupli_object, Transform& tfm, uint layer_flag, int motion); + void sync_light(BL::Object b_parent, int persistent_id[OBJECT_PERSISTENT_ID_SIZE], BL::Object b_ob, Transform& tfm); void sync_background_light(); void sync_mesh_motion(BL::Object b_ob, Mesh *mesh, int motion); void sync_camera_motion(BL::Object b_ob, int motion); - void sync_particles(BL::Object b_ob, BL::ParticleSystem b_psys); + + /* particles */ + bool sync_dupli_particle(BL::Object b_ob, BL::DupliObject b_dup, Object *object); /* util */ void find_shader(BL::ID id, vector& used_shaders, int default_shader); bool BKE_object_is_modified(BL::Object b_ob); bool object_is_mesh(BL::Object b_ob); bool object_is_light(BL::Object b_ob); - bool psys_need_update(BL::ParticleSystem b_psys); - int object_count_particles(BL::Object b_ob); /* variables */ BL::RenderEngine b_engine; diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index df1e99882b8..5c47b124642 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -284,6 +284,12 @@ public: return recalc; } + bool is_used(const K& key) + { + T *data = find(key); + return (data)? used_set.find(data) != used_set.end(): NULL; + } + void used(T *data) { /* tag data as still in use */ @@ -343,27 +349,49 @@ protected: /* Object Key */ +enum { OBJECT_PERSISTENT_ID_SIZE = 8 }; + struct ObjectKey { void *parent; - int index; + int id[OBJECT_PERSISTENT_ID_SIZE]; void *ob; - ObjectKey(void *parent_, int index_, void *ob_) - : parent(parent_), index(index_), ob(ob_) {} + ObjectKey(void *parent_, int id_[OBJECT_PERSISTENT_ID_SIZE], void *ob_) + : parent(parent_), ob(ob_) + { + if(id_) + memcpy(id, id_, sizeof(id)); + else + memset(id, 0, sizeof(id)); + } bool operator<(const ObjectKey& k) const - { return (parent < k.parent || (parent == k.parent && (index < k.index || (index == k.index && ob < k.ob)))); } + { + return (parent < k.parent) || + (parent == k.parent && (memcmp(id, k.id, sizeof(id)) < 0)) || + (memcmp(id, k.id, sizeof(id)) == 0 && ob < k.ob); + } }; struct ParticleSystemKey { void *ob; - void *psys; + int id[OBJECT_PERSISTENT_ID_SIZE]; - ParticleSystemKey(void *ob_, void *psys_) - : ob(ob_), psys(psys_) {} + ParticleSystemKey(void *ob_, int id_[OBJECT_PERSISTENT_ID_SIZE]) + : ob(ob_) + { + if(id_) + memcpy(id, id_, sizeof(id)); + else + memset(id, 0, sizeof(id)); + } bool operator<(const ParticleSystemKey& k) const - { return (ob < k.ob && psys < k.psys); } + { + /* first id is particle index, we don't compare that */ + return (ob < k.ob) || + (ob == k.ob && (memcmp(id+1, k.id+1, sizeof(int)*(OBJECT_PERSISTENT_ID_SIZE-1)) < 0)); + } }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/particles.cpp b/intern/cycles/render/particles.cpp index 9f951d9673f..2a1570f7a0d 100644 --- a/intern/cycles/render/particles.cpp +++ b/intern/cycles/render/particles.cpp @@ -57,8 +57,7 @@ void ParticleSystemManager::device_update_particles(Device *device, DeviceScene { /* count particles. * adds one dummy particle at the beginning to avoid invalid lookups, - * in case a shader uses particle info without actual particle data. - */ + * in case a shader uses particle info without actual particle data. */ int num_particles = 1; foreach(ParticleSystem *psys, scene->particle_systems) num_particles += psys->particles.size(); diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index dffe26bd782..4b0c89f3a7a 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -76,8 +76,8 @@ /* --------------------- */ /* forward declarations */ -static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, - int level, short flag); +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], + int persistent_id[MAX_DUPLI_RECUR], int level, int index, short flag); /* ******************************************************************** */ /* Animation Visualization */ @@ -706,31 +706,39 @@ int where_on_path(Object *ob, float ctime, float vec[4], float dir[3], float qua #define DUPLILIST_FOR_RENDER 2 #define DUPLILIST_ANIMATED 4 -static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, int index, int par_index, int type, short flag) +static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], int lay, + int persistent_id[MAX_DUPLI_RECUR], int level, int index, int type, short flag) { DupliObject *dob = MEM_callocN(sizeof(DupliObject), "dupliobject"); - + int i; + BLI_addtail(lb, dob); dob->ob = ob; copy_m4_m4(dob->mat, mat); copy_m4_m4(dob->omat, ob->obmat); dob->origlay = ob->lay; - dob->index = index; - dob->particle_index = par_index; dob->type = type; dob->animated = (type == OB_DUPLIGROUP) && (flag & DUPLILIST_ANIMATED); ob->lay = lay; + + /* set persistent id, which is an array with a persistent index for each level + * (particle number, vertex number, ..). by comparing this we can find the same + * dupli object between frames, which is needed for motion blur. last level + * goes first in the array. */ + dob->persistent_id[0] = index; + for(i = 1; i < level; i++) + dob->persistent_id[i] = persistent_id[level-1-i]; return dob; } -static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, +static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { DupliObject *dob; Group *group; GroupObject *go; - float mat[4][4], tmat[4][4]; + float mat[4][4], tmat[4][4], id; if (ob->dup_group == NULL) return; group = ob->dup_group; @@ -750,7 +758,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde if (group_is_animated(ob, group)) flag |= DUPLILIST_ANIMATED; - for (go = group->gobject.first; go; go = go->next) { + for (go = group->gobject.first, id = 0; go; go = go->next, id++) { /* note, if you check on layer here, render goes wrong... it still deforms verts and uses parent imat */ if (go->ob != ob) { @@ -764,7 +772,7 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde mult_m4_m4m4(mat, ob->obmat, go->ob->obmat); } - dob = new_dupli_object(lb, go->ob, mat, ob->lay, 0, par_index, OB_DUPLIGROUP, flag); + dob = new_dupli_object(lb, go->ob, mat, ob->lay, persistent_id, level, id, OB_DUPLIGROUP, flag); /* check the group instance and object layers match, also that the object visible flags are ok. */ if ((dob->origlay & group->layer) == 0 || @@ -779,14 +787,14 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_inde if (go->ob->transflag & OB_DUPLI) { copy_m4_m4(dob->ob->obmat, dob->mat); - object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, par_index, level + 1, flag); + object_duplilist_recursive(&group->id, scene, go->ob, lb, ob->obmat, persistent_id, level + 1, id, flag); copy_m4_m4(dob->ob->obmat, dob->omat); } } } } -static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_index, int level, short flag) +static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { extern int enable_cu_speed; /* object.c */ Object copyob; @@ -834,7 +842,7 @@ static void frames_duplilist(ListBase *lb, Scene *scene, Object *ob, int par_ind BKE_animsys_evaluate_animdata(scene, &ob->id, ob->adt, (float)scene->r.cfra, ADT_RECALC_ANIM); /* ob-eval will do drivers, so we don't need to do them */ BKE_object_where_is_calc_time(scene, ob, (float)scene->r.cfra); - dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, scene->r.cfra, par_index, OB_DUPLIFRAMES, flag); + dob = new_dupli_object(lb, ob, ob->obmat, ob->lay, persistent_id, level, scene->r.cfra, OB_DUPLIFRAMES, flag); copy_m4_m4(dob->omat, copyob.obmat); } } @@ -865,7 +873,7 @@ typedef struct VertexDupliData { Scene *scene; Object *ob, *par; float (*orco)[3]; - int par_index; + int *persistent_id; } VertexDupliData; /* ------------- */ @@ -902,7 +910,7 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], origlay = vdd->ob->lay; - dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, index, vdd->par_index, OB_DUPLIVERTS, vdd->flag); + dob = new_dupli_object(vdd->lb, vdd->ob, obmat, vdd->par->lay, vdd->persistent_id, vdd->level, index, OB_DUPLIVERTS, vdd->flag); /* restore the original layer so that each dupli will have proper dob->origlay */ vdd->ob->lay = origlay; @@ -914,12 +922,12 @@ static void vertex_dupli__mapFunc(void *userData, int index, const float co[3], float tmpmat[4][4]; copy_m4_m4(tmpmat, vdd->ob->obmat); copy_m4_m4(vdd->ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->par_index, vdd->level + 1, vdd->flag); + object_duplilist_recursive((ID *)vdd->id, vdd->scene, vdd->ob, vdd->lb, obmat, vdd->persistent_id, vdd->level + 1, index, vdd->flag); copy_m4_m4(vdd->ob->obmat, tmpmat); } } -static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, +static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { Object *ob, *ob_iter; @@ -1004,7 +1012,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl vdd.scene = scene; vdd.par = par; copy_m4_m4(vdd.pmat, pmat); - vdd.par_index = par_index; + vdd.persistent_id = persistent_id; /* mballs have a different dupli handling */ if (ob->type != OB_MBALL) ob->flag |= OB_DONE; /* doesnt render */ @@ -1043,7 +1051,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl dm->release(dm); } -static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int par_index, +static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { Object *ob, *ob_iter; @@ -1186,7 +1194,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa copy_m4_m4(tmat, obmat); mul_m4_m4m3(obmat, tmat, mat); - dob = new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED)); + dob = new_dupli_object(lb, ob, obmat, par->lay, persistent_id, level, a, OB_DUPLIFACES, (flag & DUPLILIST_ANIMATED)); if (flag & DUPLILIST_FOR_RENDER) { w = 1.0f / (float)mp->totloop; @@ -1209,7 +1217,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa float tmpmat[4][4]; copy_m4_m4(tmpmat, ob->obmat); copy_m4_m4(ob->obmat, obmat); /* pretend we are really this mat */ - object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, par_index, level + 1, flag); + object_duplilist_recursive((ID *)id, scene, ob, lb, ob->obmat, persistent_id, level + 1, a, flag); copy_m4_m4(ob->obmat, tmpmat); } } @@ -1229,7 +1237,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa dm->release(dm); } -static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int UNUSED(par_index), ParticleSystem *psys, +static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, float par_space_mat[][4], int persistent_id[MAX_DUPLI_RECUR], ParticleSystem *psys, int level, short flag) { GroupObject *go; @@ -1244,7 +1252,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p float ctime, pa_time, scale = 1.0f; float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0; float (*obmat)[4], (*oldobmat)[4]; - int a, b, counter, index, hair = 0; + int a, b, hair = 0; int totpart, totchild, totgroup = 0 /*, pa_num */; int no_draw_flag = PARS_UNEXIST; @@ -1360,8 +1368,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else a = totpart; - index = 0; - for (pa = psys->particles, counter = 0; a < totpart + totchild; a++, pa++, counter++) { + for (pa = psys->particles; a < totpart + totchild; a++, pa++) { if (a < totpart) { /* handle parent particle */ if (pa->flag & no_draw_flag) @@ -1456,7 +1463,8 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p else copy_m4_m4(mat, tmat); - dob = new_dupli_object(lb, go->ob, mat, par->lay, counter, index, OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); + dob = new_dupli_object(lb, go->ob, mat, par->lay, persistent_id, level, a, OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); + dob->particle_system = psys; copy_m4_m4(dob->omat, obcopylist[b].obmat); if (flag & DUPLILIST_FOR_RENDER) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); @@ -1516,14 +1524,12 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p if (part->draw & PART_DRAW_GLOBAL_OB) add_v3_v3v3(mat[3], mat[3], vec); - dob = new_dupli_object(lb, ob, mat, ob->lay, counter, index, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); + dob = new_dupli_object(lb, ob, mat, ob->lay, persistent_id, level, a, GS(id->name) == ID_GR ? OB_DUPLIGROUP : OB_DUPLIPARTS, (flag & DUPLILIST_ANIMATED)); + dob->particle_system = psys; copy_m4_m4(dob->omat, oldobmat); if (flag & DUPLILIST_FOR_RENDER) psys_get_dupli_texture(psys, part, sim.psmd, pa, cpa, dob->uv, dob->orco); } - - /* only counts visible particles */ - index++; } /* restore objects since they were changed in BKE_object_where_is_calc_time */ @@ -1570,7 +1576,7 @@ static Object *find_family_object(Object **obar, char *family, char ch) } -static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_index, int level, short flag) +static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int persistent_id[MAX_DUPLI_RECUR], int level, short flag) { Object *ob, *obar[256] = {NULL}; Curve *cu; @@ -1609,7 +1615,7 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde copy_m4_m4(obmat, par->obmat); copy_v3_v3(obmat[3], vec); - new_dupli_object(lb, ob, obmat, par->lay, a, par_index, OB_DUPLIVERTS, flag); + new_dupli_object(lb, ob, obmat, par->lay, persistent_id, level, a, OB_DUPLIVERTS, flag); } } @@ -1618,8 +1624,8 @@ static void font_duplilist(ListBase *lb, Scene *scene, Object *par, int par_inde /* ------------- */ -static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], int par_index, - int level, short flag) +static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBase *duplilist, float par_space_mat[][4], + int persistent_id[MAX_DUPLI_RECUR], int level, int index, short flag) { if ((ob->transflag & OB_DUPLI) == 0) return; @@ -1636,34 +1642,45 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas } } + /* keep track of persistent id */ + if(level > 0) + persistent_id[level-1] = index; + if (ob->transflag & OB_DUPLIPARTS) { ParticleSystem *psys = ob->particlesystem.first; - for (; psys; psys = psys->next) - new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, psys, level + 1, flag); + int psysid = 0; + + /* particle system take up one level in id, the particles another */ + for (; psys; psys = psys->next, psysid++) { + persistent_id[level] = psysid; + new_particle_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, psys, level + 2, flag); + } + + persistent_id[level] = 0; } else if (ob->transflag & OB_DUPLIVERTS) { if (ob->type == OB_MESH) { - vertex_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag); + vertex_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, level + 1, flag); } else if (ob->type == OB_FONT) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ - font_duplilist(duplilist, scene, ob, par_index, level + 1, flag); + font_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag); } } } else if (ob->transflag & OB_DUPLIFACES) { if (ob->type == OB_MESH) - face_duplilist(duplilist, id, scene, ob, par_space_mat, par_index, level + 1, flag); + face_duplilist(duplilist, id, scene, ob, par_space_mat, persistent_id, level + 1, flag); } else if (ob->transflag & OB_DUPLIFRAMES) { if (GS(id->name) == ID_SCE) { /* TODO - support dupligroups */ - frames_duplilist(duplilist, scene, ob, par_index, level + 1, flag); + frames_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag); } } else if (ob->transflag & OB_DUPLIGROUP) { DupliObject *dob; - group_duplilist(duplilist, scene, ob, par_index, level + 1, flag); /* now recursive */ + group_duplilist(duplilist, scene, ob, persistent_id, level + 1, flag); /* now recursive */ if (level == 0) { for (dob = duplilist->first; dob; dob = dob->next) @@ -1671,6 +1688,10 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas copy_m4_m4(dob->ob->obmat, dob->mat); } } + + /* clear persistent id */ + if(level > 0) + persistent_id[level-1] = 0; } /* Returns a list of DupliObject @@ -1678,13 +1699,14 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas ListBase *object_duplilist_ex(Scene *sce, Object *ob, int update, int for_render) { ListBase *duplilist = MEM_mallocN(sizeof(ListBase), "duplilist"); + int persistent_id[MAX_DUPLI_RECUR] = {0}; int flag = 0; if (update) flag |= DUPLILIST_DO_UPDATE; if (for_render) flag |= DUPLILIST_FOR_RENDER; duplilist->first = duplilist->last = NULL; - object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, 0, 0, flag); + object_duplilist_recursive((ID *)sce, sce, ob, duplilist, NULL, persistent_id, 0, 0, flag); return duplilist; } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index 9fc4e0a906d..4d1f2bbc4e9 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1136,7 +1136,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, if (dupli_gh) BLI_ghash_insert(dupli_gh, dob, ob); if (parent_gh) - BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->index)), ob); + BLI_ghash_insert(parent_gh, BLI_ghashutil_pairalloc(dob->ob, SET_INT_IN_POINTER(dob->persistent_id[0])), ob); } if (use_hierarchy) { @@ -1150,7 +1150,7 @@ static void make_object_duplilist_real(bContext *C, Scene *scene, Base *base, /* find parent that was also made real */ if (ob_src_par) { - GHashPair *pair = BLI_ghashutil_pairalloc(ob_src_par, SET_INT_IN_POINTER(dob->index)); + GHashPair *pair = BLI_ghashutil_pairalloc(ob_src_par, SET_INT_IN_POINTER(dob->persistent_id[0])); ob_dst_par = BLI_ghash_lookup(parent_gh, pair); BLI_ghashutil_pairfree(pair); } diff --git a/source/blender/makesdna/DNA_object_types.h b/source/blender/makesdna/DNA_object_types.h index 29f6499986c..89328c33674 100644 --- a/source/blender/makesdna/DNA_object_types.h +++ b/source/blender/makesdna/DNA_object_types.h @@ -297,22 +297,19 @@ typedef struct ObHook { typedef struct DupliObject { struct DupliObject *next, *prev; struct Object *ob; - unsigned int origlay; - int index; + unsigned int origlay, pad; float mat[4][4], omat[4][4]; float orco[3], uv[2]; short type; /* from Object.transflag */ char no_draw, animated; - /* Lowest-level particle index. - * Note: This is needed for particle info in shaders. - * Otherwise dupli groups in particle systems would override the - * index value from higher dupli levels. Would be nice to have full generic access - * to all dupli levels somehow, but for now this should cover most use-cases. - */ - int particle_index; - int pad; + /* persistent identifier for a dupli object, for inter-frame matching of + * objects with motion blur, or inter-update matching for syncing */ + int persistent_id[8]; /* MAX_DUPLI_RECUR */ + + /* particle this dupli was generated from */ + struct ParticleSystem *particle_system; } DupliObject; /* **************** OBJECT ********************* */ diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 82f27b953cf..d436e4719ea 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -1419,6 +1419,12 @@ int rna_Camera_object_poll(PointerRNA *UNUSED(ptr), PointerRNA value) return ((Object *)value.id.data)->type == OB_CAMERA; } +int rna_DupliObject_index_get(PointerRNA *ptr) +{ + DupliObject *dob = (DupliObject *)ptr->data; + return dob->persistent_id[0]; +} + #else static int rna_matrix_dimsize_4x4[] = {4, 4}; @@ -2653,22 +2659,23 @@ static void rna_def_dupli_object(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Hide", "Don't show dupli object in viewport or render"); prop = RNA_def_property(srna, "index", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "index"); + RNA_def_property_int_funcs(prop, "rna_DupliObject_index_get", NULL, NULL); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "Index", "Index in the lowest-level dupli list"); - - prop = RNA_def_property(srna, "particle_index", PROP_INT, PROP_NONE); - RNA_def_property_int_sdna(prop, NULL, "particle_index"); + + prop = RNA_def_property(srna, "persistent_id", PROP_INT, PROP_NONE); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); - RNA_def_property_ui_text(prop, "Particle Index", "Index in the lowest-level particle dupli list"); + RNA_def_property_ui_text(prop, "Persistent ID", "Persistent identifier for inter-frame matching of objects with motion blur"); + + prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); + RNA_def_property_ui_text(prop, "Particle System", "Particle system that this dupli object was instanced from"); prop = RNA_def_property(srna, "orco", PROP_FLOAT, PROP_TRANSLATION); - RNA_def_property_float_sdna(prop, NULL, "orco"); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "Generated Coordinates", "Generated coordinates in parent object space"); prop = RNA_def_property(srna, "uv", PROP_FLOAT, PROP_NONE); - RNA_def_property_float_sdna(prop, NULL, "uv"); RNA_def_property_array(prop, 2); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE | PROP_EDITABLE); RNA_def_property_ui_text(prop, "UV Coordinates", "UV coordinates in parent object space"); diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c index eb0a13b3942..759b0737c01 100644 --- a/source/blender/render/intern/source/convertblender.c +++ b/source/blender/render/intern/source/convertblender.c @@ -4501,7 +4501,7 @@ static void add_render_object(Render *re, Object *ob, Object *par, DupliObject * ParticleSystem *psys; int show_emitter, allow_render= 1, index, psysindex, i; - index= (dob)? dob->index: 0; + index= (dob)? dob->persistent_id[0]: 0; /* the emitter has to be processed first (render levels of modifiers) */ /* so here we only check if the emitter should be rendered */ @@ -4900,7 +4900,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, 0))) { mult_m4_m4m4(mat, re->viewmat, dob->mat); /* ob = particle system, use that layer */ - obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, 0, mat, ob->lay); + obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], 0, mat, ob->lay); /* fill in instance variables for texturing */ set_dupli_tex_mat(re, obi, dob); @@ -4927,7 +4927,7 @@ static void database_init_objects(Render *re, unsigned int renderlay, int nolamp if (dob->type != OB_DUPLIGROUP || (obr=find_dupligroup_dupli(re, obd, psysindex))) { if (obi == NULL) mult_m4_m4m4(mat, re->viewmat, dob->mat); - obi= RE_addRenderInstance(re, NULL, obd, ob, dob->index, psysindex++, mat, obd->lay); + obi= RE_addRenderInstance(re, NULL, obd, ob, dob->persistent_id[0], psysindex++, mat, obd->lay); set_dupli_tex_mat(re, obi, dob); if (dob->type != OB_DUPLIGROUP) { From 360528d66709be21cac6ef3c98916174990accc3 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Thu, 8 Nov 2012 16:50:31 +0000 Subject: [PATCH 028/118] Bugfix #29072 (Color pickers don't close properly when moving the mouse away) This rewinds the fix for revision 50483. - the removed code there (as comment said) closes menus on hoovering over another button in panels. Is unfinished feature to allow quick inspecting menus by mouse-hold going over menu popup buttons. - It added yet another check for closing menus - should be done with ->saferct - The actual bug was simple; the block flag with UI_BLOCK_MOVEMOUSE_QUIT was accidentally cleared for colorpickers. --- .../editors/interface/interface_handlers.c | 32 +++++-------------- .../editors/interface/interface_regions.c | 4 +-- 2 files changed, 9 insertions(+), 27 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index ecb161714ee..5d4427bcbef 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -6050,38 +6050,22 @@ static int ui_handle_button_event(bContext *C, wmEvent *event, uiBut *but) switch (event->type) { case MOUSEMOVE: { - /* if the mouse is over the button, do nothing */ - if (ui_mouse_inside_button(data->region, but, event->x, event->y)) { - break; - } + uiBut *bt; - /* if the mouse is over the menu, also do nothing */ if (data->menu && data->menu->region) { if (ui_mouse_inside_region(data->menu->region, event->x, event->y)) { break; } - else { - /* make a rectangle between the menu and the button that opened it, - * this avoids any space between them exiting the popup. see [#29072] - campbell */ - rctf rct_all = but->rect; - rctf rct_win; + } - ui_block_to_window_fl(ar, block, &rct_all.xmin, &rct_all.ymin); - ui_block_to_window_fl(ar, block, &rct_all.xmax, &rct_all.ymax); - - BLI_rctf_rcti_copy(&rct_win, &data->menu->region->winrct); - BLI_rctf_union(&rct_all, &rct_win); - - if (BLI_rctf_isect_pt(&rct_all, event->x, event->y)) { - break; - } + bt = ui_but_find_mouse_over(ar, event->x, event->y); + + if (bt && bt->active != data) { + if (but->type != COLOR) { /* exception */ + data->cancel = TRUE; } + button_activate_state(C, but, BUTTON_STATE_EXIT); } - - if (but->type != COLOR) { /* exception */ - data->cancel = TRUE; - } - button_activate_state(C, but, BUTTON_STATE_EXIT); break; } } diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index 28e361ccf5a..9b77072dee1 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -2254,13 +2254,11 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_ show_picker = (but->block->flag & UI_BLOCK_POPUP) == 0; } - uiBlockSetFlag(block, UI_BLOCK_MOVEMOUSE_QUIT); - copy_v3_v3(handle->retvec, but->editvec); uiBlockPicker(block, handle->retvec, &but->rnapoin, but->rnaprop, show_picker); - block->flag = UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1; + block->flag = UI_BLOCK_LOOP | UI_BLOCK_REDRAW | UI_BLOCK_KEEP_OPEN | UI_BLOCK_OUT_1 | UI_BLOCK_MOVEMOUSE_QUIT; uiBoundsBlock(block, 10); block->block_event_func = ui_picker_small_wheel_cb; From b537758192abd5657a6e2c7b365db0c1afd50bee Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Thu, 8 Nov 2012 19:50:25 +0000 Subject: [PATCH 029/118] OSX/cmake: fix jack compile --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7da2da4d61f..fa6d8711514 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1383,7 +1383,7 @@ elseif(APPLE) endif() if(WITH_JACK) - set(JACK /usr) + set(JACK /usr/local) set(JACK_INCLUDE_DIRS ${JACK}/include/jack) set(JACK_LIBRARIES jack) set(JACK_LIBPATH ${JACK}/lib) From 610d746c12c33954774a6fc903e42e03590ecb81 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 03:08:02 +0000 Subject: [PATCH 030/118] code cleanup: double promotion warnings with new bevel code & wrong use of NULL in cycles. --- intern/cycles/blender/blender_util.h | 2 +- source/blender/bmesh/operators/bmo_bevel.c | 26 +++++++++++----------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/intern/cycles/blender/blender_util.h b/intern/cycles/blender/blender_util.h index 5c47b124642..4feb8b556d5 100644 --- a/intern/cycles/blender/blender_util.h +++ b/intern/cycles/blender/blender_util.h @@ -287,7 +287,7 @@ public: bool is_used(const K& key) { T *data = find(key); - return (data)? used_set.find(data) != used_set.end(): NULL; + return (data) ? used_set.find(data) != used_set.end() : false; } void used(T *data) diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index ee8d0d7f9cd..16108bda80c 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -430,7 +430,7 @@ static void slide_dist(EdgeHalf *e, BMVert *v, float d, float slideco[3]) len = len_v3(dir); normalize_v3(dir); if (d > len) - d = len - 50 * BEVEL_EPSILON; + d = len - (float)(50 * BEVEL_EPSILON); copy_v3_v3(slideco, v->co); madd_v3_v3fl(slideco, dir, -d); } @@ -481,17 +481,17 @@ static int find_intersection_point(float r[3], float a1[3], float a2[3], float b nx = b2[0] - b1[0]; ny = b2[1] - b1[1]; - s = ((b1[1] - a1[1]) / my + (a1[0] - b1[0]) / mx) / (nx / mx - ny / my); - t = (b1[0] - a1[0] + s * nx) / mx; + s = ((double)(b1[1] - a1[1]) / my + (double)(a1[0] - b1[0]) / mx) / (nx / mx - ny / my); + t = ((double)(b1[0] - a1[0]) + s * nx) / mx; - z1 = a1[2] + t * (a2[2] - a1[2]); - z2 = b1[2] + s * (b2[2] - b1[2]); + z1 = (double)a1[2] + t * (double)(a2[2] - a1[2]); + z2 = (double)b1[2] + s * (double)(b2[2] - b1[2]); if (fabs(z1 - z2) < BEVEL_EPSILON) { flag = 1; - r[0] = a1[0] + t * mx; - r[1] = a1[1] + t * my; + r[0] = (double)a1[0] + t * mx; + r[1] = (double)a1[1] + t * my; r[2] = z1; } else @@ -510,11 +510,11 @@ static int find_intersection_point(float r[3], float a1[3], float a2[3], float b static void find_intersection_point_plane(float r[3], float p1[3], float p2[3], float p3[3], float a[3], float m[3]) { + const double null = 1e-20; float P[3], N[3], A[3], M[3]; float vv1[3], vv2[3]; double t; double C, D, E; - float null = 1e-20; /* calculation of the normal to the surface */ @@ -549,9 +549,9 @@ static void find_intersection_point_plane(float r[3], float p1[3], float p2[3], else t = (C - D) / E; - r[0] = m[0] + t * a[0]; - r[1] = m[1] + t * a[1]; - r[2] = m[2] + t * a[2]; + r[0] = (double)m[0] + t * (double)a[0]; + r[1] = (double)m[1] + t * (double)a[1]; + r[2] = (double)m[2] + t * (double)a[2]; } } @@ -579,7 +579,7 @@ static void get_point_on_round_profile(float r[3], float offset, int i, int coun add_v3_v3v3(center, vva, vvb); normalize_v3(center); - mul_v3_fl(center, offset * (1.0 / cos(0.5 * angle))); + mul_v3_fl(center, offset * (1.0f / cosf(0.5f * angle))); add_v3_v3(center, v); /* coordinates of the center of the inscribed circle */ @@ -622,7 +622,7 @@ static void get_point_on_round_edge(EdgeHalf *e, int i, else sub_v3_v3v3(dir, e->e->v2->co, e->e->v1->co); normalize_v3(dir); - if (fabs(angle_v3v3(vva, vvb) - M_PI) > BEVEL_EPSILON) { + if (fabsf(angle_v3v3(vva, vvb) - (float)M_PI) > (float)BEVEL_EPSILON) { copy_v3_v3(vaadj, va); madd_v3_v3fl(vaadj, dir, -len_v3(vva) * cosf(angle_v3v3(vva, dir))); copy_v3_v3(vbadj, vb); From 1c3640997c225d9bcd6e7559863d69366edc16ee Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 9 Nov 2012 03:10:15 +0000 Subject: [PATCH 031/118] Fix #33082: dupliverted metaball showing wrong in cycles render and metaball edit mode. I've made it follow blender internal now, but this system should really be improved once, metaballs that are in linked dupligroups will never show up. --- source/blender/blenkernel/intern/anim.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 4b0c89f3a7a..1aed26db48d 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -726,9 +726,15 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i * dupli object between frames, which is needed for motion blur. last level * goes first in the array. */ dob->persistent_id[0] = index; - for(i = 1; i < level; i++) + for (i = 1; i < level; i++) dob->persistent_id[i] = persistent_id[level-1-i]; + /* metaballs never draw in duplis, they are instead merged into one by the basis + * mball outside of the group. this does mean that if that mball is not in the + * scene, they will not show up at all, limitation that should be solved once. */ + if (ob->type == OB_MBALL) + dob->no_draw = TRUE; + return dob; } @@ -781,9 +787,6 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persiste { dob->no_draw = TRUE; } - else { - dob->no_draw = FALSE; - } if (go->ob->transflag & OB_DUPLI) { copy_m4_m4(dob->ob->obmat, dob->mat); @@ -1643,7 +1646,7 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas } /* keep track of persistent id */ - if(level > 0) + if (level > 0) persistent_id[level-1] = index; if (ob->transflag & OB_DUPLIPARTS) { @@ -1690,7 +1693,7 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas } /* clear persistent id */ - if(level > 0) + if (level > 0) persistent_id[level-1] = 0; } From f171d0f29c1394795c0a1dea2cb5118859e9ccdc Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 9 Nov 2012 03:10:22 +0000 Subject: [PATCH 032/118] Fix #33125: cycles OSL crash with multiple render sessions running at the same time. --- intern/cycles/kernel/osl/osl_globals.h | 5 +++++ intern/cycles/kernel/osl/osl_shader.cpp | 23 +++++++++++++++++++++++ intern/cycles/render/osl.cpp | 16 ++++++++++++---- intern/cycles/render/osl.h | 2 ++ 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h index 5d557ffcb07..80ced9dfd62 100644 --- a/intern/cycles/kernel/osl/osl_globals.h +++ b/intern/cycles/kernel/osl/osl_globals.h @@ -68,6 +68,11 @@ struct OSLGlobals { }; static tls_ptr(ThreadData, thread_data); + static thread_mutex thread_data_mutex; + static volatile int thread_data_users; + + void thread_data_init(); + void thread_data_free(); }; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 0c8de058b5b..abf7c041cb3 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -32,9 +32,32 @@ CCL_NAMESPACE_BEGIN tls_ptr(OSLGlobals::ThreadData, OSLGlobals::thread_data); +volatile int OSLGlobals::thread_data_users = 0; +thread_mutex OSLGlobals::thread_data_mutex; /* Threads */ +void OSLGlobals::thread_data_init() +{ + thread_scoped_lock thread_data_lock(thread_data_mutex); + + if(thread_data_users == 0) + tls_create(OSLGlobals::ThreadData, thread_data); + + thread_data_users++; +} + +void OSLGlobals::thread_data_free() +{ + /* thread local storage delete */ + thread_scoped_lock thread_data_lock(thread_data_mutex); + + thread_data_users--; + + if(thread_data_users == 0) + tls_delete(OSLGlobals::ThreadData, thread_data); +} + void OSLShader::thread_init(KernelGlobals *kg) { OSL::ShadingSystem *ss = kg->osl.ss; diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index 8bdb09eaf70..5fbc7932849 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -45,6 +45,8 @@ CCL_NAMESPACE_BEGIN OSLShaderManager::OSLShaderManager() { + thread_data_initialized = false; + services = new OSLRenderServices(); shading_system_init(); @@ -91,8 +93,6 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene og->background_state = og->surface_state[background_id & SHADER_MASK]; og->use = true; - tls_create(OSLGlobals::ThreadData, og->thread_data); - foreach(Shader *shader, scene->shaders) shader->need_update = false; @@ -102,6 +102,11 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene scene->image_manager->set_osl_texture_system((void*)ts); device_update_common(device, dscene, scene, progress); + + if(!thread_data_initialized) { + og->thread_data_init(); + thread_data_initialized = true; + } } void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) @@ -114,12 +119,15 @@ void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) og->use = false; og->ss = NULL; - tls_delete(OSLGlobals::ThreadData, og->thread_data); - og->surface_state.clear(); og->volume_state.clear(); og->displacement_state.clear(); og->background_state.reset(); + + if(thread_data_initialized) { + og->thread_data_free(); + thread_data_initialized = false; + } } void OSLShaderManager::texture_system_init() diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index cee37c58d74..b4b3f59e02a 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -73,6 +73,8 @@ protected: OSLRenderServices *services; OSL::ErrorHandler errhandler; set loaded_shaders; + + bool thread_data_initialized; }; #endif From 41deb7b021126f0b9566ee1f87787ca73adc215d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 9 Nov 2012 03:10:29 +0000 Subject: [PATCH 033/118] CMake: LLVM configuration tweak to check if llvm-config actually exists before using it (patch by IRIE Shinsuke). Also search for any library instead of just static ones. --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fa6d8711514..5ec2e3378a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -719,7 +719,7 @@ if(UNIX AND NOT APPLE) set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") set(LLVM_VERSION "3.0" CACHE STRING "Version of LLVM to use") set(LLVM_STATIC YES) - if(LLVM_DIRECTORY) + if(EXISTS "${LLVM_DIRECTORY}/bin/llvm-config") set(LLVM_CONFIG "${LLVM_DIRECTORY}/bin/llvm-config") else() set(LLVM_CONFIG llvm-config) @@ -734,7 +734,7 @@ if(UNIX AND NOT APPLE) OUTPUT_VARIABLE LLVM_LIB_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) find_library(LLVM_LIBRARY - NAMES libLLVMAnalysis.a # first of a whole bunch of libs to get + NAMES LLVMAnalysis # first of a whole bunch of libs to get PATHS ${LLVM_LIB_DIR}) message(STATUS "LLVM version = ${LLVM_VERSION}") message(STATUS "LLVM dir = ${LLVM_DIRECTORY}") @@ -1596,7 +1596,7 @@ elseif(APPLE) set(LLVM_DIRECTORY ${LIBDIR}/llvm CACHE PATH "Path to the LLVM installation") set(LLVM_VERSION "3.1" CACHE STRING "Version of LLVM to use") set(LLVM_STATIC YES) - if(LLVM_DIRECTORY) + if(EXISTS "${LLVM_DIRECTORY}/bin/llvm-config") set(LLVM_CONFIG "${LLVM_DIRECTORY}/bin/llvm-config") else() set(LLVM_CONFIG llvm-config) @@ -1611,7 +1611,7 @@ elseif(APPLE) OUTPUT_VARIABLE LLVM_LIB_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) find_library(LLVM_LIBRARY - NAMES libLLVMAnalysis.a # first of a whole bunch of libs to get + NAMES LLVMAnalysis # first of a whole bunch of libs to get PATHS ${LLVM_LIB_DIR}) message(STATUS "LLVM version = ${LLVM_VERSION}") message(STATUS "LLVM dir = ${LLVM_DIRECTORY}") From cf08068e10040a3f4d5548bfcb4e4940d2f75d8d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 03:36:38 +0000 Subject: [PATCH 034/118] fix [#33121] crashing when srolling down in text editor ! --- source/blender/blenlib/BLI_string_utf8.h | 1 + source/blender/blenlib/intern/string_utf8.c | 27 +++++++++---- .../editors/interface/interface_widgets.c | 2 + source/blender/editors/space_text/text_draw.c | 38 +++++++++---------- source/blender/editors/space_text/text_ops.c | 14 +++---- 5 files changed, 49 insertions(+), 33 deletions(-) diff --git a/source/blender/blenlib/BLI_string_utf8.h b/source/blender/blenlib/BLI_string_utf8.h index 73f138a750d..ecbc4cb1cd4 100644 --- a/source/blender/blenlib/BLI_string_utf8.h +++ b/source/blender/blenlib/BLI_string_utf8.h @@ -37,6 +37,7 @@ int BLI_utf8_invalid_byte(const char *str, int length); int BLI_utf8_invalid_strip(char *str, int length); int BLI_str_utf8_size(const char *p); /* warning, can return -1 on bad chars */ +int BLI_str_utf8_size_safe(const char *p); /* copied from glib */ unsigned int BLI_str_utf8_as_unicode(const char *p); unsigned int BLI_str_utf8_as_unicode_and_size(const char *__restrict p, size_t *__restrict index); diff --git a/source/blender/blenlib/intern/string_utf8.c b/source/blender/blenlib/intern/string_utf8.c index 0b737e0eff5..e80f96ee0fe 100644 --- a/source/blender/blenlib/intern/string_utf8.c +++ b/source/blender/blenlib/intern/string_utf8.c @@ -317,12 +317,12 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size /* end wchar_t / utf8 functions */ /* --------------------------------------------------------------------------*/ -/* copied from glib's gutf8.c */ +/* copied from glib's gutf8.c, added 'Err' arg */ /* note, glib uses unsigned int for unicode, best we do the same, * though we don't typedef it - campbell */ -#define UTF8_COMPUTE(Char, Mask, Len) \ +#define UTF8_COMPUTE(Char, Mask, Len, Err) \ if (Char < 128) { \ Len = 1; \ Mask = 0x7f; \ @@ -348,7 +348,7 @@ size_t BLI_strncpy_wchar_from_utf8(wchar_t *dst_w, const char *src_c, const size Mask = 0x01; \ } \ else { \ - Len = -1; \ + Len = Err; /* -1 is the typical error value or 1 to skip */ \ } (void)0 /* same as glib define but added an 'Err' arg */ @@ -371,7 +371,20 @@ int BLI_str_utf8_size(const char *p) int mask = 0, len; unsigned char c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len, -1); + + (void)mask; /* quiet warning */ + + return len; +} + +/* use when we want to skip errors */ +int BLI_str_utf8_size_safe(const char *p) +{ + int mask = 0, len; + unsigned char c = (unsigned char) *p; + + UTF8_COMPUTE (c, mask, len, 1); (void)mask; /* quiet warning */ @@ -397,7 +410,7 @@ unsigned int BLI_str_utf8_as_unicode(const char *p) unsigned int result; unsigned char c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len, -1); if (len == -1) return BLI_UTF8_ERR; UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR); @@ -412,7 +425,7 @@ unsigned int BLI_str_utf8_as_unicode_and_size(const char *p, size_t *index) unsigned int result; unsigned char c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len, -1); if (len == -1) return BLI_UTF8_ERR; UTF8_GET (result, p, i, mask, len, BLI_UTF8_ERR); @@ -431,7 +444,7 @@ unsigned int BLI_str_utf8_as_unicode_step(const char *p, size_t *index) p += *index; c = (unsigned char) *p; - UTF8_COMPUTE (c, mask, len); + UTF8_COMPUTE (c, mask, len, -1); if (len == -1) { /* when called with NULL end, result will never be NULL, * checks for a NULL character */ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index f41abce947e..d16169f1034 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1044,6 +1044,8 @@ static void ui_text_clip_cursor(uiFontStyle *fstyle, uiBut *but, rcti *rect) ui_text_clip_give_prev_off(but); len = strlen(but->drawstr); bytes = BLI_str_utf8_size(BLI_str_find_prev_char_utf8(but->drawstr, but->drawstr + len)); + if (bytes < 0) + bytes = 1; but->drawstr[len - bytes] = 0; } diff --git a/source/blender/editors/space_text/text_draw.c b/source/blender/editors/space_text/text_draw.c index 94f64563fd8..f463b015bf5 100644 --- a/source/blender/editors/space_text/text_draw.c +++ b/source/blender/editors/space_text/text_draw.c @@ -95,7 +95,7 @@ static int text_font_draw_character(SpaceText *st, int x, int y, char c) static int text_font_draw_character_utf8(SpaceText *st, int x, int y, const char *c) { char str[BLI_UTF8_MAX + 1]; - size_t len = BLI_str_utf8_size(c); + size_t len = BLI_str_utf8_size_safe(c); memcpy(str, c, len); str[len] = '\0'; @@ -158,7 +158,7 @@ int flatten_string(SpaceText *st, FlattenString *fs, const char *in) in++; } else { - size_t len = BLI_str_utf8_size(in); + size_t len = BLI_str_utf8_size_safe(in); flatten_string_append(fs, in, r, len); in += len; total++; @@ -342,7 +342,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) if (*str == '\\') { *fmt = prev; fmt++; str++; if (*str == '\0') break; - *fmt = prev; fmt++; str += BLI_str_utf8_size(str); + *fmt = prev; fmt++; str += BLI_str_utf8_size_safe(str); continue; } /* Handle continuations */ @@ -363,14 +363,14 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) } *fmt = 'l'; - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; } /* Not in a string... */ else { /* Deal with comments first */ if (prev == '#' || *str == '#') { *fmt = '#'; - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; } else if (*str == '"' || *str == '\'') { /* Strings */ @@ -399,7 +399,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) *fmt = 'n'; } else { - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; *fmt = 'q'; } /* Punctuation */ @@ -407,7 +407,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) *fmt = '!'; /* Identifiers and other text (no previous ws. or delims. so text continues) */ else if (prev == 'q') { - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; *fmt = 'q'; } /* Not ws, a digit, punct, or continuing text. Must be new, check for special words */ @@ -427,7 +427,7 @@ static void txt_format_line(SpaceText *st, TextLine *line, int do_next) *fmt = prev; } else { - str += BLI_str_utf8_size(str) - 1; + str += BLI_str_utf8_size_safe(str) - 1; *fmt = 'q'; } } @@ -575,7 +575,7 @@ void wrap_offset(SpaceText *st, ARegion *ar, TextLine *linein, int cursin, int * end = max; chop = 1; *offc = 0; - for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size(linep->line + j)) { + for (i = 0, j = 0; linep->line[j]; j += BLI_str_utf8_size_safe(linep->line + j)) { int chars; /* Mimic replacement of tabs */ @@ -640,7 +640,7 @@ void wrap_offset_in_line(SpaceText *st, ARegion *ar, TextLine *linein, int cursi *offc = 0; cursin = txt_utf8_offset_to_index(linein->line, cursin); - for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size(linein->line + j)) { + for (i = 0, j = 0; linein->line[j]; j += BLI_str_utf8_size_safe(linein->line + j)) { /* Mimic replacement of tabs */ ch = linein->line[j]; @@ -685,7 +685,7 @@ int text_get_char_pos(SpaceText *st, const char *line, int cur) { int a = 0, i; - for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size(line + i)) { + for (i = 0; i < cur && line[i]; i += BLI_str_utf8_size_safe(line + i)) { if (line[i] == '\t') a += st->tabnumber - a % st->tabnumber; else @@ -698,7 +698,7 @@ static const char *txt_utf8_get_nth(const char *str, int n) { int pos = 0; while (str[pos] && n--) { - pos += BLI_str_utf8_size(str + pos); + pos += BLI_str_utf8_size_safe(str + pos); } return str + pos; } @@ -719,7 +719,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w start = 0; mstart = 0; end = max; mend = txt_utf8_get_nth(str, max) - str; - for (i = 0, mi = 0; str[mi]; i++, mi += BLI_str_utf8_size(str + mi)) { + for (i = 0, mi = 0; str[mi]; i++, mi += BLI_str_utf8_size_safe(str + mi)) { if (i - start >= max) { /* skip hidden part of line */ if (skip) { @@ -730,7 +730,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w } /* Draw the visible portion of text on the overshot line */ - for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size(str + ma)) { + for (a = start, ma = mstart; a < end; a++, ma += BLI_str_utf8_size_safe(str + ma)) { if (st->showsyntax && format) format_draw_color(format[a]); x += text_font_draw_character_utf8(st, x, y, str + ma); } @@ -748,7 +748,7 @@ static int text_draw_wrapped(SpaceText *st, const char *str, int x, int y, int w } /* Draw the remaining text */ - for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size(str + ma)) { + for (a = start, ma = mstart; str[ma] && y > 0; a++, ma += BLI_str_utf8_size_safe(str + ma)) { if (st->showsyntax && format) format_draw_color(format[a]); @@ -786,7 +786,7 @@ static int text_draw(SpaceText *st, char *str, int cshift, int maxwidth, int dra for (a = 0; a < amount; a++) { format_draw_color(format[a]); x += text_font_draw_character_utf8(st, x, y, in + str_shift); - str_shift += BLI_str_utf8_size(in + str_shift); + str_shift += BLI_str_utf8_size_safe(in + str_shift); } } else text_font_draw(st, x, y, in); @@ -1016,7 +1016,7 @@ int text_get_visible_lines(SpaceText *st, ARegion *ar, const char *str) lines = 1; start = 0; end = max; - for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size(str + j)) { + for (i = 0, j = 0; str[j]; j += BLI_str_utf8_size_safe(str + j)) { /* Mimic replacement of tabs */ ch = str[j]; if (ch == '\t') { @@ -1639,7 +1639,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar) if (b > 0) { /* opening bracket, search forward for close */ fc++; - c += BLI_str_utf8_size(linep->line + c); + c += BLI_str_utf8_size_safe(linep->line + c); while (linep) { while (c < linep->len) { if (linep->format && linep->format[fc] != 'l' && linep->format[fc] != '#') { @@ -1657,7 +1657,7 @@ static void draw_brackets(SpaceText *st, ARegion *ar) } } fc++; - c += BLI_str_utf8_size(linep->line + c); + c += BLI_str_utf8_size_safe(linep->line + c); } if (endl) break; linep = linep->next; diff --git a/source/blender/editors/space_text/text_ops.c b/source/blender/editors/space_text/text_ops.c index 2d902c4586a..1be50a54b68 100644 --- a/source/blender/editors/space_text/text_ops.c +++ b/source/blender/editors/space_text/text_ops.c @@ -1503,7 +1503,7 @@ static int text_get_cursor_rel(SpaceText *st, ARegion *ar, TextLine *linein, int end = max; chop = loop = 1; - for (i = 0, j = 0; loop; j += BLI_str_utf8_size(linein->line + j)) { + for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe(linein->line + j)) { int chars; /* Mimic replacement of tabs */ ch = linein->line[j]; @@ -1682,7 +1682,7 @@ static void txt_wrap_move_bol(SpaceText *st, ARegion *ar, short sel) chop = loop = 1; *charp = 0; - for (i = 0, j = 0; loop; j += BLI_str_utf8_size((*linep)->line + j)) { + for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) { int chars; /* Mimic replacement of tabs */ ch = (*linep)->line[j]; @@ -1750,7 +1750,7 @@ static void txt_wrap_move_eol(SpaceText *st, ARegion *ar, short sel) chop = loop = 1; *charp = 0; - for (i = 0, j = 0; loop; j += BLI_str_utf8_size((*linep)->line + j)) { + for (i = 0, j = 0; loop; j += BLI_str_utf8_size_safe((*linep)->line + j)) { int chars; /* Mimic replacement of tabs */ ch = (*linep)->line[j]; @@ -2462,7 +2462,7 @@ static int flatten_len(SpaceText *st, const char *str) { int i, total = 0; - for (i = 0; str[i]; i += BLI_str_utf8_size(str + i)) { + for (i = 0; str[i]; i += BLI_str_utf8_size_safe(str + i)) { if (str[i] == '\t') { total += st->tabnumber - total % st->tabnumber; } @@ -2475,7 +2475,7 @@ static int flatten_len(SpaceText *st, const char *str) static int flatten_index_to_offset(SpaceText *st, const char *str, int index) { int i, j; - for (i = 0, j = 0; i < index; j += BLI_str_utf8_size(str + j)) + for (i = 0, j = 0; i < index; j += BLI_str_utf8_size_safe(str + j)) if (str[j] == '\t') i += st->tabnumber - i % st->tabnumber; else @@ -2519,7 +2519,7 @@ static void text_cursor_set_to_pos_wrapped(SpaceText *st, ARegion *ar, int x, in int j = 0, curs = 0, endj = 0; /* mem */ int chop = 1; /* flags */ - for (; loop; j += BLI_str_utf8_size(linep->line + j)) { + for (; loop; j += BLI_str_utf8_size_safe(linep->line + j)) { int chars; /* Mimic replacement of tabs */ @@ -2945,7 +2945,7 @@ static int text_insert_invoke(bContext *C, wmOperator *op, wmEvent *event) size_t len; if (event->utf8_buf[0]) { - len = BLI_str_utf8_size(event->utf8_buf); + len = BLI_str_utf8_size_safe(event->utf8_buf); memcpy(str, event->utf8_buf, len); } else { From 11a5c909f86e26ff00883be4b1dfcdac1f699717 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 04:01:19 +0000 Subject: [PATCH 035/118] code cleanup: move shrinkwrap's benchmark macro into PIL_time.h & some minor style edits. --- CMakeLists.txt | 4 +- source/blender/blenkernel/intern/shrinkwrap.c | 41 ++++++------------- source/blender/blenlib/PIL_time.h | 8 ++++ source/blender/bmesh/operators/bmo_bevel.c | 6 +-- 4 files changed, 25 insertions(+), 34 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5ec2e3378a6..e8119ca1fcd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -313,8 +313,8 @@ if(APPLE) string(SUBSTRING "${XCODE_VERS_BUILD_NR}" 6 3 XCODE_VERSION) # truncate away build-nr unset(XCODE_VERS_BUILD_NR) # force CMAKE_OSX_DEPLOYMENT_TARGET for makefiles, will not work else ( cmake bug ? ) - set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}" ) - set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}" ) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") add_definitions ("-DMACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}") endif() diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index 96faec389df..c71de01103f 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -56,33 +56,16 @@ #include "BKE_mesh.h" #include "BKE_tessmesh.h" +/* for timing... */ +#if 0 +# include "PIL_time.h" +#else +# define TIMEIT_BENCH(expr, id) (expr) +#endif + /* Util macros */ #define OUT_OF_MEMORY() ((void)printf("Shrinkwrap: Out of memory\n")) -/* Benchmark macros */ -#if !defined(_WIN32) && 0 - -#include - -#define BENCH(a) \ - do { \ - double _t1, _t2; \ - struct timeval _tstart, _tend; \ - clock_t _clock_init = clock(); \ - gettimeofday ( &_tstart, NULL); \ - (a); \ - gettimeofday ( &_tend, NULL); \ - _t1 = ( double ) _tstart.tv_sec + ( double ) _tstart.tv_usec/ ( 1000*1000 ); \ - _t2 = ( double ) _tend.tv_sec + ( double ) _tend.tv_usec/ ( 1000*1000 ); \ - printf("%s: %fs (real) %fs (cpu)\n", #a, _t2-_t1, (float)(clock()-_clock_init)/CLOCKS_PER_SEC);\ - } while (0) - -#else - -#define BENCH(a) (a) - -#endif - /* get derived mesh */ /* TODO is anyfunction that does this? returning the derivedFinal without we caring if its in edit mode or not? */ DerivedMesh *object_get_derived_final(Object *ob) @@ -143,7 +126,7 @@ static void shrinkwrap_calc_nearest_vertex(ShrinkwrapCalcData *calc) BVHTreeNearest nearest = NULL_BVHTreeNearest; - BENCH(bvhtree_from_mesh_verts(&treeData, calc->target, 0.0, 2, 6)); + TIMEIT_BENCH(bvhtree_from_mesh_verts(&treeData, calc->target, 0.0, 2, 6), bvhtree_verts); if (treeData.tree == NULL) { OUT_OF_MEMORY(); return; @@ -437,7 +420,7 @@ static void shrinkwrap_calc_nearest_surface_point(ShrinkwrapCalcData *calc) BVHTreeNearest nearest = NULL_BVHTreeNearest; /* Create a bvh-tree of the given target */ - BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 2, 6)); + TIMEIT_BENCH(bvhtree_from_mesh_faces(&treeData, calc->target, 0.0, 2, 6), bvhtree_faces); if (treeData.tree == NULL) { OUT_OF_MEMORY(); return; @@ -584,15 +567,15 @@ void shrinkwrapModifier_deform(ShrinkwrapModifierData *smd, Object *ob, DerivedM if (calc.target) { switch (smd->shrinkType) { case MOD_SHRINKWRAP_NEAREST_SURFACE: - BENCH(shrinkwrap_calc_nearest_surface_point(&calc)); + TIMEIT_BENCH(shrinkwrap_calc_nearest_surface_point(&calc), deform_surface); break; case MOD_SHRINKWRAP_PROJECT: - BENCH(shrinkwrap_calc_normal_projection(&calc)); + TIMEIT_BENCH(shrinkwrap_calc_normal_projection(&calc), deform_project); break; case MOD_SHRINKWRAP_NEAREST_VERTEX: - BENCH(shrinkwrap_calc_nearest_vertex(&calc)); + TIMEIT_BENCH(shrinkwrap_calc_nearest_vertex(&calc), deform_vertex); break; } } diff --git a/source/blender/blenlib/PIL_time.h b/source/blender/blenlib/PIL_time.h index b8f895c5c82..afad190ba23 100644 --- a/source/blender/blenlib/PIL_time.h +++ b/source/blender/blenlib/PIL_time.h @@ -76,6 +76,14 @@ void PIL_sleep_ms(int ms); fflush(stdout); \ } (void)0 + +#define TIMEIT_BENCH(expr, id) \ + { \ + TIMEIT_START(id); \ + (expr); \ + TIMEIT_END(id); \ + } (void)0 + #ifdef __cplusplus } #endif diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index 16108bda80c..8ced18d6d90 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -510,7 +510,7 @@ static int find_intersection_point(float r[3], float a1[3], float a2[3], float b static void find_intersection_point_plane(float r[3], float p1[3], float p2[3], float p3[3], float a[3], float m[3]) { - const double null = 1e-20; + const double isect_epsilon = 1e-20; float P[3], N[3], A[3], M[3]; float vv1[3], vv2[3]; double t; @@ -542,9 +542,9 @@ static void find_intersection_point_plane(float r[3], float p1[3], float p2[3], else { C = N[0] * P[0] + N[1] * P[1] + N[2] * P[2]; D = N[0] * M[0] + N[1] * M[1] + N[2] * M[2]; - E = (A[0] * N[0] + A[1] * N[1] + A[2] * N[2]); + E = A[0] * N[0] + A[1] * N[1] + A[2] * N[2]; - if (fabs(E) < null) + if (fabs(E) < isect_epsilon) t = 0; else t = (C - D) / E; From 56ae13be991ea652e90c06737ba59c5975bbee14 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 04:20:17 +0000 Subject: [PATCH 036/118] add a distance limit to the shrinkwrap modifiers project mode, it was problematic for vertices to fire rays out and hit some unrelated-far-off geometry which is often not what users want. --- release/scripts/startup/bl_ui/properties_data_modifier.py | 4 ++-- source/blender/blenkernel/intern/shrinkwrap.c | 8 ++++++++ source/blender/makesdna/DNA_modifier_types.h | 5 +++-- source/blender/makesrna/intern/rna_modifier.c | 7 +++++++ 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_modifier.py b/release/scripts/startup/bl_ui/properties_data_modifier.py index 902358813df..ea8ffbe6c9f 100644 --- a/release/scripts/startup/bl_ui/properties_data_modifier.py +++ b/release/scripts/startup/bl_ui/properties_data_modifier.py @@ -625,6 +625,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.prop(md, "wrap_method", text="") if md.wrap_method == 'PROJECT': + col.prop(md, "project_limit", text="Limit") split = layout.split(percentage=0.25) col = split.column() @@ -642,8 +643,7 @@ class DATA_PT_modifiers(ModifierButtonsPanel, Panel): col.label(text="Cull Faces:") col.prop(md, "cull_face", expand=True) - layout.label(text="Auxiliary Target:") - layout.prop(md, "auxiliary_target", text="") + layout.prop(md, "auxiliary_target") elif md.wrap_method == 'NEAREST_SURFACEPOINT': layout.prop(md, "use_keep_above_surface") diff --git a/source/blender/blenkernel/intern/shrinkwrap.c b/source/blender/blenkernel/intern/shrinkwrap.c index c71de01103f..72db34d339c 100644 --- a/source/blender/blenkernel/intern/shrinkwrap.c +++ b/source/blender/blenkernel/intern/shrinkwrap.c @@ -277,6 +277,7 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) /* Options about projection direction */ const char use_normal = calc->smd->shrinkOpts; + const float proj_limit_squared = calc->smd->projLimit * calc->smd->projLimit; float proj_axis[3] = {0.0f, 0.0f, 0.0f}; /* Raycast and tree stuff */ @@ -393,6 +394,13 @@ static void shrinkwrap_calc_normal_projection(ShrinkwrapCalcData *calc) treeData.raycast_callback, &treeData); } + /* don't set the initial dist (which is more efficient), + * because its calculated in the targets space, we want the dist in our own space */ + if (proj_limit_squared != 0.0f) { + if (len_squared_v3v3(hit.co, co) > proj_limit_squared) { + hit.index = -1; + } + } if (hit.index != -1) { madd_v3_v3v3fl(hit.co, hit.co, tmp_no, calc->keepDist); diff --git a/source/blender/makesdna/DNA_modifier_types.h b/source/blender/makesdna/DNA_modifier_types.h index c9e929ce41b..2c896e4893f 100644 --- a/source/blender/makesdna/DNA_modifier_types.h +++ b/source/blender/makesdna/DNA_modifier_types.h @@ -665,7 +665,8 @@ typedef struct ShrinkwrapModifierData { float keepDist; /* distance offset to keep from mesh/projection point */ short shrinkType; /* shrink type projection */ short shrinkOpts; /* shrink options */ - char projAxis; /* axis to project over */ + float projLimit; /* limit the projection ray cast */ + char projAxis; /* axis to project over */ /* * if using projection over vertex normal this controls the @@ -674,7 +675,7 @@ typedef struct ShrinkwrapModifierData { */ char subsurfLevels; - char pad[6]; + char pad[2]; } ShrinkwrapModifierData; diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c index d421eb697a3..2e3f8feda44 100644 --- a/source/blender/makesrna/intern/rna_modifier.c +++ b/source/blender/makesrna/intern/rna_modifier.c @@ -2400,6 +2400,13 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Offset", "Distance to keep from the target"); RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "project_limit", PROP_FLOAT, PROP_NONE); + RNA_def_property_float_sdna(prop, NULL, "projLimit"); + RNA_def_property_range(prop, 0.0, FLT_MAX); + RNA_def_property_ui_range(prop, 0, 100, 1, 2); + RNA_def_property_ui_text(prop, "Project Limit", "Limit the distance used for projection (zero disables)"); + RNA_def_property_update(prop, 0, "rna_Modifier_update"); + prop = RNA_def_property(srna, "use_project_x", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "projAxis", MOD_SHRINKWRAP_PROJECT_OVER_X_AXIS); RNA_def_property_ui_text(prop, "X", ""); From 0f2c27b855fe42b33d09fe841bf959e553565eb3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 05:37:36 +0000 Subject: [PATCH 037/118] Option for shrink-fatten to maintain shell thickness (hold Alt). --- source/blender/editors/transform/transform.c | 21 ++++++++++++------- .../editors/transform/transform_conversions.c | 10 ++++++++- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 28ec90a648a..961e5c49ab2 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1223,8 +1223,10 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case LEFTALTKEY: case RIGHTALTKEY: - if (t->spacetype == SPACE_SEQ) + if (ELEM(t->spacetype ,SPACE_SEQ, SPACE_VIEW3D)) { t->flag |= T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } break; default: @@ -1262,8 +1264,10 @@ int transformEvent(TransInfo *t, wmEvent *event) // break; case LEFTALTKEY: case RIGHTALTKEY: - if (t->spacetype == SPACE_SEQ) + if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { t->flag &= ~T_ALT_TRANSFORM; + t->redraw |= TREDRAW_HARD; + } break; default: @@ -3947,10 +3951,8 @@ void initShrinkFatten(TransInfo *t) } - int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) { - float vec[3]; float distance; int i; char str[64]; @@ -3978,17 +3980,20 @@ int ShrinkFatten(TransInfo *t, const int UNUSED(mval[2])) t->values[0] = -distance; for (i = 0; i < t->total; i++, td++) { + float tdistance; /* temp dist */ if (td->flag & TD_NOACTION) break; if (td->flag & TD_SKIP) continue; - copy_v3_v3(vec, td->axismtx[2]); - mul_v3_fl(vec, distance); - mul_v3_fl(vec, td->factor); + /* get the final offset */ + tdistance = distance * td->factor; + if (td->ext && (t->flag & T_ALT_TRANSFORM)) { + tdistance *= td->ext->isize[0]; /* shell factor */ + } - add_v3_v3v3(td->loc, td->iloc, vec); + madd_v3_v3v3fl(td->loc, td->iloc, td->axismtx[2], tdistance); } recalcData(t); diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index f6b888d4881..8e268e46696 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -1917,6 +1917,10 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx tx->size = vs->radius; td->val = vs->radius; } + else if (t->mode == TFM_SHRINKFATTEN) { + td->ext = tx; + tx->isize[0] = BM_vert_calc_shell_factor(eve); + } } static void createTransEditVerts(TransInfo *t) @@ -2029,7 +2033,11 @@ static void createTransEditVerts(TransInfo *t) else t->total = countsel; tob = t->data = MEM_callocN(t->total * sizeof(TransData), "TransObData(Mesh EditMode)"); - if (t->mode == TFM_SKIN_RESIZE) { + if (ELEM(t->mode, TFM_SKIN_RESIZE, TFM_SHRINKFATTEN)) { + /* warning, this is overkill, we only need 2 extra floats, + * but this stores loads of extra stuff, for TFM_SHRINKFATTEN its even more overkill + * since we may not use the 'alt' transform mode to maintain shell thickness, + * but with generic transform code its hard to lazy init vars */ tx = t->ext = MEM_callocN(t->total * sizeof(TransDataExtension), "TransObData ext"); } From 1369e29db01ccbaa5a11add9e888972fde9af7ae Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 06:06:50 +0000 Subject: [PATCH 038/118] shrink/fatten was missing from the transform menu --- release/scripts/startup/bl_ui/space_view3d.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 21a80df9ead..b29f51d90a2 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -168,6 +168,8 @@ class VIEW3D_MT_transform(VIEW3D_MT_transform_base): # generic... layout = self.layout + layout.operator("transform.shrink_fatten", text="Shrink Fatten") + layout.separator() layout.operator("transform.translate", text="Move Texture Space").texture_space = True From 9b91da0d0dea01ef74b317bdaeaf20d19cf7cfd0 Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 9 Nov 2012 06:36:11 +0000 Subject: [PATCH 039/118] Axis Colours are now Themeable This commit allows you to set the RGB <-> XYZ axis colours used for things like the mini axis indicator, grid axis indicators, manipulators, transform constraint indicators, F-Curves (when using XYZ to RGB colouring option), and perhaps something else I've missed. Previously, these places all used hardcoded defines (220 * i/j/k), but the readability of these colours was often quite poor, especially when used with certain themes. The settings for these colours can be found under the "User Interface" section of the themes (i.e. same set of colours is used across editors). I could have made these per editor, but since it's unlikely that these will need to be too different across editors in practice (+ being easier to version patch), they are stored under the UI section. --- .../scripts/startup/bl_ui/space_userpref.py | 23 ++++++++++ source/blender/blenkernel/BKE_blender.h | 2 +- source/blender/editors/animation/anim_draw.c | 2 +- source/blender/editors/include/UI_resources.h | 6 ++- source/blender/editors/interface/resources.c | 43 +++++++++++++------ .../blender/editors/space_graph/space_graph.c | 6 +-- .../editors/space_view3d/view3d_draw.c | 16 +++---- .../editors/transform/transform_manipulator.c | 10 ++--- source/blender/makesdna/DNA_userdef_types.h | 3 +- source/blender/makesrna/intern/rna_userdef.c | 19 ++++++++ 10 files changed, 95 insertions(+), 35 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 455bf210ac2..c5a0a851fc5 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -728,6 +728,29 @@ class USERPREF_PT_theme(Panel): colsub = padding.column() colsub.row().prop(ui, "header") + col.separator() + col.separator() + + ui = theme.user_interface + col.label("Axis Colors:") + + row = col.row() + + subsplit = row.split(percentage=0.95) + + padding = subsplit.split(percentage=0.15) + colsub = padding.column() + colsub = padding.column() + colsub.row().prop(ui, "axis_x") + colsub.row().prop(ui, "axis_y") + colsub.row().prop(ui, "axis_z") + + subsplit = row.split(percentage=0.85) + + padding = subsplit.split(percentage=0.15) + colsub = padding.column() + colsub = padding.column() + layout.separator() layout.separator() elif theme.theme_area == 'BONE_COLOR_SETS': diff --git a/source/blender/blenkernel/BKE_blender.h b/source/blender/blenkernel/BKE_blender.h index e7033d8648d..3c210877de7 100644 --- a/source/blender/blenkernel/BKE_blender.h +++ b/source/blender/blenkernel/BKE_blender.h @@ -42,7 +42,7 @@ extern "C" { * and keep comment above the defines. * Use STRINGIFY() rather than defining with quotes */ #define BLENDER_VERSION 264 -#define BLENDER_SUBVERSION 8 +#define BLENDER_SUBVERSION 9 /* 262 was the last editmesh release but it has compatibility code for bmesh data */ #define BLENDER_MINVERSION 262 diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c index 01c0a95e200..0f0584ad8fe 100644 --- a/source/blender/editors/animation/anim_draw.c +++ b/source/blender/editors/animation/anim_draw.c @@ -381,7 +381,7 @@ float ANIM_unit_mapping_get_factor(Scene *scene, ID *id, FCurve *fcu, short rest return RAD2DEGF(1.0f); /* radians to degrees */ } } - + /* TODO: other rotation types here as necessary */ } } diff --git a/source/blender/editors/include/UI_resources.h b/source/blender/editors/include/UI_resources.h index e879a01dbfb..f4e921e2fa4 100644 --- a/source/blender/editors/include/UI_resources.h +++ b/source/blender/editors/include/UI_resources.h @@ -215,7 +215,11 @@ enum { TH_NLA_META, TH_NLA_META_SEL, TH_NLA_SOUND, - TH_NLA_SOUND_SEL + TH_NLA_SOUND_SEL, + + TH_AXIS_X, /* X/Y/Z Axis */ + TH_AXIS_Y, + TH_AXIS_Z }; /* XXX WARNING: previous is saved in file, so do not change order! */ diff --git a/source/blender/editors/interface/resources.c b/source/blender/editors/interface/resources.c index e03a2887866..fa5d5806bb8 100644 --- a/source/blender/editors/interface/resources.c +++ b/source/blender/editors/interface/resources.c @@ -236,7 +236,7 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo cp = ts->shade2; break; case TH_HILITE: cp = ts->hilite; break; - + case TH_GRID: cp = ts->grid; break; case TH_WIRE: @@ -510,6 +510,13 @@ const unsigned char *UI_ThemeGetColorPtr(bTheme *btheme, int spacetype, int colo case TH_NLA_SOUND_SEL: cp = ts->nla_sound_sel; break; + + case TH_AXIS_X: + cp = btheme->tui.xaxis; break; + case TH_AXIS_Y: + cp = btheme->tui.yaxis; break; + case TH_AXIS_Z: + cp = btheme->tui.zaxis; break; } } } @@ -655,9 +662,14 @@ void ui_theme_init_default(void) /* UI buttons */ ui_widget_color_init(&btheme->tui); + btheme->tui.iconfile[0] = 0; btheme->tui.panel.show_header = FALSE; rgba_char_args_set(btheme->tui.panel.header, 0, 0, 0, 25); + + rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255); + rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255); + rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255); /* Bone Color Sets */ ui_theme_init_boneColorSets(btheme); @@ -1072,7 +1084,6 @@ float UI_GetThemeValuef(int colorid) cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); return ((float)cp[0]); - } /* get individual values, not scaled */ @@ -1082,7 +1093,6 @@ int UI_GetThemeValue(int colorid) cp = UI_ThemeGetColorPtr(theme_active, theme_spacetype, colorid); return ((int) cp[0]); - } @@ -1244,21 +1254,20 @@ void UI_ThemeClearColor(int colorid) void UI_make_axis_color(const unsigned char src_col[3], unsigned char dst_col[3], const char axis) { + unsigned char col[3]; + switch (axis) { case 'X': - dst_col[0] = src_col[0] > 219 ? 255 : src_col[0] + 36; - dst_col[1] = src_col[1] < 26 ? 0 : src_col[1] - 26; - dst_col[2] = src_col[2] < 26 ? 0 : src_col[2] - 26; + UI_GetThemeColor3ubv(TH_AXIS_X, col); + UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10); break; case 'Y': - dst_col[0] = src_col[0] < 46 ? 0 : src_col[0] - 36; - dst_col[1] = src_col[1] > 189 ? 255 : src_col[1] + 66; - dst_col[2] = src_col[2] < 46 ? 0 : src_col[2] - 36; + UI_GetThemeColor3ubv(TH_AXIS_Y, col); + UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10); break; case 'Z': - dst_col[0] = src_col[0] < 26 ? 0 : src_col[0] - 26; - dst_col[1] = src_col[1] < 26 ? 0 : src_col[1] - 26; - dst_col[2] = src_col[2] > 209 ? 255 : src_col[2] + 46; + UI_GetThemeColor3ubv(TH_AXIS_Z, col); + UI_GetColorPtrBlendShade3ubv(src_col, col, dst_col, 0.5f, -10); break; default: BLI_assert(!"invalid axis arg"); @@ -1946,6 +1955,16 @@ void init_userdef_do_versions(void) rgba_char_args_set(btheme->tv3d.skin_root, 180, 77, 77, 255); } } + + if (bmain->versionfile < 264 || (bmain->versionfile == 264 && bmain->subversionfile < 9)) { + bTheme *btheme; + + for (btheme = U.themes.first; btheme; btheme = btheme->next) { + rgba_char_args_set(btheme->tui.xaxis, 220, 0, 0, 255); + rgba_char_args_set(btheme->tui.yaxis, 0, 220, 0, 255); + rgba_char_args_set(btheme->tui.zaxis, 0, 0, 220, 255); + } + } /* GL Texture Garbage Collection (variable abused above!) */ if (U.textimeout == 0) { diff --git a/source/blender/editors/space_graph/space_graph.c b/source/blender/editors/space_graph/space_graph.c index f41169b6c39..fa7c6bd472a 100644 --- a/source/blender/editors/space_graph/space_graph.c +++ b/source/blender/editors/space_graph/space_graph.c @@ -563,13 +563,13 @@ static void graph_refresh(const bContext *C, ScrArea *sa) switch (fcu->array_index) { case 0: - col[0] = 1.0f; col[1] = 0.0f; col[2] = 0.0f; + UI_GetThemeColor3fv(TH_AXIS_X, col); break; case 1: - col[0] = 0.0f; col[1] = 1.0f; col[2] = 0.0f; + UI_GetThemeColor3fv(TH_AXIS_Y, col); break; case 2: - col[0] = 0.0f; col[1] = 0.0f; col[2] = 1.0f; + UI_GetThemeColor3fv(TH_AXIS_Z, col); break; default: /* 'unknown' color - bluish so as to not conflict with handles */ diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 4d4fad47698..60cf9a3c4c4 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -545,12 +545,8 @@ static void drawfloor(Scene *scene, View3D *v3d, const char **grid_unit) } } } - - - - - if (v3d->zbuf && scene->obedit) glDepthMask(1); + if (v3d->zbuf && scene->obedit) glDepthMask(1); } static void drawcursor(Scene *scene, ARegion *ar, View3D *v3d) @@ -600,8 +596,8 @@ static void draw_view_axis(RegionView3D *rv3d) mul_qt_v3(rv3d->viewquat, vec); dx = vec[0] * k; dy = vec[1] * k; - - glColor4ub(220, 0, 0, bright); + + UI_ThemeColorShadeAlpha(TH_AXIS_X, 0, bright); glBegin(GL_LINES); glVertex2f(start, start + ydisp); glVertex2f(start + dx, start + dy + ydisp); @@ -620,8 +616,8 @@ static void draw_view_axis(RegionView3D *rv3d) mul_qt_v3(rv3d->viewquat, vec); dx = vec[0] * k; dy = vec[1] * k; - - glColor4ub(0, 220, 0, bright); + + UI_ThemeColorShadeAlpha(TH_AXIS_Y, 0, bright); glBegin(GL_LINES); glVertex2f(start, start + ydisp); glVertex2f(start + dx, start + dy + ydisp); @@ -640,7 +636,7 @@ static void draw_view_axis(RegionView3D *rv3d) dx = vec[0] * k; dy = vec[1] * k; - glColor4ub(30, 30, 220, bright); + UI_ThemeColorShadeAlpha(TH_AXIS_Z, 0, bright); glBegin(GL_LINES); glVertex2f(start, start + ydisp); glVertex2f(start + dx, start + dy + ydisp); diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 0780b8f90b5..a3f45acc02e 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -744,7 +744,7 @@ static char axisBlendAngle(float angle) return (char)(255.0f * (angle - 5) / 15.0f); } -/* three colors can be set; +/* three colors can be set: * gray for ghosting * moving: in transform theme color * else the red/green/blue @@ -776,15 +776,13 @@ static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned c } break; case 'X': - col[0] = 220; + UI_GetThemeColor3ubv(TH_AXIS_X, col); break; case 'Y': - col[1] = 220; + UI_GetThemeColor3ubv(TH_AXIS_Y, col); break; case 'Z': - col[0] = 30; - col[1] = 30; - col[2] = 220; + UI_GetThemeColor3ubv(TH_AXIS_Z, col); break; default: BLI_assert(!"invalid axis arg"); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index 2256968da56..caa7c880aee 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -162,7 +162,8 @@ typedef struct ThemeUI { char iconfile[256]; // FILE_MAXFILE length float icon_alpha; - float pad; + /* Axis Colors */ + char xaxis[4], yaxis[4], zaxis[4]; } ThemeUI; /* try to put them all in one, if needed a special struct can be created as well diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index fe179d8486d..11e04cdd281 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -770,6 +770,25 @@ static void rna_def_userdef_theme_ui(BlenderRNA *brna) prop = RNA_def_property(srna, "icon_alpha", PROP_FLOAT, PROP_FACTOR); RNA_def_property_ui_text(prop, "Icon Alpha", "Transparency of icons in the interface, to reduce contrast"); RNA_def_property_update(prop, 0, "rna_userdef_update"); + + /* axis */ + prop = RNA_def_property(srna, "axis_x", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "xaxis"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "X Axis", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "axis_y", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "yaxis"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Y Axis", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); + + prop = RNA_def_property(srna, "axis_z", PROP_FLOAT, PROP_COLOR_GAMMA); + RNA_def_property_float_sdna(prop, NULL, "zaxis"); + RNA_def_property_array(prop, 3); + RNA_def_property_ui_text(prop, "Z Axis", ""); + RNA_def_property_update(prop, 0, "rna_userdef_update"); } static void rna_def_userdef_theme_space_generic(BlenderRNA *brna) From 9dcd7f3b0b55e49a18296a67863368a0c4fca8b0 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 9 Nov 2012 07:29:27 +0000 Subject: [PATCH 040/118] Fix crash when copying scene with sequencer's animation using Link Objects or Link Object Data methods - Don't crash if there's any fcurves created for sequencer but no sequencer itself - Don't copy sequencer's fcurves when copy new scene with linking data/objects method --- source/blender/blenkernel/intern/scene.c | 24 +++++++++++++++++++ .../blender/editors/animation/anim_filter.c | 16 +++++++------ 2 files changed, 33 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index c923c34a0ae..edd880238ca 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -58,8 +58,10 @@ #include "BKE_anim.h" #include "BKE_animsys.h" +#include "BKE_action.h" #include "BKE_colortools.h" #include "BKE_depsgraph.h" +#include "BKE_fcurve.h" #include "BKE_global.h" #include "BKE_group.h" #include "BKE_idprop.h" @@ -115,6 +117,24 @@ void free_qtcodecdata(QuicktimeCodecData *qcd) } } +static void remove_sequencer_fcurves(Scene *sce) +{ + AnimData *ad = BKE_animdata_from_id(&sce->id); + + if (ad && ad->action) { + FCurve *fcu, *nextfcu; + + for (fcu = ad->action->curves.first; fcu; fcu = nextfcu) { + nextfcu = fcu->next; + + if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { + action_groups_remove_channel(ad->action, fcu); + free_fcurve(fcu); + } + } + } +} + Scene *BKE_scene_copy(Scene *sce, int type) { Scene *scen; @@ -179,6 +199,10 @@ Scene *BKE_scene_copy(Scene *sce, int type) BLI_strncpy(scen->sequencer_colorspace_settings.name, sce->sequencer_colorspace_settings.name, sizeof(scen->sequencer_colorspace_settings.name)); + + /* remove animation used by sequencer */ + if (type != SCE_COPY_FULL) + remove_sequencer_fcurves(scen); } /* tool settings */ diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 721b3473792..425ee899fe7 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -911,14 +911,16 @@ static short skip_fcurve_selected_data(bDopeSheet *ads, FCurve *fcu, ID *owner_i /* only consider if F-Curve involves sequence_editor.sequences */ if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { Editing *ed = BKE_sequencer_editing_get(scene, FALSE); - Sequence *seq; + Sequence *seq = NULL; char *seq_name; - - /* get strip name, and check if this strip is selected */ - seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); - seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, FALSE); - if (seq_name) MEM_freeN(seq_name); - + + if (ed) { + /* get strip name, and check if this strip is selected */ + seq_name = BLI_str_quoted_substrN(fcu->rna_path, "sequences_all["); + seq = BKE_sequence_get_by_name(ed->seqbasep, seq_name, FALSE); + if (seq_name) MEM_freeN(seq_name); + } + /* can only add this F-Curve if it is selected */ if (ads->filterflag & ADS_FILTER_ONLYSEL) { if ((seq == NULL) || (seq->flag & SELECT) == 0) From eff734203ff7a0f4a4f97015c9f1f59632c75abf Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 08:28:14 +0000 Subject: [PATCH 041/118] add fallbacks for BM_vert_calc_shell_factor() and BM_vert_calc_mean_tagged_edge_length() to avoid divide by zero when a vertex has no connected geometry. also style cleanup. --- source/blender/blenkernel/intern/anim.c | 6 +++--- source/blender/blenlib/PIL_time.h | 7 +++++-- source/blender/bmesh/intern/bmesh_queries.c | 14 ++++++++++++-- source/blender/bmesh/operators/bmo_bevel.c | 3 +-- source/blender/editors/space_view3d/view3d_draw.c | 2 +- source/blender/editors/transform/transform.c | 2 +- .../blender/windowmanager/intern/wm_event_system.c | 9 ++++++--- 7 files changed, 29 insertions(+), 14 deletions(-) diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index 1aed26db48d..f5c0660371b 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -727,7 +727,7 @@ static DupliObject *new_dupli_object(ListBase *lb, Object *ob, float mat[][4], i * goes first in the array. */ dob->persistent_id[0] = index; for (i = 1; i < level; i++) - dob->persistent_id[i] = persistent_id[level-1-i]; + dob->persistent_id[i] = persistent_id[level - 1 - i]; /* metaballs never draw in duplis, they are instead merged into one by the basis * mball outside of the group. this does mean that if that mball is not in the @@ -1647,7 +1647,7 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas /* keep track of persistent id */ if (level > 0) - persistent_id[level-1] = index; + persistent_id[level - 1] = index; if (ob->transflag & OB_DUPLIPARTS) { ParticleSystem *psys = ob->particlesystem.first; @@ -1694,7 +1694,7 @@ static void object_duplilist_recursive(ID *id, Scene *scene, Object *ob, ListBas /* clear persistent id */ if (level > 0) - persistent_id[level-1] = 0; + persistent_id[level - 1] = 0; } /* Returns a list of DupliObject diff --git a/source/blender/blenlib/PIL_time.h b/source/blender/blenlib/PIL_time.h index afad190ba23..c3e7e8486d9 100644 --- a/source/blender/blenlib/PIL_time.h +++ b/source/blender/blenlib/PIL_time.h @@ -20,7 +20,7 @@ * * The Original Code is: all of this file. * - * Contributor(s): none yet. + * Contributor(s): Campbell Barton * * ***** END GPL LICENSE BLOCK ***** */ @@ -76,7 +76,10 @@ void PIL_sleep_ms(int ms); fflush(stdout); \ } (void)0 - +/** + * Given some function/expression: + * TIMEIT_BENCH(some_function(), some_unique_description); + */ #define TIMEIT_BENCH(expr, id) \ { \ TIMEIT_START(id); \ diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index ed36a86274c..8eb87cf29be 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -1024,7 +1024,12 @@ float BM_vert_calc_shell_factor(BMVert *v) accum_angle += face_angle; } - return accum_shell / accum_angle; + if (accum_angle != 0.0f) { + return accum_shell / accum_angle; + } + else { + return 1.0f; + } } /** @@ -1045,7 +1050,12 @@ float BM_vert_calc_mean_tagged_edge_length(BMVert *v) } } - return length / (float)tot; + if (tot) { + return length / (float)tot; + } + else { + return 0.0f; + } } diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index 8ced18d6d90..50d3598dba2 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -1155,8 +1155,7 @@ static void bevel_vert_construct(BMesh *bm, BevelParams *bp, BMOperator *op, BMV /* Gather input selected edges. * Only bevel selected edges that have exactly two incident faces. */ BMO_ITER (bme, &siter, bm, op, "geom", BM_EDGE) { - if ((bme->v1 == v) || (BM_edge_other_vert(bme, bme->v1) == v)) - { + if ((bme->v1 == v) || (BM_edge_other_vert(bme, bme->v1) == v)) { if (BM_edge_face_count(bme) == 2) { BMO_elem_flag_enable(bm, bme, EDGE_SELECTED); nsel++; diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 60cf9a3c4c4..db74179b569 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1214,7 +1214,7 @@ static void drawviewborder(Scene *scene, ARegion *ar, View3D *v3d) hmargin = 0.1f * (x2 - x1); vmargin = 0.05f * (y2 - y1); - uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1+vmargin, x2 - hmargin, y2 - vmargin, 2.0f); + uiDrawBox(GL_LINE_LOOP, x1 + hmargin, y1 + vmargin, x2 - hmargin, y2 - vmargin, 2.0f); hmargin = 0.035f * (x2 - x1); vmargin = 0.035f * (y2 - y1); diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 961e5c49ab2..1334db63865 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -1223,7 +1223,7 @@ int transformEvent(TransInfo *t, wmEvent *event) break; case LEFTALTKEY: case RIGHTALTKEY: - if (ELEM(t->spacetype ,SPACE_SEQ, SPACE_VIEW3D)) { + if (ELEM(t->spacetype, SPACE_SEQ, SPACE_VIEW3D)) { t->flag |= T_ALT_TRANSFORM; t->redraw |= TREDRAW_HARD; } diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 236ab264f8c..14244de00f6 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -2979,9 +2979,12 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U event.keymodifier = 0; /* if test_break set, it catches this. Do not set with modifier presses. XXX Keep global for now? */ - if (event.type == ESCKEY && event.val == KM_PRESS && - event.shift == 0 && event.ctrl == 0 && event.alt == 0) - G.is_break = TRUE; + if ((event.type == ESCKEY && event.val == KM_PRESS) && + /* check other modifiers because ms-windows uses these to bring up the task manager */ + (event.shift == 0 && event.ctrl == 0 && event.alt == 0)) + { + G.is_break = TRUE; + } /* double click test - only for press */ if (event.val == KM_PRESS) { From 76525d53982dc783d9f1bf33223e0e7a2b412c60 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 9 Nov 2012 08:46:53 +0000 Subject: [PATCH 042/118] Cycles: persistent images option This option enables keeping loaded images in the memory in-between of rendering. Implemented by keeping render engine alive for until Render structure is being freed. Cycles will free all data when render finishes, optionally keeping image manager untouched. All shaders, meshes, objects will be re-allocated next time rendering happens. Cycles cession and scene will be re-created from scratch if render/ scene parameters were changed. This will also allow to keep compiled OSL shaders in memory without need to re-compile them again. P.S. Performance panel could be cleaned up a bit, not so much happy with it's vertical alignment currently but not sure how to make it look better. P.P.S. Currently the only way to free images from the device is to disable Persistent Images option and start rendering. --- intern/cycles/blender/addon/__init__.py | 6 +- intern/cycles/blender/addon/engine.py | 7 ++ intern/cycles/blender/addon/properties.py | 6 ++ intern/cycles/blender/addon/ui.py | 4 + intern/cycles/blender/blender_python.cpp | 27 ++++++ intern/cycles/blender/blender_session.cpp | 52 ++++++++++- intern/cycles/blender/blender_session.h | 2 + intern/cycles/blender/blender_sync.cpp | 2 + intern/cycles/render/scene.cpp | 88 ++++++++++++------- intern/cycles/render/scene.h | 10 ++- intern/cycles/render/session.cpp | 14 +++ intern/cycles/render/session.h | 1 + intern/cycles/util/util_progress.h | 15 ++++ .../render/intern/include/render_types.h | 4 + .../render/intern/source/external_engine.c | 9 +- .../blender/render/intern/source/pipeline.c | 3 + 16 files changed, 214 insertions(+), 36 deletions(-) diff --git a/intern/cycles/blender/addon/__init__.py b/intern/cycles/blender/addon/__init__.py index 16697c08b2b..0fad2ac5618 100644 --- a/intern/cycles/blender/addon/__init__.py +++ b/intern/cycles/blender/addon/__init__.py @@ -48,7 +48,11 @@ class CyclesRender(bpy.types.RenderEngine): # final render def update(self, data, scene): - engine.create(self, data, scene) + if not self.session: + engine.create(self, data, scene) + else: + engine.reset(self, data, scene) + engine.update(self, data, scene) def render(self, scene): diff --git a/intern/cycles/blender/addon/engine.py b/intern/cycles/blender/addon/engine.py index e4f80cb4d5d..ca5cbee9325 100644 --- a/intern/cycles/blender/addon/engine.py +++ b/intern/cycles/blender/addon/engine.py @@ -61,6 +61,13 @@ def render(engine): _cycles.render(engine.session) +def reset(engine, data, scene): + import _cycles + data = data.as_pointer() + scene = scene.as_pointer() + _cycles.reset(engine.session, data, scene) + + def update(engine, data, scene): import _cycles _cycles.sync(engine.session) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 0b8ca6e0fbe..32b07f47ba8 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -297,6 +297,12 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=False, ) + cls.use_persistent_images = BoolProperty( + name="Persistent Images", + description="Keep images loaded on the device so they could be reused by next render", + default=False, + ) + @classmethod def unregister(cls): del bpy.types.Scene.cycles diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 9cc58e65bef..d8d8c11baa6 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -216,6 +216,10 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub.label(text="Viewport:") sub.prop(cscene, "preview_start_resolution") + sub = col.column(align=True) + sub.label(text="Final Render:") + sub.prop(cscene, "use_persistent_images") + class CyclesRender_PT_layers(CyclesButtonsPanel, Panel): bl_label = "Layers" diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index 3b78651a6a1..fbc88f1056f 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -146,6 +146,32 @@ static PyObject *draw_func(PyObject *self, PyObject *args) Py_RETURN_NONE; } +static PyObject *reset_func(PyObject *self, PyObject *args) +{ + PyObject *pysession, *pydata, *pyscene; + + if(!PyArg_ParseTuple(args, "OOO", &pysession, &pydata, &pyscene)) + return NULL; + + BlenderSession *session = (BlenderSession*)PyLong_AsVoidPtr(pysession); + + PointerRNA dataptr; + RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pydata), &dataptr); + BL::BlendData b_data(dataptr); + + PointerRNA sceneptr; + RNA_id_pointer_create((ID*)PyLong_AsVoidPtr(pyscene), &sceneptr); + BL::Scene b_scene(sceneptr); + + Py_BEGIN_ALLOW_THREADS + + session->reset_session(b_data, b_scene); + + Py_END_ALLOW_THREADS + + Py_RETURN_NONE; +} + static PyObject *sync_func(PyObject *self, PyObject *value) { Py_BEGIN_ALLOW_THREADS @@ -352,6 +378,7 @@ static PyMethodDef methods[] = { {"render", render_func, METH_O, ""}, {"draw", draw_func, METH_VARARGS, ""}, {"sync", sync_func, METH_O, ""}, + {"reset", reset_func, METH_VARARGS, ""}, #ifdef WITH_OSL {"osl_update_node", osl_update_node_func, METH_VARARGS, ""}, {"osl_compile", osl_compile_func, METH_VARARGS, ""}, diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index 01bd5f013e3..fcc3d89f5d8 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -109,9 +109,50 @@ void BlenderSession::create_session() session->reset(buffer_params, session_params.samples); } +void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_) +{ + b_data = b_data_; + b_scene = b_scene_; + + SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); + SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); + + if(scene->params.modified(scene_params) || + session->params.modified(session_params)) + { + /* if scene or session parameters changed, it's easier to simply re-create + * them rather than trying to distinguish which settings need to be updated + */ + + delete session; + + create_session(); + + return; + } + + session->progress.reset(); + scene->reset(); + + /* peak memory usage should show current render peak, not peak for all renders + * made by this render session + */ + session->stats.mem_peak = session->stats.mem_used; + + /* sync object should be re-created */ + sync = new BlenderSync(b_engine, b_data, b_scene, scene, !background, session->progress); + sync->sync_data(b_v3d, b_engine.camera_override()); + sync->sync_camera(b_engine.camera_override(), width, height); + + BufferParams buffer_params = BlenderSync::get_buffer_params(b_scene, PointerRNA_NULL, PointerRNA_NULL, scene->camera, width, height); + session->reset(buffer_params, session_params.samples); +} + void BlenderSession::free_session() { - delete sync; + if(sync) + delete sync; + delete session; } @@ -304,6 +345,15 @@ void BlenderSession::render() /* clear callback */ session->write_render_tile_cb = NULL; session->update_render_tile_cb = NULL; + + /* free all memory used (host and device), so we wouldn't leave render + * engine with extra memory allocated + */ + + session->device_free(); + + delete sync; + sync = NULL; } void BlenderSession::do_write_update_render_result(BL::RenderResult b_rr, BL::RenderLayer b_rlay, RenderTile& rtile, bool do_update_only) diff --git a/intern/cycles/blender/blender_session.h b/intern/cycles/blender/blender_session.h index d52e0103bbf..7f3973ae873 100644 --- a/intern/cycles/blender/blender_session.h +++ b/intern/cycles/blender/blender_session.h @@ -46,6 +46,8 @@ public: void create_session(); void free_session(); + void reset_session(BL::BlendData b_data, BL::Scene b_scene); + /* offline render */ void render(); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index 024cb1685d0..eacfbdadba0 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -294,6 +294,8 @@ SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background) params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits"); params.use_bvh_cache = (background)? RNA_boolean_get(&cscene, "use_cache"): false; + params.persistent_images = (background)? RNA_boolean_get(&cscene, "use_persistent_images"): false; + return params; } diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 15031b9500c..a2febc31f60 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -62,33 +62,11 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_) Scene::~Scene() { - if(device) camera->device_free(device, &dscene); - delete camera; - - if(device) filter->device_free(device, &dscene); - delete filter; - - if(device) film->device_free(device, &dscene); - delete film; - - if(device) background->device_free(device, &dscene); - delete background; - - if(device) mesh_manager->device_free(device, &dscene); - delete mesh_manager; - - if(device) object_manager->device_free(device, &dscene); - delete object_manager; - - if(device) integrator->device_free(device, &dscene); - delete integrator; - - if(device) shader_manager->device_free(device, &dscene); - delete shader_manager; - - if(device) light_manager->device_free(device, &dscene); - delete light_manager; + free_memory(true); +} +void Scene::free_memory(bool final) +{ foreach(Shader *s, shaders) delete s; foreach(Mesh *m, meshes) @@ -100,11 +78,44 @@ Scene::~Scene() foreach(ParticleSystem *p, particle_systems) delete p; - if(device) image_manager->device_free(device, &dscene); - delete image_manager; + if(device) { + camera->device_free(device, &dscene); + filter->device_free(device, &dscene); + film->device_free(device, &dscene); + background->device_free(device, &dscene); + integrator->device_free(device, &dscene); - if(device) particle_system_manager->device_free(device, &dscene); - delete particle_system_manager; + object_manager->device_free(device, &dscene); + mesh_manager->device_free(device, &dscene); + shader_manager->device_free(device, &dscene); + light_manager->device_free(device, &dscene); + + particle_system_manager->device_free(device, &dscene); + + if(!params.persistent_images || final) + image_manager->device_free(device, &dscene); + } + + if(final) { + delete filter; + delete camera; + delete film; + delete background; + delete integrator; + delete object_manager; + delete mesh_manager; + delete shader_manager; + delete light_manager; + delete particle_system_manager; + delete image_manager; + } + else { + shaders.clear(); + meshes.clear(); + objects.clear(); + lights.clear(); + particle_systems.clear(); + } } void Scene::device_update(Device *device_, Progress& progress) @@ -229,5 +240,22 @@ bool Scene::need_reset() || particle_system_manager->need_update); } +void Scene::reset() +{ + shader_manager->add_default(this); + + /* ensure all objects are updated */ + camera->tag_update(); + filter->tag_update(this); + film->tag_update(this); + background->tag_update(this); + integrator->tag_update(this); +} + +void Scene::device_free() +{ + free_memory(false); +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index bd45c1c04e6..92ef692b4b9 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -120,6 +120,7 @@ public: bool use_bvh_cache; bool use_bvh_spatial_split; bool use_qbvh; + bool persistent_images; SceneParams() { @@ -139,7 +140,8 @@ public: && bvh_type == params.bvh_type && use_bvh_cache == params.use_bvh_cache && use_bvh_spatial_split == params.use_bvh_spatial_split - && use_qbvh == params.use_qbvh); } + && use_qbvh == params.use_qbvh + && persistent_images == params.persistent_images); } }; /* Scene */ @@ -198,6 +200,12 @@ public: bool need_update(); bool need_reset(); + + void reset(); + void device_free(); + +protected: + void free_memory(bool final); }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.cpp b/intern/cycles/render/session.cpp index 7f6b43c1e00..41212c2db84 100644 --- a/intern/cycles/render/session.cpp +++ b/intern/cycles/render/session.cpp @@ -842,4 +842,18 @@ bool Session::update_progressive_refine(bool cancel) return write; } +void Session::device_free() +{ + scene->device_free(); + + foreach(RenderBuffers *buffers, tile_buffers) + delete buffers; + + tile_buffers.clear(); + + /* used from background render only, so no need to + * re-create render/display buffers here + */ +} + CCL_NAMESPACE_END diff --git a/intern/cycles/render/session.h b/intern/cycles/render/session.h index 7bb0cd1ae01..cfc1502287d 100644 --- a/intern/cycles/render/session.h +++ b/intern/cycles/render/session.h @@ -130,6 +130,7 @@ public: void set_samples(int samples); void set_pause(bool pause); + void device_free(); protected: struct DelayedReset { thread_mutex mutex; diff --git a/intern/cycles/util/util_progress.h b/intern/cycles/util/util_progress.h index c97379d8776..03e25d4d132 100644 --- a/intern/cycles/util/util_progress.h +++ b/intern/cycles/util/util_progress.h @@ -68,6 +68,21 @@ public: return *this; } + void reset() + { + tile = 0; + sample = 0; + start_time = time_dt(); + total_time = 0.0f; + tile_time = 0.0f; + status = "Initializing"; + substatus = ""; + sync_status = ""; + sync_substatus = ""; + cancel = false; + cancel_message = ""; + } + /* cancel */ void set_cancel(const string& cancel_message_) { diff --git a/source/blender/render/intern/include/render_types.h b/source/blender/render/intern/include/render_types.h index 825fe2ff4d0..6ed8d6a7b6c 100644 --- a/source/blender/render/intern/include/render_types.h +++ b/source/blender/render/intern/include/render_types.h @@ -59,6 +59,7 @@ struct RenderBuckets; struct ObjectInstanceRen; struct RayObject; struct RayFace; +struct RenderEngine; struct ReportList; struct Main; @@ -183,6 +184,9 @@ struct Render ListBase parts; + /* render engine */ + struct RenderEngine *engine; + /* octree tables and variables for raytrace */ struct RayObject *raytree; struct RayFace *rayfaces; diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index e2f347c05f1..736cb5de7c3 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -349,7 +349,12 @@ int RE_engine_render(Render *re, int do_all) re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0; /* render */ - engine = RE_engine_create(type); + if(!re->engine) + re->engine = RE_engine_create(type); + + engine = re->engine; + + /* TODO: actually link to a parent which shouldn't happen */ engine->re = re; if (re->flag & R_ANIMATION) @@ -389,8 +394,6 @@ int RE_engine_render(Render *re, int do_all) render_result_free_list(&engine->fullresult, engine->fullresult.first); - RE_engine_free(engine); - if (BKE_reports_contain(re->reports, RPT_ERROR)) G.is_break = TRUE; diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index d305ed06af1..369818d37d5 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -387,6 +387,9 @@ void RE_InitRenderCB(Render *re) /* only call this while you know it will remove the link too */ void RE_FreeRender(Render *re) { + if (re->engine) + RE_engine_free(re->engine); + BLI_rw_mutex_end(&re->resultmutex); free_renderdata_tables(re); From ffbf0a1b12ae840f5fd5a21b3663743ee9beb26c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 9 Nov 2012 08:47:08 +0000 Subject: [PATCH 043/118] Cycles: no need in spin lock in memory statistics This functions are called from device code which is guaranteed not to be called simultaneously from different threads. --- intern/cycles/util/util_stats.h | 11 +---------- intern/cycles/util/util_thread.h | 3 --- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/intern/cycles/util/util_stats.h b/intern/cycles/util/util_stats.h index 405c81a1e1f..27638015f40 100644 --- a/intern/cycles/util/util_stats.h +++ b/intern/cycles/util/util_stats.h @@ -19,31 +19,22 @@ #ifndef __UTIL_STATS_H__ #define __UTIL_STATS_H__ -#include "util_thread.h" - CCL_NAMESPACE_BEGIN class Stats { public: - Stats() : lock(), mem_used(0), mem_peak(0) {} + Stats() : mem_used(0), mem_peak(0) {} void mem_alloc(size_t size) { - lock.lock(); - mem_used += size; if(mem_used > mem_peak) mem_peak = mem_used; - - lock.unlock(); } void mem_free(size_t size) { - lock.lock(); mem_used -= size; - lock.unlock(); } - spin_lock lock; size_t mem_used; size_t mem_peak; }; diff --git a/intern/cycles/util/util_thread.h b/intern/cycles/util/util_thread.h index 6d1bd0023a7..843764ca9d6 100644 --- a/intern/cycles/util/util_thread.h +++ b/intern/cycles/util/util_thread.h @@ -33,9 +33,6 @@ typedef boost::mutex thread_mutex; typedef boost::mutex::scoped_lock thread_scoped_lock; typedef boost::condition_variable thread_condition_variable; -/* use boost for spinlocks as well */ -typedef boost::detail::spinlock spin_lock; - /* own pthread based implementation, to avoid boost version conflicts with * dynamically loaded blender plugins */ From 03cc3b94c94c38767802bccac4e9384ab704065a Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 9 Nov 2012 09:11:24 +0000 Subject: [PATCH 044/118] Fisheye Equidistant Lens algorith bugfix r = lens * theta Thanks for Adriano Oliveira for reporting this and chasing down the right formula. Now fulldome works no longer need to use equisolid + a specific lens+sensor size. And happy birthday to me. And yes, that's how I celebrate it ;) --- intern/cycles/blender/addon/enums.py | 5 ++--- intern/cycles/kernel/kernel_projection.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/intern/cycles/blender/addon/enums.py b/intern/cycles/blender/addon/enums.py index a98a6aab4c4..82b48973ca1 100644 --- a/intern/cycles/blender/addon/enums.py +++ b/intern/cycles/blender/addon/enums.py @@ -57,8 +57,7 @@ aperture_types = ( panorama_types = ( ('EQUIRECTANGULAR', "Equirectangular", "Render the scene with a spherical camera, also known as Lat Long panorama"), - ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ignore the sensor dimensions"), + ('FISHEYE_EQUIDISTANT', "Fisheye Equidistant", "Ideal for fulldomes, ignore the sensor dimensions"), ('FISHEYE_EQUISOLID', "Fisheye Equisolid", - "Similar to most fisheye modern lens, takes sensor dimensions into consideration " - "(for fulldomes use it with a square sensor ratio)"), + "Similar to most fisheye modern lens, takes sensor dimensions into consideration"), ) diff --git a/intern/cycles/kernel/kernel_projection.h b/intern/cycles/kernel/kernel_projection.h index 64747bcb42e..6516b9e4d82 100644 --- a/intern/cycles/kernel/kernel_projection.h +++ b/intern/cycles/kernel/kernel_projection.h @@ -98,7 +98,7 @@ __device float3 fisheye_to_direction(float u, float v, float fov) return make_float3(0.0f, 0.0f, 0.0f); float phi = acosf((r != 0.0f)? u/r: 0.0f); - float theta = asinf(r) * (fov / M_PI_F); + float theta = r * fov * 0.5f; if(v < 0.0f) phi = -phi; From 2bb174cfa40af730f16785884e0f74e58b627065 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 09:33:28 +0000 Subject: [PATCH 045/118] style cleanup: indentation --- source/blender/avi/intern/avi.c | 14 ++++---- source/blender/blenkernel/BKE_mesh.h | 4 +-- source/blender/blenkernel/BKE_multires.h | 2 +- .../blender/blenkernel/intern/DerivedMesh.c | 4 +-- source/blender/blenkernel/intern/bmfont.c | 13 +++---- source/blender/blenkernel/intern/curve.c | 14 ++++---- source/blender/blenkernel/intern/image.c | 22 ++++++------ .../blender/blenkernel/intern/mask_evaluate.c | 2 +- source/blender/blenkernel/intern/mesh.c | 2 +- source/blender/blenkernel/intern/multires.c | 2 +- .../blender/blenkernel/intern/seqmodifier.c | 4 +-- source/blender/blenkernel/intern/sound.c | 20 +++++------ source/blender/blenlib/BLI_math_matrix.h | 18 ++++++---- source/blender/blenlib/intern/voronoi.c | 6 ++-- source/blender/bmesh/intern/bmesh_construct.c | 8 ++--- .../bmesh/intern/bmesh_decimate_unsubdivide.c | 6 ++-- source/blender/bmesh/operators/bmo_hull.c | 18 +++++----- .../operations/COM_TrackPositionOperation.cpp | 2 +- .../blender/editors/animation/anim_filter.c | 4 +-- .../editors/armature/editarmature_sketch.c | 18 +++++----- source/blender/editors/curve/editcurve.c | 4 +-- source/blender/editors/mesh/editmesh_tools.c | 12 +++---- .../editors/sculpt_paint/paint_stroke.c | 2 +- .../editors/sculpt_paint/paint_vertex.c | 8 +++-- source/blender/editors/space_clip/clip_ops.c | 2 +- .../blender/editors/space_clip/clip_utils.c | 22 ++++++------ source/blender/editors/space_node/node_edit.c | 2 +- .../editors/space_outliner/outliner_draw.c | 2 +- .../editors/transform/transform_conversions.c | 5 +-- source/blender/imbuf/intern/dds/FlipDXT.cpp | 6 ++-- source/blender/imbuf/intern/divers.c | 16 ++++----- source/blender/imbuf/intern/jpeg.c | 14 ++++---- .../imbuf/intern/openexr/openexr_stub.cpp | 34 +++++++++---------- source/blender/imbuf/intern/rectop.c | 2 +- source/blender/imbuf/intern/scaling.c | 14 ++++---- source/blender/makesdna/intern/makesdna.c | 2 +- source/blender/makesrna/intern/makesrna.c | 10 +++--- source/blender/makesrna/intern/rna_brush.c | 4 +-- source/blender/makesrna/intern/rna_mesh.c | 2 +- source/blender/makesrna/intern/rna_nodetree.c | 2 +- source/blender/modifiers/intern/MOD_explode.c | 3 +- source/blender/modifiers/intern/MOD_skin.c | 14 ++++---- .../blender/modifiers/intern/MOD_solidify.c | 7 ++-- source/blender/python/generic/py_capi_utils.c | 2 +- 44 files changed, 194 insertions(+), 180 deletions(-) diff --git a/source/blender/avi/intern/avi.c b/source/blender/avi/intern/avi.c index e1732b0caae..d6301b723a7 100644 --- a/source/blender/avi/intern/avi.c +++ b/source/blender/avi/intern/avi.c @@ -665,13 +665,13 @@ AviError AVI_open_movie(const char *name, AviMovie *movie) } } -/* Some AVI's have offset entries in absolute coordinates - * instead of an offset from the movie beginning... this is... - * wacky, but we need to handle it. The wacky offset always - * starts at movi_offset it seems... so we'll check that. - * Note the the offset needs an extra 4 bytes for some - * undetermined reason */ - + /* Some AVI's have offset entries in absolute coordinates + * instead of an offset from the movie beginning... this is... + * wacky, but we need to handle it. The wacky offset always + * starts at movi_offset it seems... so we'll check that. + * Note the the offset needs an extra 4 bytes for some + * undetermined reason */ + if (movie->entries[0].Offset == movie->movi_offset) movie->read_offset = 4; } diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 2f889084d0e..e53d0efffbd 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -283,9 +283,9 @@ typedef struct IndexNode { void create_vert_poly_map(MeshElemMap **map, int **mem, const struct MPoly *mface, const struct MLoop *mloop, int totvert, int totface, int totloop); - + void create_vert_edge_map(MeshElemMap **map, int **mem, - const struct MEdge *medge, int totvert, int totedge); + const struct MEdge *medge, int totvert, int totedge); /* vertex level transformations & checks (no derived mesh) */ diff --git a/source/blender/blenkernel/BKE_multires.h b/source/blender/blenkernel/BKE_multires.h index 8fa20eb2cc2..bee2c374f27 100644 --- a/source/blender/blenkernel/BKE_multires.h +++ b/source/blender/blenkernel/BKE_multires.h @@ -48,7 +48,7 @@ struct Scene; void multires_customdata_delete(struct Mesh *me); void multires_set_tot_level(struct Object *ob, - struct MultiresModifierData *mmd, int lvl); + struct MultiresModifierData *mmd, int lvl); void multires_mark_as_modified(struct Object *ob, enum MultiresModifiedFlags flags); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index fd92b7b5d69..cca425a63d8 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -1680,8 +1680,8 @@ static void mesh_calc_modifiers(Scene *scene, Object *ob, float (*inputVertexCos nextmask &= ~CD_MASK_ORCO; DM_set_only_copy(orcodm, nextmask | CD_MASK_ORIGINDEX | - (mti->requiredDataMask ? - mti->requiredDataMask(ob, md) : 0)); + (mti->requiredDataMask ? + mti->requiredDataMask(ob, md) : 0)); ndm = mti->applyModifier(md, ob, orcodm, app_flags & ~MOD_APPLY_USECACHE); if (ndm) { diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c index df7fb2c1807..0495e729937 100644 --- a/source/blender/blenkernel/intern/bmfont.c +++ b/source/blender/blenkernel/intern/bmfont.c @@ -247,12 +247,13 @@ int locateGlyph(bmFont *bmfont, unsigned short unicode) return(current); } -void matrixGlyph(ImBuf * ibuf, unsigned short unicode, - float *centerx, float *centery, - float *sizex, float *sizey, - float *transx, float *transy, - float *movex, float *movey, - float *advance) +void matrixGlyph( + ImBuf * ibuf, unsigned short unicode, + float *centerx, float *centery, + float *sizex, float *sizey, + float *transx, float *transy, + float *movex, float *movey, + float *advance) { int index; bmFont *bmfont; diff --git a/source/blender/blenkernel/intern/curve.c b/source/blender/blenkernel/intern/curve.c index 67aaaceaa38..f2cd695d64a 100644 --- a/source/blender/blenkernel/intern/curve.c +++ b/source/blender/blenkernel/intern/curve.c @@ -1117,12 +1117,12 @@ void BKE_nurb_makeCurve(Nurb *nu, float *coord_array, float *tilt_array, float * sumdiv += *fp; } if (sumdiv != 0.0f) if (sumdiv < 0.999f || sumdiv > 1.001f) { - /* is normalizing needed? */ - fp = sum; - for (i = istart; i <= iend; i++, fp++) { - *fp /= sumdiv; - } + /* is normalizing needed? */ + fp = sum; + for (i = istart; i <= iend; i++, fp++) { + *fp /= sumdiv; } + } /* one! (1.0) real point */ fp = sum; @@ -2481,8 +2481,8 @@ void BKE_curve_bevelList_make(Object *ob) else bevp2 = bevp1 + 1; - inp = (bevp1->vec[0] - bevp0->vec[0]) * (bevp0->vec[1] - bevp2->vec[1]) + - (bevp0->vec[1] - bevp1->vec[1]) * (bevp0->vec[0] - bevp2->vec[0]); + inp = ((bevp1->vec[0] - bevp0->vec[0]) * (bevp0->vec[1] - bevp2->vec[1]) + + (bevp0->vec[1] - bevp1->vec[1]) * (bevp0->vec[0] - bevp2->vec[0])); if (inp > 0.0f) sd->dir = 1; diff --git a/source/blender/blenkernel/intern/image.c b/source/blender/blenkernel/intern/image.c index ef751ce3493..55d37c91859 100644 --- a/source/blender/blenkernel/intern/image.c +++ b/source/blender/blenkernel/intern/image.c @@ -1561,7 +1561,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* also a little of space to the background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and draw the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1578,7 +1578,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* and space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.note); @@ -1594,7 +1594,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* and space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.date); @@ -1610,7 +1610,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* and space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + 0, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.rendertime); @@ -1625,7 +1625,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1641,7 +1641,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1656,7 +1656,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1671,7 +1671,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.camera); @@ -1684,7 +1684,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.cameralens); } @@ -1697,7 +1697,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); /* and pad the text. */ BLF_position(mono, x, y + y_ofs, 0.0); @@ -1713,7 +1713,7 @@ void BKE_stamp_buf(Scene *scene, Object *camera, unsigned char *rect, float *rec /* extra space for background. */ buf_rectfill_area(rect, rectf, width, height, scene->r.bg_stamp, display, - x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); + x - BUFF_MARGIN_X, y - BUFF_MARGIN_Y, x + w + BUFF_MARGIN_X, y + h + BUFF_MARGIN_Y); BLF_position(mono, x, y + y_ofs, 0.0); BLF_draw_buffer(mono, stamp_data.strip); diff --git a/source/blender/blenkernel/intern/mask_evaluate.c b/source/blender/blenkernel/intern/mask_evaluate.c index e67df9c6419..7d89678d36f 100644 --- a/source/blender/blenkernel/intern/mask_evaluate.c +++ b/source/blender/blenkernel/intern/mask_evaluate.c @@ -245,7 +245,7 @@ static void feather_bucket_add_edge(FeatherEdgesBucket *bucket, int start, int e } else { bucket->segments = MEM_reallocN(bucket->segments, - (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments)); + (alloc_delta + bucket->tot_segment) * sizeof(*bucket->segments)); } bucket->alloc_segment += alloc_delta; diff --git a/source/blender/blenkernel/intern/mesh.c b/source/blender/blenkernel/intern/mesh.c index 6d44473583f..068059dc29a 100644 --- a/source/blender/blenkernel/intern/mesh.c +++ b/source/blender/blenkernel/intern/mesh.c @@ -2388,7 +2388,7 @@ void create_vert_poly_map(MeshElemMap **map, int **mem, * of edges that use that vertex as an endpoint. The lists are allocated * from one memory pool. */ void create_vert_edge_map(MeshElemMap **map, int **mem, - const MEdge *medge, int totvert, int totedge) + const MEdge *medge, int totvert, int totedge) { int i, *indices; diff --git a/source/blender/blenkernel/intern/multires.c b/source/blender/blenkernel/intern/multires.c index 66f2ff12258..c737dccc5d2 100644 --- a/source/blender/blenkernel/intern/multires.c +++ b/source/blender/blenkernel/intern/multires.c @@ -984,7 +984,7 @@ static void grid_tangent(const CCGKey *key, int x, int y, int axis, CCGElem *gri /* Construct 3x3 tangent-space matrix in 'mat' */ static void grid_tangent_matrix(float mat[3][3], const CCGKey *key, - int x, int y, CCGElem *grid) + int x, int y, CCGElem *grid) { grid_tangent(key, x, y, 0, grid, mat[0]); normalize_v3(mat[0]); diff --git a/source/blender/blenkernel/intern/seqmodifier.c b/source/blender/blenkernel/intern/seqmodifier.c index b0dcad64722..609724e802f 100644 --- a/source/blender/blenkernel/intern/seqmodifier.c +++ b/source/blender/blenkernel/intern/seqmodifier.c @@ -349,9 +349,9 @@ static void hue_correct_apply_threaded(int width, int height, unsigned char *rec hsv_to_rgb(hsv[0], hsv[1], hsv[2], result, result + 1, result + 2); if (mask_rect_float) - copy_v3_v3(mask, mask_rect_float + pixel_index); + copy_v3_v3(mask, mask_rect_float + pixel_index); else if (mask_rect) - rgb_uchar_to_float(mask, mask_rect + pixel_index); + rgb_uchar_to_float(mask, mask_rect + pixel_index); result[0] = pixel[0] * (1.0f - mask[0]) + result[0] * mask[0]; result[1] = pixel[1] * (1.0f - mask[1]) + result[1] * mask[1]; diff --git a/source/blender/blenkernel/intern/sound.c b/source/blender/blenkernel/intern/sound.c index aad205bb5bf..af9d21d8cbc 100644 --- a/source/blender/blenkernel/intern/sound.c +++ b/source/blender/blenkernel/intern/sound.c @@ -353,17 +353,17 @@ void sound_load(struct Main *bmain, bSound *sound) } // XXX unused currently #if 0 - break; + break; + } + case SOUND_TYPE_BUFFER: + if (sound->child_sound && sound->child_sound->handle) + sound->handle = AUD_bufferSound(sound->child_sound->handle); + break; + case SOUND_TYPE_LIMITER: + if (sound->child_sound && sound->child_sound->handle) + sound->handle = AUD_limitSound(sound->child_sound, sound->start, sound->end); + break; } - case SOUND_TYPE_BUFFER: - if (sound->child_sound && sound->child_sound->handle) - sound->handle = AUD_bufferSound(sound->child_sound->handle); - break; - case SOUND_TYPE_LIMITER: - if (sound->child_sound && sound->child_sound->handle) - sound->handle = AUD_limitSound(sound->child_sound, sound->start, sound->end); - break; -} #endif if (sound->flags & SOUND_FLAGS_MONO) { void *handle = AUD_monoSound(sound->handle); diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 0783a7981ea..f51bd1cf840 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -36,14 +36,18 @@ extern "C" { /********************************* Init **************************************/ -#define MAT4_UNITY {{ 1.0, 0.0, 0.0, 0.0}, \ - { 0.0, 1.0, 0.0, 0.0}, \ - { 0.0, 0.0, 1.0, 0.0}, \ - { 0.0, 0.0, 0.0, 1.0}} +#define MAT4_UNITY { \ + { 1.0, 0.0, 0.0, 0.0}, \ + { 0.0, 1.0, 0.0, 0.0}, \ + { 0.0, 0.0, 1.0, 0.0}, \ + { 0.0, 0.0, 0.0, 1.0} \ +} -#define MAT3_UNITY {{ 1.0, 0.0, 0.0}, \ - { 0.0, 1.0, 0.0}, \ - { 0.0, 0.0, 1.0}} +#define MAT3_UNITY { \ + { 1.0, 0.0, 0.0}, \ + { 0.0, 1.0, 0.0}, \ + { 0.0, 0.0, 1.0} \ +} void zero_m3(float R[3][3]); void zero_m4(float R[4][4]); diff --git a/source/blender/blenlib/intern/voronoi.c b/source/blender/blenlib/intern/voronoi.c index 0d411038b3e..601b07c9a5d 100644 --- a/source/blender/blenlib/intern/voronoi.c +++ b/source/blender/blenlib/intern/voronoi.c @@ -609,9 +609,9 @@ static int voronoi_getNextSideCoord(ListBase *edges, float coord[2], int dim, in static void voronoi_createBoundaryEdges(ListBase *edges, int width, int height) { const float corners[4][2] = {{width - 1, 0.0f}, - {width - 1, height - 1}, - {0.0f, height - 1}, - {0.0f, 0.0f}}; + {width - 1, height - 1}, + {0.0f, height - 1}, + {0.0f, 0.0f}}; int i, dim = 0, dir = 1; float coord[2] = {0.0f, 0.0f}; diff --git a/source/blender/bmesh/intern/bmesh_construct.c b/source/blender/bmesh/intern/bmesh_construct.c index d86a26e19ac..eae78c6cc25 100644 --- a/source/blender/bmesh/intern/bmesh_construct.c +++ b/source/blender/bmesh/intern/bmesh_construct.c @@ -397,11 +397,11 @@ BMFace *BM_face_create_ngon_vcloud(BMesh *bm, BMVert **vert_arr, int totv, int n /* more of a weight then a distance */ far_cross_dist = (/* first we want to have a value close to zero mapped to 1 */ - 1.0f - fabsf(dot_v3v3(far_vec, far_cross_vec)) * + 1.0f - fabsf(dot_v3v3(far_vec, far_cross_vec)) * - /* second we multiply by the distance - * so points close to the center are not preferred */ - far_cross_dist); + /* second we multiply by the distance + * so points close to the center are not preferred */ + far_cross_dist); if (far_cross_dist > far_cross_best || far_cross == NULL) { far_cross = vert_arr[i]->co; diff --git a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c b/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c index 68c0652d2c4..1ec13010d80 100644 --- a/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c +++ b/source/blender/bmesh/intern/bmesh_decimate_unsubdivide.c @@ -247,9 +247,9 @@ void BM_mesh_decimate_unsubdivide_ex(BMesh *bm, const int iterations, const int #ifdef USE_WALKER /* Walk over selected elements starting at active */ BMW_init(&walker, bm, BMW_CONNECTED_VERTEX, - ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP, - BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */ - BMW_NIL_LAY); + ELE_VERT_TAG, BMW_MASK_NOP, BMW_MASK_NOP, + BMW_FLAG_NOP, /* don't use BMW_FLAG_TEST_HIDDEN here since we want to desel all */ + BMW_NIL_LAY); BLI_assert(walker.order == BMW_BREADTH_FIRST); for (v = BMW_begin(&walker, v_first); v != NULL; v = BMW_step(&walker)) { diff --git a/source/blender/bmesh/operators/bmo_hull.c b/source/blender/bmesh/operators/bmo_hull.c index 013b6183f84..b9c9398fbfa 100644 --- a/source/blender/bmesh/operators/bmo_hull.c +++ b/source/blender/bmesh/operators/bmo_hull.c @@ -426,12 +426,12 @@ static int hull_input_vert_count(BMesh *bm, BMOperator *op) } static BMVert **hull_input_verts_copy(BMesh *bm, BMOperator *op, - const int num_input_verts) + const int num_input_verts) { BMOIter oiter; BMVert *v; BMVert **input_verts = MEM_callocN(sizeof(*input_verts) * - num_input_verts, AT); + num_input_verts, AT); int i = 0; BMO_ITER (v, &oiter, bm, op, "input", BM_VERT) { @@ -442,7 +442,7 @@ static BMVert **hull_input_verts_copy(BMesh *bm, BMOperator *op, } static float (*hull_verts_for_bullet(BMVert **input_verts, - const int num_input_verts))[3] + const int num_input_verts))[3] { float (*coords)[3] = MEM_callocN(sizeof(*coords) * num_input_verts, AT); int i; @@ -455,12 +455,12 @@ static float (*hull_verts_for_bullet(BMVert **input_verts, } static BMVert **hull_verts_from_bullet(plConvexHull hull, - BMVert **input_verts, - const int num_input_verts) + BMVert **input_verts, + const int num_input_verts) { const int num_verts = plConvexHullNumVertices(hull); BMVert **hull_verts = MEM_mallocN(sizeof(*hull_verts) * - num_verts, AT); + num_verts, AT); int i; for (i = 0; i < num_verts; i++) { @@ -479,8 +479,8 @@ static BMVert **hull_verts_from_bullet(plConvexHull hull, } static void hull_from_bullet(BMesh *bm, BMOperator *op, - GHash *hull_triangles, - BLI_mempool *pool) + GHash *hull_triangles, + BLI_mempool *pool) { int *fvi = NULL; BLI_array_declare(fvi); @@ -523,7 +523,7 @@ static void hull_from_bullet(BMesh *bm, BMOperator *op, fv[2] = hull_verts[fvi[j]]; hull_add_triangle(bm, hull_triangles, pool, - fv[0], fv[1], fv[2]); + fv[0], fv[1], fv[2]); } } } diff --git a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp index d41d1c128da..8b5288321c1 100644 --- a/source/blender/compositor/operations/COM_TrackPositionOperation.cpp +++ b/source/blender/compositor/operations/COM_TrackPositionOperation.cpp @@ -92,7 +92,7 @@ void TrackPositionOperation::initExecution() } else if (this->m_position == POSITION_RELATIVE_FRAME) { int relative_clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(this->m_movieClip, - this->m_relativeFrame); + this->m_relativeFrame); marker = BKE_tracking_marker_get(track, relative_clip_framenr); copy_v2_v2(this->m_relativePos, marker->pos); diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 425ee899fe7..5e215fbd6a2 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -175,7 +175,7 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction) return 1; case SACTCONT_MASK: /* Mask */ /* XXX review how this mode is handled... */ -{ + { /* TODO, other methods to get the mask */ // Sequence *seq = BKE_sequencer_active_get(ac->scene); //MovieClip *clip = ac->scene->clip; @@ -189,7 +189,7 @@ static short actedit_get_context(bAnimContext *ac, SpaceAction *saction) ac->mode = saction->mode; return 1; -} + } case SACTCONT_DOPESHEET: /* DopeSheet */ /* update scene-pointer (no need to check for pinning yet, as not implemented) */ saction->ads.source = (ID *)ac->scene; diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index da8fc328343..f9cf4a29269 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -2104,15 +2104,15 @@ static void sk_drawSketch(Scene *scene, View3D *UNUSED(v3d), SK_Sketch *sketch, if (sketch->depth_peels.first != NULL) { float colors[8][3] = { - {1, 0, 0}, - {0, 1, 0}, - {0, 0, 1}, - {1, 1, 0}, - {1, 0, 1}, - {0, 1, 1}, - {1, 1, 1}, - {0, 0, 0} - }; + {1, 0, 0}, + {0, 1, 0}, + {0, 0, 1}, + {1, 1, 0}, + {1, 0, 1}, + {0, 1, 1}, + {1, 1, 1}, + {0, 0, 0} + }; DepthPeel *p; GLUquadric *quad = gluNewQuadric(); gluQuadricNormals(quad, GLU_SMOOTH); diff --git a/source/blender/editors/curve/editcurve.c b/source/blender/editors/curve/editcurve.c index 485d73974cd..957dcfbd848 100644 --- a/source/blender/editors/curve/editcurve.c +++ b/source/blender/editors/curve/editcurve.c @@ -6465,8 +6465,8 @@ Nurb *add_nurbs_primitive(bContext *C, Object *obedit, float mat[4][4], int type fac = (float)b - 1.5f; bp->vec[1] += fac * grid; if (a == 1 || a == 2) if (b == 1 || b == 2) { - bp->vec[2] += grid; - } + bp->vec[2] += grid; + } mul_m4_v3(mat, bp->vec); bp->vec[3] = 1.0; bp++; diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 80057ba04be..20b52f50b2d 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -1736,12 +1736,12 @@ void MESH_OT_vertices_smooth_laplacian(wmOperatorType *ot) /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; - RNA_def_int(ot->srna, "repeat", 1, 1, 200, - "Number of iterations to smooth the mesh", "", 1, 200); - RNA_def_float(ot->srna, "lambda", 0.00005f, 0.0000001f, 1000.0f, - "Lambda factor", "", 0.0000001f, 1000.0f); - RNA_def_float(ot->srna, "lambda_border", 0.00005f, 0.0000001f, 1000.0f, - "Lambda factor in border", "", 0.0000001f, 1000.0f); + RNA_def_int(ot->srna, "repeat", 1, 1, 200, + "Number of iterations to smooth the mesh", "", 1, 200); + RNA_def_float(ot->srna, "lambda", 0.00005f, 0.0000001f, 1000.0f, + "Lambda factor", "", 0.0000001f, 1000.0f); + RNA_def_float(ot->srna, "lambda_border", 0.00005f, 0.0000001f, 1000.0f, + "Lambda factor in border", "", 0.0000001f, 1000.0f); RNA_def_boolean(ot->srna, "use_x", 1, "Smooth X Axis", "Smooth object along X axis"); RNA_def_boolean(ot->srna, "use_y", 1, "Smooth Y Axis", "Smooth object along Y axis"); RNA_def_boolean(ot->srna, "use_z", 1, "Smooth Z Axis", "Smooth object along Z axis"); diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c index 6396a0c2cbc..9ebeb61a7bb 100644 --- a/source/blender/editors/sculpt_paint/paint_stroke.c +++ b/source/blender/editors/sculpt_paint/paint_stroke.c @@ -195,7 +195,7 @@ static void paint_brush_stroke_add_step(bContext *C, wmOperator *op, wmEvent *ev /* Returns zero if no sculpt changes should be made, non-zero otherwise */ static int paint_smooth_stroke(PaintStroke *stroke, float output[2], - const PaintSample *sample) + const PaintSample *sample) { output[0] = sample->mouse[0]; output[1] = sample->mouse[1]; diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c index 56d46a22e10..94b00101dc2 100644 --- a/source/blender/editors/sculpt_paint/paint_vertex.c +++ b/source/blender/editors/sculpt_paint/paint_vertex.c @@ -125,9 +125,11 @@ static void update_tessface_data(Object *ob, Mesh *me) if (!me->mcol || !me->mface) { /* should always be true */ /* XXX Why this clearing? tessface_calc will reset it anyway! */ -/* if (me->mcol) {*/ -/* memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface);*/ -/* }*/ +#if 0 + if (me->mcol) { + memset(me->mcol, 255, 4 * sizeof(MCol) * me->totface); + } +#endif /* create tessfaces because they will be used for drawing & fast updates */ BKE_mesh_tessface_calc(me); /* does own call to update pointers */ diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 9ec2ad82bef..4e53f34359e 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -1065,7 +1065,7 @@ static int clip_rebuild_proxy_exec(bContext *C, wmOperator *UNUSED(op)) if (clip->anim) { pj->index_context = IMB_anim_index_rebuild_context(clip->anim, clip->proxy.build_tc_flag, - clip->proxy.build_size_flag, clip->proxy.quality); + clip->proxy.build_size_flag, clip->proxy.quality); } WM_jobs_customdata_set(wm_job, pj, proxy_freejob); diff --git a/source/blender/editors/space_clip/clip_utils.c b/source/blender/editors/space_clip/clip_utils.c index ddc624b4cdf..d7a9b1c0cb6 100644 --- a/source/blender/editors/space_clip/clip_utils.c +++ b/source/blender/editors/space_clip/clip_utils.c @@ -63,11 +63,12 @@ #include "clip_intern.h" // own include -void clip_graph_tracking_values_iterate_track(SpaceClip *sc, MovieTrackingTrack *track, void *userdata, - void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, - int scene_framenr, float val), - void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), - void (*segment_end)(void *userdata)) +void clip_graph_tracking_values_iterate_track( + SpaceClip *sc, MovieTrackingTrack *track, void *userdata, + void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, int coord, + int scene_framenr, float val), + void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), + void (*segment_end)(void *userdata)) { MovieClip *clip = ED_space_clip_get_clip(sc); int width, height, coord; @@ -122,11 +123,12 @@ void clip_graph_tracking_values_iterate_track(SpaceClip *sc, MovieTrackingTrack } } -void clip_graph_tracking_values_iterate(SpaceClip *sc, int selected_only, int include_hidden, void *userdata, - void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, - int coord, int scene_framenr, float val), - void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), - void (*segment_end)(void *userdata)) +void clip_graph_tracking_values_iterate( + SpaceClip *sc, int selected_only, int include_hidden, void *userdata, + void (*func)(void *userdata, MovieTrackingTrack *track, MovieTrackingMarker *marker, + int coord, int scene_framenr, float val), + void (*segment_start)(void *userdata, MovieTrackingTrack *track, int coord), + void (*segment_end)(void *userdata)) { MovieClip *clip = ED_space_clip_get_clip(sc); MovieTracking *tracking = &clip->tracking; diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index 5dd005e9ddf..62e941d3148 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -2226,7 +2226,7 @@ static int node_shader_script_update_exec(bContext *C, wmOperator *op) data.text = CTX_data_pointer_get_type(C, "edit_text", &RNA_Text).data; if (data.text) { - bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); + bNodeTreeType *ntreetype = ntreeGetType(NTREE_SHADER); if (ntreetype && ntreetype->foreach_nodetree) ntreetype->foreach_nodetree(bmain, &data, node_shader_script_update_text); diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index c4afe32e85f..2c40e0e656d 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -1042,7 +1042,7 @@ static void tselem_draw_icon(uiBlock *block, int xmax, float x, float y, TreeSto /* Default */ case eModifierType_None: case eModifierType_ShapeKey: - case NUM_MODIFIER_TYPES: + case NUM_MODIFIER_TYPES: UI_icon_draw(x, y, ICON_DOT); break; } break; diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index 8e268e46696..9bbd3f59cbf 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -5037,9 +5037,10 @@ static void special_aftertrans_update__mask(bContext *C, TransInfo *t) if (t->scene->nodetree) { /* tracks can be used for stabilization nodes, * flush update for such nodes */ - //if (nodeUpdateID(t->scene->nodetree, &mask->id)) { + //if (nodeUpdateID(t->scene->nodetree, &mask->id)) + { WM_event_add_notifier(C, NC_MASK | ND_DATA, &mask->id); - //} + } } /* TODO - dont key all masks... */ diff --git a/source/blender/imbuf/intern/dds/FlipDXT.cpp b/source/blender/imbuf/intern/dds/FlipDXT.cpp index ee7a0ebb2f7..05821b27ca6 100644 --- a/source/blender/imbuf/intern/dds/FlipDXT.cpp +++ b/source/blender/imbuf/intern/dds/FlipDXT.cpp @@ -140,10 +140,10 @@ static void FlipDXT5BlockFull(uint8_t *block) unsigned int line_2_3 = block[5] + 256 * (block[6] + 256 * block[7]); // swap lines 0 and 1 in line_0_1. unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | - ((line_0_1 & 0xfff000) >> 12); + ((line_0_1 & 0xfff000) >> 12); // swap lines 2 and 3 in line_2_3. unsigned int line_3_2 = ((line_2_3 & 0x000fff) << 12) | - ((line_2_3 & 0xfff000) >> 12); + ((line_2_3 & 0xfff000) >> 12); block[2] = line_3_2 & 0xff; block[3] = (line_3_2 & 0xff00) >> 8; @@ -162,7 +162,7 @@ static void FlipDXT5BlockHalf(uint8_t *block) // See layout above. unsigned int line_0_1 = block[2] + 256 * (block[3] + 256 * block[4]); unsigned int line_1_0 = ((line_0_1 & 0x000fff) << 12) | - ((line_0_1 & 0xfff000) >> 12); + ((line_0_1 & 0xfff000) >> 12); block[2] = line_1_0 & 0xff; block[3] = (line_1_0 & 0xff00) >> 8; block[4] = (line_1_0 & 0xff0000) >> 8; diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 55c1b02e90b..8d289de9970 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -583,23 +583,23 @@ void IMB_partial_rect_from_float(ImBuf *ibuf, float *buffer, int x, int y, int w if (is_data) { /* exception for non-color data, just copy float */ IMB_buffer_float_from_float(buffer, rect_float, - ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, 0, - w, h, w, ibuf->x); + ibuf->channels, IB_PROFILE_LINEAR_RGB, IB_PROFILE_LINEAR_RGB, 0, + w, h, w, ibuf->x); /* and do color space conversion to byte */ IMB_buffer_byte_from_float(rect_byte, rect_float, - 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, - w, h, ibuf->x, w); + 4, ibuf->dither, IB_PROFILE_SRGB, profile_from, predivide, + w, h, ibuf->x, w); } else { IMB_buffer_float_from_float(buffer, rect_float, - ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, - w, h, w, ibuf->x); + ibuf->channels, IB_PROFILE_SRGB, profile_from, predivide, + w, h, w, ibuf->x); /* XXX: need to convert to image buffer's rect space */ IMB_buffer_byte_from_float(rect_byte, buffer, - 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, - w, h, ibuf->x, w); + 4, ibuf->dither, IB_PROFILE_SRGB, IB_PROFILE_SRGB, 0, + w, h, ibuf->x, w); } /* ensure user flag is reset */ diff --git a/source/blender/imbuf/intern/jpeg.c b/source/blender/imbuf/intern/jpeg.c index 61275a8937c..d96a01d7093 100644 --- a/source/blender/imbuf/intern/jpeg.c +++ b/source/blender/imbuf/intern/jpeg.c @@ -235,19 +235,19 @@ static void memory_source(j_decompress_ptr cinfo, unsigned char *buffer, size_t */ #define INPUT_BYTE(cinfo, V, action) \ MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = GETJOCTET(*next_input_byte++); ) + bytes_in_buffer--; \ + V = GETJOCTET(*next_input_byte++); ) /* As above, but read two bytes interpreted as an unsigned 16-bit integer. * V should be declared unsigned int or perhaps INT32. */ #define INPUT_2BYTES(cinfo, V, action) \ MAKESTMT(MAKE_BYTE_AVAIL(cinfo,action); \ - bytes_in_buffer--; \ - V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ - MAKE_BYTE_AVAIL(cinfo, action); \ - bytes_in_buffer--; \ - V += GETJOCTET(*next_input_byte++); ) + bytes_in_buffer--; \ + V = ((unsigned int) GETJOCTET(*next_input_byte++)) << 8; \ + MAKE_BYTE_AVAIL(cinfo, action); \ + bytes_in_buffer--; \ + V += GETJOCTET(*next_input_byte++); ) static boolean diff --git a/source/blender/imbuf/intern/openexr/openexr_stub.cpp b/source/blender/imbuf/intern/openexr/openexr_stub.cpp index 7262656d4e8..21fa878c08a 100644 --- a/source/blender/imbuf/intern/openexr/openexr_stub.cpp +++ b/source/blender/imbuf/intern/openexr/openexr_stub.cpp @@ -33,25 +33,25 @@ #include "openexr_multi.h" -void * IMB_exr_get_handle (void) {return NULL;} -void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } +void *IMB_exr_get_handle (void) {return NULL;} +void IMB_exr_add_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } -int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;} -int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;} -void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; } +int IMB_exr_begin_read (void *handle, const char *filename, int *width, int *height) { (void)handle; (void)filename; (void)width; (void)height; return 0;} +int IMB_exr_begin_write (void *handle, const char *filename, int width, int height, int compress) { (void)handle; (void)filename; (void)width; (void)height; (void)compress; return 0;} +void IMB_exrtile_begin_write (void *handle, const char *filename, int mipmap, int width, int height, int tilex, int tiley) { (void)handle; (void)filename; (void)mipmap; (void)width; (void)height; (void)tilex; (void)tiley; } -void IMB_exr_set_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } +void IMB_exr_set_channel (void *handle, const char *layname, const char *channame, int xstride, int ystride, float *rect) { (void)handle; (void)layname; (void)channame; (void)xstride; (void)ystride; (void)rect; } -void IMB_exr_read_channels (void *handle) { (void)handle; } -void IMB_exr_write_channels (void *handle) { (void)handle; } -void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) { (void)handle; (void)partx; (void)party; (void)level; } -void IMB_exrtile_clear_channels (void *handle) { (void)handle; } +void IMB_exr_read_channels (void *handle) { (void)handle; } +void IMB_exr_write_channels (void *handle) { (void)handle; } +void IMB_exrtile_write_channels (void *handle, int partx, int party, int level) { (void)handle; (void)partx; (void)party; (void)level; } +void IMB_exrtile_clear_channels (void *handle) { (void)handle; } -void IMB_exr_multilayer_convert (void *handle, void *base, - void * (*addlayer)(void *base, const char *str), - void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id)) - { - (void)handle; (void)base; (void)addlayer; (void)addpass; - } +void IMB_exr_multilayer_convert (void *handle, void *base, + void * (*addlayer)(void *base, const char *str), + void (*addpass)(void *base, void *lay, const char *str, float *rect, int totchan, const char *chan_id)) +{ + (void)handle; (void)base; (void)addlayer; (void)addpass; +} -void IMB_exr_close (void *handle) { (void)handle; } +void IMB_exr_close (void *handle) { (void)handle; } diff --git a/source/blender/imbuf/intern/rectop.c b/source/blender/imbuf/intern/rectop.c index 8e072361583..d2b0645cf93 100644 --- a/source/blender/imbuf/intern/rectop.c +++ b/source/blender/imbuf/intern/rectop.c @@ -587,7 +587,7 @@ void IMB_rectfill_area(struct ImBuf *ibuf, const float col[4], int x1, int y1, i { if (!ibuf) return; buf_rectfill_area((unsigned char *) ibuf->rect, ibuf->rect_float, ibuf->x, ibuf->y, col, display, - x1, y1, x2, y2); + x1, y1, x2, y2); } diff --git a/source/blender/imbuf/intern/scaling.c b/source/blender/imbuf/intern/scaling.c index 527f334d6a4..b9525ccccf1 100644 --- a/source/blender/imbuf/intern/scaling.c +++ b/source/blender/imbuf/intern/scaling.c @@ -331,13 +331,13 @@ void imb_onehalf_no_alloc(struct ImBuf *ibuf2, struct ImBuf *ibuf1) for (y = ibuf2->y; y > 0; y--) { p2f = p1f + (ibuf1->x << 2); for (x = ibuf2->x; x > 0; x--) { - destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]); - destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]); - destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]); - destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]); - p1f += 8; - p2f += 8; - destf += 4; + destf[0] = 0.25f * (p1f[0] + p2f[0] + p1f[4] + p2f[4]); + destf[1] = 0.25f * (p1f[1] + p2f[1] + p1f[5] + p2f[5]); + destf[2] = 0.25f * (p1f[2] + p2f[2] + p1f[6] + p2f[6]); + destf[3] = 0.25f * (p1f[3] + p2f[3] + p1f[7] + p2f[7]); + p1f += 8; + p2f += 8; + destf += 4; } p1f = p2f; if (ibuf1->x & 1) p1f += 4; diff --git a/source/blender/makesdna/intern/makesdna.c b/source/blender/makesdna/intern/makesdna.c index bef5e5cc161..fa0b313a120 100644 --- a/source/blender/makesdna/intern/makesdna.c +++ b/source/blender/makesdna/intern/makesdna.c @@ -1001,7 +1001,7 @@ static int make_structDNA(char *baseDirectory, FILE *file) /* FOR DEBUG */ if (debugSDNA > 1) { int a, b; -/* short *elem; */ + /* short *elem; */ short num_types; printf("nr_names %d nr_types %d nr_structs %d\n", nr_names, nr_types, nr_structs); diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c index 7c4ce3d18d7..8a71adec772 100644 --- a/source/blender/makesrna/intern/makesrna.c +++ b/source/blender/makesrna/intern/makesrna.c @@ -80,13 +80,15 @@ static void rna_generate_static_parameter_prototypes(FILE *f, StructRNA *srna, F const char *name_override, int close_prototype); /* helpers */ -#define WRITE_COMMA { \ +#define WRITE_COMMA \ + { \ if (!first) \ fprintf(f, ", "); \ first = 0; \ } (void)0 -#define WRITE_PARAM(param) { \ +#define WRITE_PARAM(param) \ + { \ WRITE_COMMA; \ fprintf(f, param); \ } @@ -3579,10 +3581,10 @@ static void rna_generate_header_class_cpp(StructDefRNA *ds, FILE *f) fprintf(f, "class %s : public %s {\n", srna->identifier, (srna->base) ? srna->base->identifier : "Pointer"); fprintf(f, "public:\n"); fprintf(f, "\t%s(const PointerRNA &ptr_arg) :\n\t\t%s(ptr_arg)", srna->identifier, - (srna->base) ? srna->base->identifier : "Pointer"); + (srna->base) ? srna->base->identifier : "Pointer"); for (dp = ds->cont.properties.first; dp; dp = dp->next) if (rna_is_collection_prop(dp->prop)) - fprintf(f, ",\n\t\t%s(ptr_arg)", dp->prop->identifier); + fprintf(f, ",\n\t\t%s(ptr_arg)", dp->prop->identifier); fprintf(f, "\n\t\t{}\n\n"); for (dp = ds->cont.properties.first; dp; dp = dp->next) diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c index e96ed4f38d3..7bdebd620ee 100644 --- a/source/blender/makesrna/intern/rna_brush.c +++ b/source/blender/makesrna/intern/rna_brush.c @@ -146,8 +146,8 @@ static int rna_SculptCapabilities_has_overlay_get(PointerRNA *ptr) { Brush *br = (Brush *)ptr->data; return ELEM(br->mtex.brush_map_mode, - MTEX_MAP_MODE_VIEW, - MTEX_MAP_MODE_TILED); + MTEX_MAP_MODE_VIEW, + MTEX_MAP_MODE_TILED); } static int rna_SculptCapabilities_has_persistence_get(PointerRNA *ptr) diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index 170e6147d99..287995e0aa6 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -2809,7 +2809,7 @@ static void rna_def_mesh(BlenderRNA *brna) prop = RNA_def_property(srna, "skin_vertices", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "vdata.layers", "vdata.totlayer"); RNA_def_property_collection_funcs(prop, "rna_Mesh_skin_vertices_begin", NULL, NULL, NULL, - "rna_Mesh_skin_vertices_length", NULL, NULL, NULL); + "rna_Mesh_skin_vertices_length", NULL, NULL, NULL); RNA_def_property_struct_type(prop, "MeshSkinVertexLayer"); RNA_def_property_ui_text(prop, "Skin Vertices", "All skin vertices"); rna_def_skin_vertices(brna, prop); diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index d241f697be0..67e876b70a0 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1204,7 +1204,7 @@ typedef struct NodeInfo { static NodeInfo nodes[MaxNodes]; static void reg_node(int ID, int category, const char *enum_name, const char *struct_name, - const char *base_name, const char *ui_name, const char *ui_desc) + const char *base_name, const char *ui_name, const char *ui_desc) { NodeInfo *ni = nodes + ID; diff --git a/source/blender/modifiers/intern/MOD_explode.c b/source/blender/modifiers/intern/MOD_explode.c index 92ad6faa3ce..1298d281de8 100644 --- a/source/blender/modifiers/intern/MOD_explode.c +++ b/source/blender/modifiers/intern/MOD_explode.c @@ -205,7 +205,8 @@ static MFace *get_dface(DerivedMesh *dm, DerivedMesh *split, int cur, int i, MFa return df; } -#define SET_VERTS(a, b, c, d) { \ +#define SET_VERTS(a, b, c, d) \ + { \ v[0] = mf->v##a; uv[0] = a - 1; \ v[1] = mf->v##b; uv[1] = b - 1; \ v[2] = mf->v##c; uv[2] = c - 1; \ diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 8a4d70da6e8..80966fee599 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -644,8 +644,8 @@ typedef struct { } EdgeStackElem; static void build_emats_stack(BLI_Stack *stack, int *visited_e, EMat *emat, - const MeshElemMap *emap, const MEdge *medge, - const MVertSkin *vs, const MVert *mvert) + const MeshElemMap *emap, const MEdge *medge, + const MVertSkin *vs, const MVert *mvert) { EdgeStackElem stack_elem; float axis[3], angle; @@ -673,7 +673,7 @@ static void build_emats_stack(BLI_Stack *stack, int *visited_e, EMat *emat, /* If parent is a branch node, start a new edge chain */ if (parent_is_branch) { calc_edge_mat(emat[e].mat, mvert[parent_v].co, - mvert[v].co); + mvert[v].co); } else { /* Build edge matrix guided by parent matrix */ @@ -959,12 +959,12 @@ static void add_poly(SkinOutput *so, static void connect_frames(SkinOutput *so, BMVert *frame1[4], - BMVert *frame2[4]) +BMVert *frame2[4]) { BMVert *q[4][4] = {{frame2[0], frame2[1], frame1[1], frame1[0]}, - {frame2[1], frame2[2], frame1[2], frame1[1]}, - {frame2[2], frame2[3], frame1[3], frame1[2]}, - {frame2[3], frame2[0], frame1[0], frame1[3]}}; + {frame2[1], frame2[2], frame1[2], frame1[1]}, + {frame2[2], frame2[3], frame1[3], frame1[2]}, + {frame2[3], frame2[0], frame1[0], frame1[3]}}; float p[3], no[3]; int i, swap; diff --git a/source/blender/modifiers/intern/MOD_solidify.c b/source/blender/modifiers/intern/MOD_solidify.c index cc77d73a736..fbd3c084e70 100644 --- a/source/blender/modifiers/intern/MOD_solidify.c +++ b/source/blender/modifiers/intern/MOD_solidify.c @@ -207,9 +207,10 @@ BLI_INLINE void madd_v3v3short_fl(float r[3], const short a[3], const float f) r[2] += (float)a[2] * f; } -static DerivedMesh *applyModifier(ModifierData *md, Object *ob, - DerivedMesh *dm, - ModifierApplyFlag UNUSED(flag)) +static DerivedMesh *applyModifier( + ModifierData *md, Object *ob, + DerivedMesh *dm, + ModifierApplyFlag UNUSED(flag)) { int i; DerivedMesh *result; diff --git a/source/blender/python/generic/py_capi_utils.c b/source/blender/python/generic/py_capi_utils.c index 3b8193c422d..b8537a1359f 100644 --- a/source/blender/python/generic/py_capi_utils.c +++ b/source/blender/python/generic/py_capi_utils.c @@ -504,7 +504,7 @@ void PyC_SetHomePath(const char *py_path_bundle) * but current Python lib (release 3.1.1) doesn't handle these correctly */ if (strchr(py_path_bundle, ':')) printf("Warning : Blender application is located in a path containing : or / chars\ - \nThis may make python import function fail\n"); + \nThis may make python import function fail\n"); #endif From 98e60b2f43a20dd206994aa62f04254badcfb98c Mon Sep 17 00:00:00 2001 From: Joshua Leung Date: Fri, 9 Nov 2012 09:57:35 +0000 Subject: [PATCH 046/118] Edits for consistency with other parts of code For the record, AnimData vars should be named "adt", not "ad" --- source/blender/blenkernel/intern/scene.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index edd880238ca..bb045a3cfd2 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -119,16 +119,16 @@ void free_qtcodecdata(QuicktimeCodecData *qcd) static void remove_sequencer_fcurves(Scene *sce) { - AnimData *ad = BKE_animdata_from_id(&sce->id); + AnimData *adt = BKE_animdata_from_id(&sce->id); - if (ad && ad->action) { + if (adt && adt->action) { FCurve *fcu, *nextfcu; - - for (fcu = ad->action->curves.first; fcu; fcu = nextfcu) { + + for (fcu = adt->action->curves.first; fcu; fcu = nextfcu) { nextfcu = fcu->next; - + if ((fcu->rna_path) && strstr(fcu->rna_path, "sequences_all")) { - action_groups_remove_channel(ad->action, fcu); + action_groups_remove_channel(adt->action, fcu); free_fcurve(fcu); } } From 3ce1d54e95cd7ae8bb6777497688386f9729cf96 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Fri, 9 Nov 2012 10:33:42 +0000 Subject: [PATCH 047/118] Bugfix #33124 User Preference setting for Color Picker type only affected the popup version. Now it uses it for all color pickers in Panels too. Note for UI Py team: col.template_color_wheel() function follows the userpref - might be a need for rename here? Dunno how to handle this. Comment noted in template code. --- .../editors/interface/interface_templates.c | 46 ++++++++++++++++--- .../editors/interface/interface_widgets.c | 4 +- source/blender/makesrna/intern/rna_userdef.c | 1 + 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 24aca0c037d..3ee389fbd1f 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1951,10 +1951,11 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propn MEM_freeN(cb); } -/********************* ColorWheel Template ************************/ +/********************* ColorPicker Template ************************/ #define WHEEL_SIZE 100 +/* This template now follows User Preference for type - name is not correct anymore... */ void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); @@ -1970,10 +1971,24 @@ void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propnam RNA_property_float_ui_range(ptr, prop, &softmin, &softmax, &step, &precision); - col = uiLayoutColumn(layout, FALSE); + col = uiLayoutColumn(layout, TRUE); row = uiLayoutRow(col, TRUE); - but = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, ""); + switch (U.color_picker_type) { + case USER_CP_CIRCLE: + but = uiDefButR_prop(block, HSVCIRCLE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, 0, 0, ""); + break; + case USER_CP_SQUARE_SV: + but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, UI_GRAD_SV, 0, ""); + break; + case USER_CP_SQUARE_HS: + but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, UI_GRAD_HS, 0, ""); + break; + case USER_CP_SQUARE_HV: + but = uiDefButR_prop(block, HSVCUBE, 0, "", 0, 0, WHEEL_SIZE, WHEEL_SIZE, ptr, prop, -1, 0.0, 0.0, UI_GRAD_HV, 0, ""); + break; + } + if (lock) { but->flag |= UI_BUT_COLOR_LOCK; @@ -1989,10 +2004,29 @@ void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propnam if (cubic) but->flag |= UI_BUT_COLOR_CUBIC; - uiItemS(row); - if (value_slider) - uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, ""); + if (value_slider) { + + switch (U.color_picker_type) { + case USER_CP_CIRCLE: + uiItemS(row); + uiDefButR_prop(block, HSVCUBE, 0, "", WHEEL_SIZE + 6, 0, 14, WHEEL_SIZE, ptr, prop, -1, softmin, softmax, UI_GRAD_V_ALT, 0, ""); + break; + case USER_CP_SQUARE_SV: + uiItemS(col); + uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, -1, softmin, softmax, UI_GRAD_SV + 3, 0, ""); + break; + case USER_CP_SQUARE_HS: + uiItemS(col); + uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, -1, softmin, softmax, UI_GRAD_HS + 3, 0, ""); + break; + case USER_CP_SQUARE_HV: + uiItemS(col); + uiDefButR_prop(block, HSVCUBE, 0, "", 0, 4, WHEEL_SIZE, 18, ptr, prop, -1, softmin, softmax, UI_GRAD_HV + 3, 0, ""); + break; + } + + } } /********************* Layer Buttons Template ************************/ diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index d16169f1034..feb1e95ad23 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2059,7 +2059,7 @@ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const floa /* old below */ - for (dx = 0.0f; dx < 1.0f; dx += color_step) { + for (dx = 0.0f; dx < 0.999f; dx += color_step) { /* 0.999 = prevent float inaccuracy for steps */ /* previous color */ copy_v3_v3(col0[0], col1[0]); copy_v3_v3(col0[1], col1[1]); @@ -2114,7 +2114,7 @@ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const floa sx1 = rect->xmin + dx * BLI_rcti_size_x(rect); sx2 = rect->xmin + (dx + color_step) * BLI_rcti_size_x(rect); sy = rect->ymin; - dy = BLI_rcti_size_y(rect) / 3.0; + dy = (float)BLI_rcti_size_y(rect) / 3.0; glBegin(GL_QUADS); for (a = 0; a < 3; a++, sy += dy) { diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 11e04cdd281..31a1360829e 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3162,6 +3162,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_enum_items(prop, color_picker_types); RNA_def_property_enum_sdna(prop, NULL, "color_picker_type"); RNA_def_property_ui_text(prop, "Color Picker Type", "Different styles of displaying the color picker widget"); + RNA_def_property_update(prop, 0, "rna_userdef_update"); prop = RNA_def_property(srna, "use_preview_images", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_ALLWINCODECS); From 6d31921b2608ba743f290bf90aabd3e6fb110c50 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Fri, 9 Nov 2012 10:41:47 +0000 Subject: [PATCH 048/118] Temporarily change: Intel graphics cards now use Triple Buffer when you set it to "Auto". Recent tests proved that this is now working... and better test this now well than a week before a release! --- source/blender/windowmanager/intern/wm_draw.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index d7285ec4380..60e3f7d6164 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -711,12 +711,14 @@ static int wm_automatic_draw_method(wmWindow *win) if (GPU_type_matches(GPU_DEVICE_ATI, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE)) return USER_DRAW_OVERLAP; /* also Intel drivers are slow */ + /* 2.64 BCon3 period, let's try if intel now works... else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_UNIX, GPU_DRIVER_ANY)) return USER_DRAW_OVERLAP; else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_WIN, GPU_DRIVER_ANY)) return USER_DRAW_OVERLAP_FLIP; else if (GPU_type_matches(GPU_DEVICE_INTEL, GPU_OS_MAC, GPU_DRIVER_ANY)) return USER_DRAW_OVERLAP_FLIP; + */ /* Windows software driver darkens color on each redraw */ else if (GPU_type_matches(GPU_DEVICE_SOFTWARE, GPU_OS_WIN, GPU_DRIVER_SOFTWARE)) return USER_DRAW_OVERLAP_FLIP; From c046b13b56d80ec3888b64e9215f1fc35b68b9b3 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 11:03:53 +0000 Subject: [PATCH 049/118] rename template_color_wheel() to template_color_picker() --- release/scripts/startup/bl_ui/space_image.py | 2 +- .../scripts/startup/bl_ui/space_sequencer.py | 6 ++--- .../startup/bl_ui/space_view3d_toolbar.py | 4 +-- source/blender/editors/include/UI_interface.h | 2 +- .../editors/interface/interface_templates.c | 2 +- .../editors/interface/interface_widgets.c | 2 +- source/blender/editors/space_node/drawnode.c | 26 +++++++++---------- source/blender/makesrna/intern/rna_ui_api.c | 2 +- .../bad_level_call_stubs/stubs.c | 2 +- 9 files changed, 24 insertions(+), 24 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_image.py b/release/scripts/startup/bl_ui/space_image.py index 5302ad9b471..18eb8f8d9dd 100644 --- a/release/scripts/startup/bl_ui/space_image.py +++ b/release/scripts/startup/bl_ui/space_image.py @@ -684,7 +684,7 @@ class IMAGE_PT_paint(Panel, ImagePaintPanel): if brush: col = layout.column() - col.template_color_wheel(brush, "color", value_slider=True) + col.template_color_picker(brush, "color", value_slider=True) col.prop(brush, "color", text="") row = col.row(align=True) diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py index cba45d4c2b7..ad4074d9744 100644 --- a/release/scripts/startup/bl_ui/space_sequencer.py +++ b/release/scripts/startup/bl_ui/space_sequencer.py @@ -31,21 +31,21 @@ def act_strip(context): def draw_color_balance(layout, color_balance): col = layout.column() col.label(text="Lift:") - col.template_color_wheel(color_balance, "lift", value_slider=True, cubic=True) + col.template_color_picker(color_balance, "lift", value_slider=True, cubic=True) row = col.row() row.prop(color_balance, "lift", text="") row.prop(color_balance, "invert_lift", text="Inverse") col = layout.column() col.label(text="Gamma:") - col.template_color_wheel(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True) + col.template_color_picker(color_balance, "gamma", value_slider=True, lock_luminosity=True, cubic=True) row = col.row() row.prop(color_balance, "gamma", text="") row.prop(color_balance, "invert_gamma", text="Inverse") col = layout.column() col.label(text="Gain:") - col.template_color_wheel(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True) + col.template_color_picker(color_balance, "gain", value_slider=True, lock_luminosity=True, cubic=True) row = col.row() row.prop(color_balance, "gain", text="") row.prop(color_balance, "invert_gain", text="Inverse") diff --git a/release/scripts/startup/bl_ui/space_view3d_toolbar.py b/release/scripts/startup/bl_ui/space_view3d_toolbar.py index 9bb8255356c..91132a72b07 100644 --- a/release/scripts/startup/bl_ui/space_view3d_toolbar.py +++ b/release/scripts/startup/bl_ui/space_view3d_toolbar.py @@ -633,7 +633,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel): elif context.image_paint_object and brush: col = layout.column() - col.template_color_wheel(brush, "color", value_slider=True) + col.template_color_picker(brush, "color", value_slider=True) col.prop(brush, "color", text="") row = col.row(align=True) @@ -681,7 +681,7 @@ class VIEW3D_PT_tools_brush(Panel, View3DPaintPanel): # Vertex Paint Mode # elif context.vertex_paint_object and brush: col = layout.column() - col.template_color_wheel(brush, "color", value_slider=True) + col.template_color_picker(brush, "color", value_slider=True) col.prop(brush, "color", text="") row = col.row(align=True) diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index ed4b4ae027f..3645f13f27a 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -807,7 +807,7 @@ void uiTemplateHistogram(uiLayout *layout, struct PointerRNA *ptr, const char *p void uiTemplateWaveform(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateVectorscope(uiLayout *layout, struct PointerRNA *ptr, const char *propname); void uiTemplateCurveMapping(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int type, int levels, int brush); -void uiTemplateColorWheel(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic); +void uiTemplateColorPicker(uiLayout *layout, struct PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic); void uiTemplateLayers(uiLayout *layout, struct PointerRNA *ptr, const char *propname, PointerRNA *used_ptr, const char *used_propname, int active_layer); void uiTemplateGameStates(uiLayout *layout, struct PointerRNA *ptr, const char *propname, diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 3ee389fbd1f..84ae3a8f57d 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -1956,7 +1956,7 @@ void uiTemplateCurveMapping(uiLayout *layout, PointerRNA *ptr, const char *propn #define WHEEL_SIZE 100 /* This template now follows User Preference for type - name is not correct anymore... */ -void uiTemplateColorWheel(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic) +void uiTemplateColorPicker(uiLayout *layout, PointerRNA *ptr, const char *propname, int value_slider, int lock, int lock_luminosity, int cubic) { PropertyRNA *prop = RNA_struct_find_property(ptr, propname); uiBlock *block = uiLayoutGetBlock(layout); diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index feb1e95ad23..c836d62021e 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -2114,7 +2114,7 @@ void ui_draw_gradient(rcti *rect, const float hsv[3], const int type, const floa sx1 = rect->xmin + dx * BLI_rcti_size_x(rect); sx2 = rect->xmin + (dx + color_step) * BLI_rcti_size_x(rect); sy = rect->ymin; - dy = (float)BLI_rcti_size_y(rect) / 3.0; + dy = (float)BLI_rcti_size_y(rect) / 3.0f; glBegin(GL_QUADS); for (a = 0; a < 3; a++, sy += dy) { diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index aafd4abb25e..8d44da2e367 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -319,7 +319,7 @@ static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr); col = uiLayoutColumn(layout, FALSE); - uiTemplateColorWheel(col, &sockptr, "default_value", 1, 0, 0, 0); + uiTemplateColorPicker(col, &sockptr, "default_value", 1, 0, 0, 0); uiItemR(col, &sockptr, "default_value", 0, "", ICON_NONE); } @@ -2258,17 +2258,17 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C split = uiLayoutSplit(layout, 0.0f, FALSE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "lift", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "lift", 1, 1, 0, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "lift", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "gamma", 1, 1, 1, 1); + uiTemplateColorPicker(col, ptr, "gamma", 1, 1, 1, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "gamma", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "gain", 1, 1, 1, 1); + uiTemplateColorPicker(col, ptr, "gain", 1, 1, 1, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "gain", 0, NULL, ICON_NONE); @@ -2277,17 +2277,17 @@ static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C split = uiLayoutSplit(layout, 0.0f, FALSE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "offset", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "offset", 1, 1, 0, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "offset", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "power", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "power", 1, 1, 0, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "power", 0, NULL, ICON_NONE); col = uiLayoutColumn(split, FALSE); - uiTemplateColorWheel(col, ptr, "slope", 1, 1, 0, 1); + uiTemplateColorPicker(col, ptr, "slope", 1, 1, 0, 1); row = uiLayoutRow(col, FALSE); uiItemR(row, ptr, "slope", 0, NULL, ICON_NONE); } @@ -2299,23 +2299,23 @@ static void node_composit_buts_colorbalance_but(uiLayout *layout, bContext *UNUS if (RNA_enum_get(ptr, "correction_method") == 0) { - uiTemplateColorWheel(layout, ptr, "lift", 1, 1, 0, 1); + uiTemplateColorPicker(layout, ptr, "lift", 1, 1, 0, 1); uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE); - uiTemplateColorWheel(layout, ptr, "gamma", 1, 1, 1, 1); + uiTemplateColorPicker(layout, ptr, "gamma", 1, 1, 1, 1); uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE); - uiTemplateColorWheel(layout, ptr, "gain", 1, 1, 1, 1); + uiTemplateColorPicker(layout, ptr, "gain", 1, 1, 1, 1); uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE); } else { - uiTemplateColorWheel(layout, ptr, "offset", 1, 1, 0, 1); + uiTemplateColorPicker(layout, ptr, "offset", 1, 1, 0, 1); uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE); - uiTemplateColorWheel(layout, ptr, "power", 1, 1, 0, 1); + uiTemplateColorPicker(layout, ptr, "power", 1, 1, 0, 1); uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE); - uiTemplateColorWheel(layout, ptr, "slope", 1, 1, 0, 1); + uiTemplateColorPicker(layout, ptr, "slope", 1, 1, 0, 1); uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE); } } diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index 2a8f1b90d4e..548539e3395 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -390,7 +390,7 @@ void RNA_api_ui_layout(StructRNA *srna) parm = RNA_def_int(func, "active_layer", 0, 0, INT_MAX, "Active Layer", "", 0, INT_MAX); RNA_def_property_flag(parm, PROP_REQUIRED); - func = RNA_def_function(srna, "template_color_wheel", "uiTemplateColorWheel"); + func = RNA_def_function(srna, "template_color_picker", "uiTemplateColorPicker"); RNA_def_function_ui_description(func, "Item. A color wheel widget to pick colors"); api_ui_item_rna_common(func); RNA_def_boolean(func, "value_slider", 0, "", "Display the value slider to the right of the color wheel"); diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 5550cc69f89..3dcfecac542 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -422,7 +422,7 @@ void uiTemplateEditModeSelection(struct uiLayout *layout, struct bContext *C) {} void uiTemplateTextureImage(struct uiLayout *layout, struct bContext *C, struct Tex *tex) {} void uiTemplateImage(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, char *propname, struct PointerRNA *userptr, int compact) {} void uiTemplateDopeSheetFilter(struct uiLayout *layout, struct bContext *C, struct PointerRNA *ptr) {} -void uiTemplateColorWheel(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider) {} +void uiTemplateColorPicker(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int value_slider) {} void uiTemplateHistogram(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand) {} void uiTemplateReportsBanner(struct uiLayout *layout, struct bContext *C, struct wmOperator *op) {} void uiTemplateWaveform(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, int expand) {} From 079a0a30e49c036c1ce4425c949e0c370a91492b Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Fri, 9 Nov 2012 13:33:23 +0000 Subject: [PATCH 050/118] Usability: Made SHIFT+drag mouse in Curve and ColorPicker widgets move with more precision. This was only working with UserPref "continuous grab". --- .../editors/interface/interface_handlers.c | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 5d4427bcbef..5f01255b8e0 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -279,12 +279,7 @@ static int ui_is_a_warp_but(uiBut *but) static float ui_mouse_scale_warp_factor(const short shift) { - if (U.uiflag & USER_CONTINUOUS_MOUSE) { - return shift ? 0.05f : 1.0f; - } - else { - return 1.0f; - } + return shift ? 0.05f : 1.0f; } static void ui_mouse_scale_warp(uiHandleButtonData *data, @@ -292,16 +287,11 @@ static void ui_mouse_scale_warp(uiHandleButtonData *data, float *r_mx, float *r_my, const short shift) { - if (U.uiflag & USER_CONTINUOUS_MOUSE) { - const float fac = ui_mouse_scale_warp_factor(shift); - /* slow down the mouse, this is fairly picky */ - *r_mx = (data->dragstartx * (1.0f - fac) + mx * fac); - *r_my = (data->dragstarty * (1.0f - fac) + my * fac); - } - else { - *r_mx = mx; - *r_my = my; - } + const float fac = ui_mouse_scale_warp_factor(shift); + + /* slow down the mouse, this is fairly picky */ + *r_mx = (data->dragstartx * (1.0f - fac) + mx * fac); + *r_my = (data->dragstarty * (1.0f - fac) + my * fac); } /* file selectors are exempt from utf-8 checks */ From dc5ba03945c9f9cc8cbc93c91ff872a29c38659c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 9 Nov 2012 13:57:09 +0000 Subject: [PATCH 051/118] Fix #33123: lamp nodes drivers not working, now uses same hacks as material to work around dependency graph limitations. --- source/blender/blenkernel/BKE_lamp.h | 3 ++ source/blender/blenkernel/intern/anim_sys.c | 8 ++-- source/blender/blenkernel/intern/depsgraph.c | 43 ++++++++++++++++---- source/blender/blenkernel/intern/lamp.c | 38 +++++++++++++++++ source/blender/blenkernel/intern/object.c | 2 + source/blender/blenkernel/intern/scene.c | 2 + 6 files changed, 84 insertions(+), 12 deletions(-) diff --git a/source/blender/blenkernel/BKE_lamp.h b/source/blender/blenkernel/BKE_lamp.h index 3acd4d1986e..244decf9d52 100644 --- a/source/blender/blenkernel/BKE_lamp.h +++ b/source/blender/blenkernel/BKE_lamp.h @@ -37,6 +37,7 @@ extern "C" { #endif struct Lamp; +struct Scene; struct Lamp *BKE_lamp_add(const char *name) WARN_UNUSED; struct Lamp *BKE_lamp_copy(struct Lamp *la) WARN_UNUSED; @@ -44,6 +45,8 @@ struct Lamp *localize_lamp(struct Lamp *la) WARN_UNUSED; void BKE_lamp_make_local(struct Lamp *la); void BKE_lamp_free(struct Lamp *la); +void lamp_drivers_update(struct Scene *scene, struct Lamp *la, float ctime); + #ifdef __cplusplus } #endif diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c index 75ab02ee8e9..40b883e3f4e 100644 --- a/source/blender/blenkernel/intern/anim_sys.c +++ b/source/blender/blenkernel/intern/anim_sys.c @@ -781,7 +781,7 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u ANIMDATA_NODETREE_IDS_CB(mainptr->tex.first, Tex); /* lamps */ - ANIMDATA_IDS_CB(mainptr->lamp.first); + ANIMDATA_NODETREE_IDS_CB(mainptr->lamp.first, Lamp); /* materials */ ANIMDATA_NODETREE_IDS_CB(mainptr->mat.first, Material); @@ -823,7 +823,7 @@ void BKE_animdata_main_cb(Main *mainptr, ID_AnimData_Edit_Callback func, void *u ANIMDATA_IDS_CB(mainptr->mask.first); /* worlds */ - ANIMDATA_IDS_CB(mainptr->world.first); + ANIMDATA_NODETREE_IDS_CB(mainptr->world.first, World); /* scenes */ ANIMDATA_NODETREE_IDS_CB(mainptr->scene.first, Scene); @@ -868,7 +868,7 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha RENAMEFIX_ANIM_NODETREE_IDS(mainptr->tex.first, Tex); /* lamps */ - RENAMEFIX_ANIM_IDS(mainptr->lamp.first); + RENAMEFIX_ANIM_NODETREE_IDS(mainptr->lamp.first, Lamp); /* materials */ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->mat.first, Material); @@ -910,7 +910,7 @@ void BKE_all_animdata_fix_paths_rename(ID *ref_id, const char *prefix, const cha RENAMEFIX_ANIM_IDS(mainptr->mask.first); /* worlds */ - RENAMEFIX_ANIM_IDS(mainptr->world.first); + RENAMEFIX_ANIM_NODETREE_IDS(mainptr->world.first, World); /* scenes */ RENAMEFIX_ANIM_NODETREE_IDS(mainptr->scene.first, Scene); diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c index 44b3917df7f..9d3a7ec57cf 100644 --- a/source/blender/blenkernel/intern/depsgraph.c +++ b/source/blender/blenkernel/intern/depsgraph.c @@ -45,6 +45,7 @@ #include "DNA_anim_types.h" #include "DNA_camera_types.h" #include "DNA_group_types.h" +#include "DNA_lamp_types.h" #include "DNA_lattice_types.h" #include "DNA_key_types.h" #include "DNA_material_types.h" @@ -350,8 +351,8 @@ static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node /* XXX: forward def for material driver handling... */ static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma); -/* recursive handling for material nodetree drivers */ -static void dag_add_material_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree) +/* recursive handling for shader nodetree drivers */ +static void dag_add_shader_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree) { bNode *n; @@ -367,7 +368,7 @@ static void dag_add_material_nodetree_driver_relations(DagForest *dag, DagNode * dag_add_material_driver_relations(dag, node, (Material *)n->id); } else if (n->type == NODE_GROUP) { - dag_add_material_nodetree_driver_relations(dag, node, (bNodeTree *)n->id); + dag_add_shader_nodetree_driver_relations(dag, node, (bNodeTree *)n->id); } } } @@ -386,18 +387,41 @@ static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Mat ma->id.flag |= LIB_DOIT; /* material itself */ - if (ma->adt) { + if (ma->adt) dag_add_driver_relation(ma->adt, dag, node, 1); - } /* textures */ // TODO... //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id); /* material's nodetree */ - if (ma->nodetree) { - dag_add_material_nodetree_driver_relations(dag, node, ma->nodetree); - } + if (ma->nodetree) + dag_add_shader_nodetree_driver_relations(dag, node, ma->nodetree); +} + +/* recursive handling for lamp drivers */ +static void dag_add_lamp_driver_relations(DagForest *dag, DagNode *node, Lamp *la) +{ + /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited + * already (see build_dag()). This assumes la->id.flag & LIB_DOIT isn't set by anything else + * in the meantime... [#32017] + */ + if (la->id.flag & LIB_DOIT) + return; + else + la->id.flag |= LIB_DOIT; + + /* lamp itself */ + if (la->adt) + dag_add_driver_relation(la->adt, dag, node, 1); + + /* textures */ + // TODO... + //dag_add_texture_driver_relations(DagForest *dag, DagNode *node, ID *id); + + /* lamp's nodetree */ + if (la->nodetree) + dag_add_shader_nodetree_driver_relations(dag, node, la->nodetree); } static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node, int skip_forcefield) @@ -647,6 +671,8 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O } } } + else if(ob->type == OB_LAMP) + dag_add_lamp_driver_relations(dag, node, ob->data); /* particles */ psys = ob->particlesystem.first; @@ -817,6 +843,7 @@ DagForest *build_dag(Main *bmain, Scene *sce, short mask) /* clear "LIB_DOIT" flag from all materials, to prevent infinite recursion problems later [#32017] */ tag_main_idcode(bmain, ID_MA, FALSE); + tag_main_idcode(bmain, ID_LA, FALSE); /* add base node for scene. scene is always the first node in DAG */ scenenode = dag_add_node(dag, sce); diff --git a/source/blender/blenkernel/intern/lamp.c b/source/blender/blenkernel/intern/lamp.c index 576afe123c0..2f37db846f3 100644 --- a/source/blender/blenkernel/intern/lamp.c +++ b/source/blender/blenkernel/intern/lamp.c @@ -33,9 +33,12 @@ #include "MEM_guardedalloc.h" +#include "DNA_anim_types.h" #include "DNA_lamp_types.h" #include "DNA_material_types.h" +#include "DNA_node_types.h" #include "DNA_object_types.h" +#include "DNA_scene_types.h" #include "DNA_texture_types.h" #include "BLI_listbase.h" @@ -232,3 +235,38 @@ void BKE_lamp_free(Lamp *la) la->id.icon_id = 0; } +/* Calculate all drivers for lamps, see material_drivers_update for why this is a bad hack */ + +static void lamp_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime) +{ + bNode *node; + + /* nodetree itself */ + if (ntree->adt && ntree->adt->drivers.first) + BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS); + + /* nodes */ + for (node = ntree->nodes.first; node; node = node->next) + if (node->id && node->type == NODE_GROUP) + lamp_node_drivers_update(scene, (bNodeTree *)node->id, ctime); +} + +void lamp_drivers_update(Scene *scene, Lamp *la, float ctime) +{ + /* Prevent infinite recursion by checking (and tagging the lamp) as having been visited already + * (see BKE_scene_update_tagged()). This assumes la->id.flag & LIB_DOIT isn't set by anything else + * in the meantime... [#32017] */ + if (la->id.flag & LIB_DOIT) + return; + else + la->id.flag |= LIB_DOIT; + + /* lamp itself */ + if (la->adt && la->adt->drivers.first) + BKE_animsys_evaluate_animdata(scene, &la->id, la->adt, ctime, ADT_RECALC_DRIVERS); + + /* nodes */ + if (la->nodetree) + lamp_node_drivers_update(scene, la->nodetree, ctime); +} + diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 0611e84bdf3..6ec173a5908 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -2654,6 +2654,8 @@ void BKE_object_handle_update(Scene *scene, Object *ob) } } } + else if (ob->type == OB_LAMP) + lamp_drivers_update(scene, ob->data, ctime); /* particles */ if (ob->particlesystem.first) { diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index bb045a3cfd2..4f62732f5e6 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1074,6 +1074,7 @@ void BKE_scene_update_tagged(Main *bmain, Scene *scene) * when trying to find materials with drivers that need evaluating [#32017] */ tag_main_idcode(bmain, ID_MA, FALSE); + tag_main_idcode(bmain, ID_LA, FALSE); /* update all objects: drivers, matrices, displists, etc. flags set * by depgraph or manual, no layer check here, gets correct flushed @@ -1143,6 +1144,7 @@ void BKE_scene_update_for_newframe(Main *bmain, Scene *sce, unsigned int lay) * when trying to find materials with drivers that need evaluating [#32017] */ tag_main_idcode(bmain, ID_MA, FALSE); + tag_main_idcode(bmain, ID_LA, FALSE); /* BKE_object_handle_update() on all objects, groups and sets */ scene_update_tagged_recursive(bmain, sce, sce); From 6cdb555e6ebef2b9c3dde8672deef027d9d70d1a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 14:52:05 +0000 Subject: [PATCH 052/118] bmesh refactor - rename some of the BM_****_share_****_count() functions to BM_***_share_check() some of these were only returning a boolean, others returned a count even though only a boolean was needed. split some of the functions in two as well where check/count are both needed. --- .../blender/blenkernel/intern/cdderivedmesh.c | 2 - source/blender/bmesh/intern/bmesh_mods.c | 2 +- source/blender/bmesh/intern/bmesh_queries.c | 63 ++++++++++++++++++- source/blender/bmesh/intern/bmesh_queries.h | 8 ++- source/blender/bmesh/operators/bmo_create.c | 6 +- .../blender/bmesh/operators/bmo_subdivide.c | 2 +- .../blender/editors/mesh/editmesh_loopcut.c | 2 +- source/blender/modifiers/intern/MOD_skin.c | 20 +----- 8 files changed, 74 insertions(+), 31 deletions(-) diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index a0a402cc061..a6b303f3556 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -828,8 +828,6 @@ static void cdDM_drawMappedFaces(DerivedMesh *dm, mcol = DM_get_tessface_data_layer(dm, colType); } - printf("%s: %p(%d/%d)\n", __func__, mcol, CD_ID_MCOL, colType); - cdDM_update_normals_from_pbvh(dm); /* back-buffer always uses legacy since VBO's would need the diff --git a/source/blender/bmesh/intern/bmesh_mods.c b/source/blender/bmesh/intern/bmesh_mods.c index 62374d8b7bb..dc8b52423ab 100644 --- a/source/blender/bmesh/intern/bmesh_mods.c +++ b/source/blender/bmesh/intern/bmesh_mods.c @@ -118,7 +118,7 @@ int BM_disk_dissolve(BMesh *bm, BMVert *v) e = v->e; do { e = bmesh_disk_edge_next(e, v); - if (!(BM_edge_share_face_count(e, v->e))) { + if (!(BM_edge_share_face_check(e, v->e))) { keepedge = e; baseedge = v->e; break; diff --git a/source/blender/bmesh/intern/bmesh_queries.c b/source/blender/bmesh/intern/bmesh_queries.c index 8eb87cf29be..1e1d7d1becb 100644 --- a/source/blender/bmesh/intern/bmesh_queries.c +++ b/source/blender/bmesh/intern/bmesh_queries.c @@ -724,6 +724,47 @@ int BM_edge_is_boundary(BMEdge *e) } #endif +/** + * Returns the number of faces that are adjacent to both f1 and f2, + * \note Could be sped up a bit by not using iterators and by tagging + * faces on either side, then count the tags rather then searching. + */ +int BM_face_share_face_count(BMFace *f1, BMFace *f2) +{ + BMIter iter1, iter2; + BMEdge *e; + BMFace *f; + int count = 0; + + BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { + BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { + if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) + count++; + } + } + + return count; +} + +/** + * same as #BM_face_share_face_count but returns a bool + */ +int BM_face_share_face_check(BMFace *f1, BMFace *f2) +{ + BMIter iter1, iter2; + BMEdge *e; + BMFace *f; + + BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { + BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { + if (f != f1 && f != f2 && BM_face_share_edge_check(f, f2)) + return TRUE; + } + } + + return FALSE; +} + /** * Counts the number of edges two faces share (if any) */ @@ -743,10 +784,28 @@ int BM_face_share_edge_count(BMFace *f1, BMFace *f2) return count; } +/** + * Returns TRUE if the faces share an edge + */ +int BM_face_share_edge_check(BMFace *f1, BMFace *f2) +{ + BMLoop *l_iter; + BMLoop *l_first; + + l_iter = l_first = BM_FACE_FIRST_LOOP(f1); + do { + if (bmesh_radial_face_find(l_iter->e, f2)) { + return TRUE; + } + } while ((l_iter = l_iter->next) != l_first); + + return FALSE; +} + /** * Test if e1 shares any faces with e2 */ -int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2) +int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2) { BMLoop *l; BMFace *f; @@ -767,7 +826,7 @@ int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2) /** * Tests to see if e1 shares a vertex with e2 */ -int BM_edge_share_vert_count(BMEdge *e1, BMEdge *e2) +int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2) { return (e1->v1 == e2->v1 || e1->v1 == e2->v2 || diff --git a/source/blender/bmesh/intern/bmesh_queries.h b/source/blender/bmesh/intern/bmesh_queries.h index 34d0747676c..579a1397b0c 100644 --- a/source/blender/bmesh/intern/bmesh_queries.h +++ b/source/blender/bmesh/intern/bmesh_queries.h @@ -84,9 +84,13 @@ int BM_face_exists(BMesh *bm, BMVert **varr, int len, BMFace **r_existface); int BM_face_exists_multi(BMVert **varr, BMEdge **earr, int len); int BM_face_exists_multi_edge(BMEdge **earr, int len); +int BM_face_share_face_count(BMFace *f1, BMFace *f2); int BM_face_share_edge_count(BMFace *f1, BMFace *f2); -int BM_edge_share_face_count(BMEdge *e1, BMEdge *e2); -int BM_edge_share_vert_count(BMEdge *e1, BMEdge *e2); + +int BM_face_share_face_check(BMFace *f1, BMFace *f2); +int BM_face_share_edge_check(BMFace *f1, BMFace *f2); +int BM_edge_share_face_check(BMEdge *e1, BMEdge *e2); +int BM_edge_share_vert_check(BMEdge *e1, BMEdge *e2); BMVert *BM_edge_share_vert(BMEdge *e1, BMEdge *e2); BMLoop *BM_face_vert_share_loop(BMFace *f, BMVert *v); diff --git a/source/blender/bmesh/operators/bmo_create.c b/source/blender/bmesh/operators/bmo_create.c index bd1c0f809bd..093f567d995 100644 --- a/source/blender/bmesh/operators/bmo_create.c +++ b/source/blender/bmesh/operators/bmo_create.c @@ -1177,10 +1177,10 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) } if (edges1 && BLI_array_count(edges1) > 2 && - BM_edge_share_vert_count(edges1[0], edges1[BLI_array_count(edges1) - 1])) + BM_edge_share_vert_check(edges1[0], edges1[BLI_array_count(edges1) - 1])) { if (edges2 && BLI_array_count(edges2) > 2 && - BM_edge_share_vert_count(edges2[0], edges2[BLI_array_count(edges2) - 1])) + BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1])) { BLI_array_free(edges1); BLI_array_free(edges2); @@ -1193,7 +1193,7 @@ void bmo_edgenet_prepare(BMesh *bm, BMOperator *op) } if (edges2 && BLI_array_count(edges2) > 2 && - BM_edge_share_vert_count(edges2[0], edges2[BLI_array_count(edges2) - 1])) + BM_edge_share_vert_check(edges2[0], edges2[BLI_array_count(edges2) - 1])) { edges2 = NULL; } diff --git a/source/blender/bmesh/operators/bmo_subdivide.c b/source/blender/bmesh/operators/bmo_subdivide.c index 346daf830d0..f6b9b18d716 100644 --- a/source/blender/bmesh/operators/bmo_subdivide.c +++ b/source/blender/bmesh/operators/bmo_subdivide.c @@ -825,7 +825,7 @@ void bmo_subdivide_edges_exec(BMesh *bm, BMOperator *op) } /* make sure the two edges have a valid angle to each other */ - if (totesel == 2 && BM_edge_share_vert_count(e1, e2)) { + if (totesel == 2 && BM_edge_share_vert_check(e1, e2)) { sub_v3_v3v3(vec1, e1->v2->co, e1->v1->co); sub_v3_v3v3(vec2, e2->v2->co, e2->v1->co); normalize_v3(vec1); diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c index 8e5c89adfca..bf4ee0eb61f 100644 --- a/source/blender/editors/mesh/editmesh_loopcut.c +++ b/source/blender/editors/mesh/editmesh_loopcut.c @@ -261,7 +261,7 @@ static void edgering_sel(RingSelOpData *lcd, int previewlines, int select) lasteed = eed; } - if (lasteed != startedge && BM_edge_share_face_count(lasteed, startedge)) { + if (lasteed != startedge && BM_edge_share_face_check(lasteed, startedge)) { v[1][0] = v[0][0]; v[1][1] = v[0][1]; diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c index 80966fee599..38ec0e8bb4c 100644 --- a/source/blender/modifiers/intern/MOD_skin.c +++ b/source/blender/modifiers/intern/MOD_skin.c @@ -1354,24 +1354,6 @@ static void add_quad_from_tris(SkinOutput *so, BMEdge *e, BMFace *adj[2]) add_poly(so, quad[0], quad[1], quad[2], quad[3]); } -/* Returns the number of faces that are adjacent to both f1 and f2 */ -static int BM_face_share_face_count(BMFace *f1, BMFace *f2) -{ - BMIter iter1, iter2; - BMEdge *e; - BMFace *f; - int count = 0; - - BM_ITER_ELEM (e, &iter1, f1, BM_EDGES_OF_FACE) { - BM_ITER_ELEM (f, &iter2, e, BM_FACES_OF_EDGE) { - if (f != f1 && f != f2 && BM_face_share_edge_count(f, f2)) - count++; - } - } - - return count; -} - static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd) { BMIter iter; @@ -1434,7 +1416,7 @@ static void hull_merge_triangles(SkinOutput *so, const SkinModifierData *smd) * share a border with another face, output as a quad */ if (!BM_elem_flag_test(adj[0], BM_ELEM_TAG) && !BM_elem_flag_test(adj[1], BM_ELEM_TAG) && - !BM_face_share_face_count(adj[0], adj[1])) + !BM_face_share_face_check(adj[0], adj[1])) { add_quad_from_tris(so, e, adj); BM_elem_flag_enable(adj[0], BM_ELEM_TAG); From 1d90323637d55cc07cbdc9a5a5005e6dc5eb2b5f Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Fri, 9 Nov 2012 15:00:27 +0000 Subject: [PATCH 053/118] UI scripting: Layout separator should end button aligning. --- source/blender/editors/interface/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index c6e25ab9a34..e2f105b5761 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -2424,7 +2424,7 @@ void uiBlockEndAlign(uiBlock *block) int ui_but_can_align(uiBut *but) { - return !ELEM3(but->type, LABEL, OPTION, OPTIONN); + return !ELEM4(but->type, LABEL, OPTION, OPTIONN, SEPR); } static void ui_block_do_align_but(uiBut *first, short nr) From b67a297d33dc97708940b17ca50401d9277f8bd5 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Fri, 9 Nov 2012 16:00:30 +0000 Subject: [PATCH 054/118] Bevel: use library plane/line intersection instead of custom one. Custom one had a bug, not worth tracking down. --- source/blender/bmesh/operators/bmo_bevel.c | 104 ++------------------- 1 file changed, 8 insertions(+), 96 deletions(-) diff --git a/source/blender/bmesh/operators/bmo_bevel.c b/source/blender/bmesh/operators/bmo_bevel.c index 50d3598dba2..7df5aa8fe9c 100644 --- a/source/blender/bmesh/operators/bmo_bevel.c +++ b/source/blender/bmesh/operators/bmo_bevel.c @@ -463,99 +463,6 @@ static int bev_ccw_test(BMEdge *a, BMEdge *b, BMFace *f) return lb->next == la ? 1 : -1; } -/* - * Search for crossing the line and line - * a1-a2 lineA - * b1-b2 line B - * r - result, coordinate of crossing point - */ -static int find_intersection_point(float r[3], float a1[3], float a2[3], float b1[3], float b2[3]) -{ - double s, t, z1, z2; - double mx, my, nx, ny; - int flag = 0; - - mx = a2[0] - a1[0]; - my = a2[1] - a1[1]; - - nx = b2[0] - b1[0]; - ny = b2[1] - b1[1]; - - s = ((double)(b1[1] - a1[1]) / my + (double)(a1[0] - b1[0]) / mx) / (nx / mx - ny / my); - t = ((double)(b1[0] - a1[0]) + s * nx) / mx; - - - z1 = (double)a1[2] + t * (double)(a2[2] - a1[2]); - z2 = (double)b1[2] + s * (double)(b2[2] - b1[2]); - - if (fabs(z1 - z2) < BEVEL_EPSILON) { - flag = 1; - r[0] = (double)a1[0] + t * mx; - r[1] = (double)a1[1] + t * my; - r[2] = z1; - } - else - flag = 0; - - return flag; -} - -/* - * Search for crossing the line and plane - * p1, p2, p3 points which is given by the plane - * a - line vector - * m - point through which the line - * r - result; - */ -static void find_intersection_point_plane(float r[3], float p1[3], float p2[3], float p3[3], - float a[3], float m[3]) -{ - const double isect_epsilon = 1e-20; - float P[3], N[3], A[3], M[3]; - float vv1[3], vv2[3]; - double t; - double C, D, E; - - - /* calculation of the normal to the surface */ - sub_v3_v3v3(vv1, p1, p2); - sub_v3_v3v3(vv2, p3, p2); - cross_v3_v3v3(N, vv1, vv2); - - copy_v3_v3(A, a); - copy_v3_v3(P, p2); - copy_v3_v3(M, m); - - - if (fabs(N[0] * (A[0] - P[0]) + N[1] * (A[1] - P[1]) + N[2] * (A[2] - P[2])) < BEVEL_EPSILON) { - /* point located on plane */ - float tmp[3], line[3]; - add_v3_v3v3(line, a, m); - if (find_intersection_point(tmp, m, a, p1, p2)) - copy_v3_v3(r, tmp); - else { - if (find_intersection_point(tmp, m, a, p2, p3)) - copy_v3_v3(r, tmp); - } - - } - else { - C = N[0] * P[0] + N[1] * P[1] + N[2] * P[2]; - D = N[0] * M[0] + N[1] * M[1] + N[2] * M[2]; - E = A[0] * N[0] + A[1] * N[1] + A[2] * N[2]; - - if (fabs(E) < isect_epsilon) - t = 0; - else - t = (C - D) / E; - - r[0] = (double)m[0] + t * (double)a[0]; - r[1] = (double)m[1] + t * (double)a[1]; - r[2] = (double)m[2] + t * (double)a[2]; - } - -} - /* * calculation of points on the round profile * r - result, coordinate of point on round profile @@ -612,7 +519,7 @@ static void get_point_on_round_profile(float r[3], float offset, int i, int coun static void get_point_on_round_edge(EdgeHalf *e, int i, float va[3], float vmid[3], float vb[3], float profileco[3]) { - float vva[3], vvb[3], point[3], dir[3], vaadj[3], vbadj[3]; + float vva[3], vvb[3], point[3], dir[3], vaadj[3], vbadj[3], p2[3], pn[3]; int n = e->seg; sub_v3_v3v3(vva, va, vmid); @@ -630,7 +537,12 @@ static void get_point_on_round_edge(EdgeHalf *e, int i, get_point_on_round_profile(point, e->offset, i, n, vaadj, vmid, vbadj); - find_intersection_point_plane(profileco, va, vmid, vb, dir, point); + add_v3_v3v3(p2, profileco, dir); + cross_v3_v3v3(pn, vva, vvb); + if (!isect_line_plane_v3(profileco, point, p2, vmid, pn, 0)) { + BLI_assert(!"bevel: unexpected non-intersection"); + copy_v3_v3(profileco, point); + } } else { /* planar case */ @@ -908,7 +820,7 @@ static void bevel_build_rings(BMesh *bm, BevVert *bv) } while (v != vm->boundstart); /* center point need to be average of all centers of rings */ - /* TODO: this is wrong if not all verts have ebev: could hae + /* TODO: this is wrong if not all verts have ebev: could have * several disconnected sections of mesh. */ zero_v3(midco); nn = 0; From d25b13d13f22581b7ed107f0774d1bd8c510add4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 16:15:00 +0000 Subject: [PATCH 055/118] code cleanup: double promotion warnings, also allow cmake to build SDL without audaspace. --- CMakeLists.txt | 4 +-- source/blender/blenfont/intern/blf_lang.c | 6 ++-- source/blender/blenkernel/intern/ocean.c | 20 ++++++------- source/blender/blenkernel/intern/smoke.c | 28 +++++++++---------- .../blender/blenkernel/intern/writeffmpeg.c | 6 ++-- source/blender/imbuf/intern/indexer.c | 2 +- .../blender/render/intern/source/voxeldata.c | 2 +- .../gameengine/Expressions/PyObjectPlus.cpp | 14 +++++----- .../GameLogic/SCA_RandomActuator.cpp | 10 +++---- source/gameengine/Rasterizer/RAS_TexVert.cpp | 8 +++--- 10 files changed, 49 insertions(+), 51 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e8119ca1fcd..822c77ba094 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -340,8 +340,8 @@ if(NOT WITH_GAMEENGINE AND WITH_PLAYER) message(FATAL_ERROR "WITH_PLAYER requires WITH_GAMEENGINE") endif() -if(NOT WITH_AUDASPACE AND (WITH_OPENAL OR WITH_SDL OR WITH_JACK OR WITH_GAMEENGINE)) - message(FATAL_ERROR "WITH_OPENAL/WITH_SDL/WITH_JACK/WITH_CODEC_FFMPEG/WITH_GAMEENGINE require WITH_AUDASPACE") +if(NOT WITH_AUDASPACE AND (WITH_OPENAL OR WITH_JACK OR WITH_GAMEENGINE)) + message(FATAL_ERROR "WITH_OPENAL/WITH_JACK/WITH_CODEC_FFMPEG/WITH_GAMEENGINE require WITH_AUDASPACE") endif() if(NOT WITH_SDL AND WITH_GHOST_SDL) diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c index 501f8cd2958..f02d4a25554 100644 --- a/source/blender/blenfont/intern/blf_lang.c +++ b/source/blender/blenfont/intern/blf_lang.c @@ -79,9 +79,9 @@ static void free_locales(void) if (locales) { int idx = num_locales_menu - 1; /* Last item does not need to be freed! */ while (idx--) { - MEM_freeN((void*)locales_menu[idx].identifier); - MEM_freeN((void*)locales_menu[idx].name); - MEM_freeN((void*)locales_menu[idx].description); /* Also frees locales's relevant value! */ + MEM_freeN((void *)locales_menu[idx].identifier); + MEM_freeN((void *)locales_menu[idx].name); + MEM_freeN((void *)locales_menu[idx].description); /* Also frees locales's relevant value! */ } idx = num_locales; diff --git a/source/blender/blenkernel/intern/ocean.c b/source/blender/blenkernel/intern/ocean.c index 7bc736d394e..e694a7e7eb3 100644 --- a/source/blender/blenkernel/intern/ocean.c +++ b/source/blender/blenkernel/intern/ocean.c @@ -183,7 +183,7 @@ MINLINE float catrom(float p0, float p1, float p2, float p3, float f) MINLINE float omega(float k, float depth) { - return sqrt(GRAVITY * k * tanh(k * depth)); + return sqrtf(GRAVITY * k * tanhf(k * depth)); } // modified Phillips spectrum @@ -256,8 +256,8 @@ static void add_comlex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl static void mul_complex_f(fftw_complex res, fftw_complex cmpl, float f) { - res[0] = cmpl[0] * f; - res[1] = cmpl[1] * f; + res[0] = cmpl[0] * (double)f; + res[1] = cmpl[1] * (double)f; } static void mul_complex_c(fftw_complex res, fftw_complex cmpl1, fftw_complex cmpl2) @@ -289,8 +289,8 @@ static void exp_complex(fftw_complex res, fftw_complex cmpl) { float r = expf(cmpl[0]); - res[0] = cos(cmpl[1]) * r; - res[1] = sin(cmpl[1]) * r; + res[0] = cosf(cmpl[1]) * r; + res[1] = sinf(cmpl[1]) * r; } float BKE_ocean_jminus_to_foam(float jminus, float coverage) @@ -462,7 +462,7 @@ void BKE_ocean_eval_ij(struct Ocean *oc, struct OceanResult *ocr, int i, int j) i = abs(i) % oc->_M; j = abs(j) % oc->_N; - ocr->disp[1] = oc->_do_disp_y ? oc->_disp_y[i * oc->_N + j] : 0.0f; + ocr->disp[1] = oc->_do_disp_y ? (float)oc->_disp_y[i * oc->_N + j] : 0.0f; if (oc->_do_chop) { ocr->disp[0] = oc->_disp_x[i * oc->_N + j]; @@ -546,7 +546,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, minus_i); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_x[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } @@ -568,7 +568,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, minus_i); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_z[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } @@ -589,7 +589,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kx[i] * o->_kx[i] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_jxx[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } @@ -616,7 +616,7 @@ void BKE_simulate_ocean(struct Ocean *o, float t, float scale, float chop_amount mul_complex_f(mul_param, mul_param, chop_amount); mul_complex_c(mul_param, mul_param, o->_htilda[i * (1 + o->_N / 2) + j]); - mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0 ? 0.0 : o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); + mul_complex_f(mul_param, mul_param, (o->_k[i * (1 + o->_N / 2) + j] == 0.0f ? 0.0f : o->_kz[j] * o->_kz[j] / o->_k[i * (1 + o->_N / 2) + j])); init_complex(o->_fft_in_jzz[i * (1 + o->_N / 2) + j], real_c(mul_param), image_c(mul_param)); } } diff --git a/source/blender/blenkernel/intern/smoke.c b/source/blender/blenkernel/intern/smoke.c index f9925a41177..d96bece2b11 100644 --- a/source/blender/blenkernel/intern/smoke.c +++ b/source/blender/blenkernel/intern/smoke.c @@ -262,21 +262,21 @@ static void smoke_set_domain_from_derivedmesh(SmokeDomainSettings *sds, Object * scale = res / size[0]; sds->scale = size[0] / ob->size[0]; sds->base_res[0] = res; - sds->base_res[1] = (int)(size[1] * scale + 0.5); - sds->base_res[2] = (int)(size[2] * scale + 0.5); + sds->base_res[1] = (int)(size[1] * scale + 0.5f); + sds->base_res[2] = (int)(size[2] * scale + 0.5f); } else if (size[1] > MAX2(size[0], size[2])) { scale = res / size[1]; sds->scale = size[1] / ob->size[1]; - sds->base_res[0] = (int)(size[0] * scale + 0.5); + sds->base_res[0] = (int)(size[0] * scale + 0.5f); sds->base_res[1] = res; - sds->base_res[2] = (int)(size[2] * scale + 0.5); + sds->base_res[2] = (int)(size[2] * scale + 0.5f); } else { scale = res / size[2]; sds->scale = size[2] / ob->size[2]; - sds->base_res[0] = (int)(size[0] * scale + 0.5); - sds->base_res[1] = (int)(size[1] * scale + 0.5); + sds->base_res[0] = (int)(size[0] * scale + 0.5f); + sds->base_res[1] = (int)(size[1] * scale + 0.5f); sds->base_res[2] = res; } @@ -1581,7 +1581,7 @@ BLI_INLINE void apply_inflow_fields(SmokeFlowSettings *sfs, float emission_value if (fuel && fuel[index]) { /* instead of using 1.0 for all new fuel add slight falloff * to reduce flow blockiness */ - float value = 1.0f - pow(1.0f - emission_value, 2.0f); + float value = 1.0f - powf(1.0f - emission_value, 2.0f); if (value > react[index]) { float f = fuel_flow / fuel[index]; @@ -1944,9 +1944,9 @@ static void update_effectors(Scene *scene, Object *ob, SmokeDomainSettings *sds, mul_v3_fl(retvel, mag); // TODO dg - do in force! - force_x[index] = MIN2(MAX2(-1.0, retvel[0] * 0.2), 1.0); - force_y[index] = MIN2(MAX2(-1.0, retvel[1] * 0.2), 1.0); - force_z[index] = MIN2(MAX2(-1.0, retvel[2] * 0.2), 1.0); + force_x[index] = min_ff(max_ff(-1.0f, retvel[0] * 0.2f), 1.0f); + force_y[index] = min_ff(max_ff(-1.0f, retvel[1] * 0.2f), 1.0f); + force_z[index] = min_ff(max_ff(-1.0f, retvel[2] * 0.2f), 1.0f); } } } @@ -1999,7 +1999,7 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh * /* adapt timestep for different framerates, dt = 0.1 is at 25fps */ dt = DT_DEFAULT * (25.0f / fps); // maximum timestep/"CFL" constraint: dt < 5.0 *dx / maxVel - maxVel = (sds->dx * 5.0); + maxVel = (sds->dx * 5.0f); #if 0 for (i = 0; i < size; i++) { @@ -2009,7 +2009,7 @@ static void step(Scene *scene, Object *ob, SmokeModifierData *smd, DerivedMesh * } #endif - maxVelMag = sqrt(maxVelMag) * dt * sds->time_scale; + maxVelMag = sqrtf(maxVelMag) * dt * sds->time_scale; totalSubsteps = (int)((maxVelMag / maxVel) + 1.0f); /* always round up */ totalSubsteps = (totalSubsteps < 1) ? 1 : totalSubsteps; totalSubsteps = (totalSubsteps > maxSubSteps) ? maxSubSteps : totalSubsteps; @@ -2286,7 +2286,7 @@ static float calc_voxel_transp(float *result, float *input, int res[3], int *pix const size_t index = smoke_get_index(pixel[0], res[0], pixel[1], res[1], pixel[2]); // T_ray *= T_vox - *tRay *= exp(input[index] * correct); + *tRay *= expf(input[index] * correct); if (result[index] < 0.0f) { @@ -2386,7 +2386,7 @@ static void smoke_calc_transparency(SmokeDomainSettings *sds, Scene *scene) float light[3]; int a, z, slabsize = sds->res[0] * sds->res[1], size = sds->res[0] * sds->res[1] * sds->res[2]; float *density = smoke_get_density(sds->fluid); - float correct = -7.0 * sds->dx; + float correct = -7.0f * sds->dx; if (!get_lamp(scene, light)) return; diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index 3a8a14290dc..da9c919c109 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -478,9 +478,7 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex c->time_base.den = 2997; c->time_base.num = 100; } - else if ((double) ((int) rd->frs_sec_base) == - rd->frs_sec_base) - { + else if ((float) ((int) rd->frs_sec_base) == rd->frs_sec_base) { c->time_base.den = rd->frs_sec; c->time_base.num = (int) rd->frs_sec_base; } @@ -999,7 +997,7 @@ int BKE_ffmpeg_append(RenderData *rd, int start_frame, int frame, int *pixels, i } #ifdef WITH_AUDASPACE - write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / rd->frs_sec_base)); + write_audio_frames((frame - rd->sfra) / (((double)rd->frs_sec) / (double)rd->frs_sec_base)); #endif return success; } diff --git a/source/blender/imbuf/intern/indexer.c b/source/blender/imbuf/intern/indexer.c index 5dda33dfd62..38bd28452f3 100644 --- a/source/blender/imbuf/intern/indexer.c +++ b/source/blender/imbuf/intern/indexer.c @@ -872,7 +872,7 @@ static void index_rebuild_ffmpeg_proc_decoded_frame( context->frameno = floor((pts - context->start_pts) * context->pts_time_base * - context->frame_rate + 0.5f); + context->frame_rate + 0.5); /* decoding starts *always* on I-Frames, * so: P-Frames won't work, even if all the diff --git a/source/blender/render/intern/source/voxeldata.c b/source/blender/render/intern/source/voxeldata.c index b486407c61c..42849a01971 100644 --- a/source/blender/render/intern/source/voxeldata.c +++ b/source/blender/render/intern/source/voxeldata.c @@ -265,7 +265,7 @@ static void init_frame_smoke(VoxelData *vd, float cfra) /* map velocities between 0 and 0.3f */ for (i = 0; i < totRes; i++) { - vd->dataset[i] = sqrt(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f; + vd->dataset[i] = sqrtf(xvel[i] * xvel[i] + yvel[i] * yvel[i] + zvel[i] * zvel[i]) * 3.0f; } } diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index bb1d0a31c1f..03f9fb5fb19 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -486,8 +486,8 @@ PyObject *PyObjectPlus::py_get_attrdef(PyObject *self_py, const PyAttributeDef * static bool py_check_attr_float(float *var, PyObject *value, const PyAttributeDef *attrdef) { - double val = PyFloat_AsDouble(value); - if (val == -1.0 && PyErr_Occurred()) + float val = PyFloat_AsDouble(value); + if (val == -1.0f && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "expected float value for attribute \"%s\"", attrdef->m_name); return false; @@ -664,13 +664,13 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt { float *var = reinterpret_cast(ptr); ptr += sizeof(float); - double val = PyFloat_AsDouble(item); - if (val == -1.0 && PyErr_Occurred()) + float val = PyFloat_AsDouble(item); + if (val == -1.0f && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "expected a float for attribute \"%s\"", attrdef->m_name); goto UNDO_AND_ERROR; } - else if (attrdef->m_clamp) + else if (attrdef->m_clamp) { if (val < attrdef->m_fmin) val = attrdef->m_fmin; @@ -985,10 +985,10 @@ int PyObjectPlus::py_set_attrdef(PyObject *self_py, PyObject *value, const PyAtt for (int i=0; i<3; i++) { item = PySequence_GetItem(value, i); /* new ref */ - double val = PyFloat_AsDouble(item); + float val = PyFloat_AsDouble(item); Py_DECREF(item); item = NULL; - if (val == -1.0 && PyErr_Occurred()) + if (val == -1.0f && PyErr_Occurred()) { PyErr_Format(PyExc_TypeError, "expected a sequence of 3 floats for attribute \"%s\"", attrdef->m_name); goto RESTORE_AND_ERROR; diff --git a/source/gameengine/GameLogic/SCA_RandomActuator.cpp b/source/gameengine/GameLogic/SCA_RandomActuator.cpp index 2d51a45fe55..01995b13ad7 100644 --- a/source/gameengine/GameLogic/SCA_RandomActuator.cpp +++ b/source/gameengine/GameLogic/SCA_RandomActuator.cpp @@ -220,11 +220,11 @@ bool SCA_RandomActuator::Update() * this will be quite sufficient here. */ do { - x = 2.0 * m_base->DrawFloat() - 1.0; - y = 2.0 * m_base->DrawFloat() - 1.0; - s = x*x + y*y; - } while ( (s >= 1.0) || (s == 0.0) ); - t = x * sqrt( (-2.0 * log(s)) / s); + x = 2.0f * m_base->DrawFloat() - 1.0f; + y = 2.0f * m_base->DrawFloat() - 1.0f; + s = x * x + y * y; + } while ((s >= 1.0f) || (s == 0.0f)); + t = x * sqrtf((-2.0 * log(s)) / s); tmpval = new CFloatValue(m_parameter1 + m_parameter2 * t); } } diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index b60fae73e2a..3b4f4cae30e 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -63,10 +63,10 @@ const MT_Point3& RAS_TexVert::xyz() void RAS_TexVert::SetRGBA(const MT_Vector4& rgba) { unsigned char *colp = (unsigned char*) &m_rgba; - colp[0] = (unsigned char) (rgba[0]*255.0f); - colp[1] = (unsigned char) (rgba[1]*255.0f); - colp[2] = (unsigned char) (rgba[2]*255.0f); - colp[3] = (unsigned char) (rgba[3]*255.0f); + colp[0] = (unsigned char) (rgba[0] * 255.0); + colp[1] = (unsigned char) (rgba[1] * 255.0); + colp[2] = (unsigned char) (rgba[2] * 255.0); + colp[3] = (unsigned char) (rgba[3] * 255.0); } From cf503f5c77f0c78234db5335b0e44f7904ca5f3a Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 9 Nov 2012 16:49:17 +0000 Subject: [PATCH 056/118] Sequencer: disabled sequencer recursion and corrected rendered preview mode Sequencer recursion was never actually supported and only gives lots of issues. Disabled it now, so users are not getting confused by semi-working stuff. Also made a correction to rendered sequencer preview, so now using scene strip in it's own sequencer will work properly (it produced black frames before). This required killing compositor jobs since they could be using the same render result as renderer called from sequencer uses. Small improvements could be: - Add slight delay before compositor job starts handling nodes so killing this job would be fast - Tag compositor to be updated after preview was fully rendered. --- source/blender/blenkernel/intern/sequencer.c | 17 ++++++++++------- .../editors/space_sequencer/sequencer_draw.c | 7 +++++++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index af0cab98fe0..a947a48938e 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2344,6 +2344,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float int do_seq; int have_seq = FALSE; Scene *scene; + int is_thread_main = BLI_thread_is_main(); /* don't refer to seq->scene above this point!, it can be NULL */ if (seq->scene == NULL) { @@ -2373,7 +2374,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float /* prevent eternal loop */ do_seq = context.scene->r.scemode & R_DOSEQ; - context.scene->r.scemode &= ~R_DOSEQ; + scene->r.scemode &= ~R_DOSEQ; #ifdef DURIAN_CAMERA_SWITCH /* stooping to new low's in hackyness :( */ @@ -2383,9 +2384,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float (void)oldmarkers; #endif - if ((sequencer_view3d_cb && do_seq_gl && camera) && - (BLI_thread_is_main() == TRUE) && - ((have_seq == FALSE) || (scene == context.scene))) + if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) { char err_out[256] = "unknown"; /* for old scened this can be uninitialized, @@ -2405,8 +2404,12 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float Render *re = RE_GetRender(scene->id.name); RenderResult rres; - /* XXX: this if can be removed when sequence preview rendering uses the job system */ - if (is_rendering || context.scene != scene) { + /* XXX: this if can be removed when sequence preview rendering uses the job system + * + * disable rendered preview for sequencer while rendering -- it's very much possible + * that preview render will went into conflict with final render + */ + if (!is_thread_main || is_rendering == FALSE) { if (re == NULL) re = RE_NewRender(scene->id.name); @@ -2440,7 +2443,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float } /* restore */ - context.scene->r.scemode |= do_seq; + scene->r.scemode |= do_seq; scene->r.cfra = oldcfra; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index a8103fe2630..37e57a1e850 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -913,6 +913,13 @@ void draw_image_seq(const bContext *C, Scene *scene, ARegion *ar, SpaceSeq *sseq unsigned char *display_buffer; void *cache_handle = NULL; + if (G.is_rendering == FALSE) { + /* stop all running jobs, except screen one. currently previews frustrate Render + * needed to make so sequencer's rendering doesn't conflict with compositor + */ + WM_jobs_kill_all_except(CTX_wm_manager(C), CTX_wm_screen(C)); + } + render_size = sseq->render_size; if (render_size == 0) { render_size = scene->r.size; From b5553f006fbb75e57c052c4a04b1a4e4358ea7ba Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 9 Nov 2012 17:12:39 +0000 Subject: [PATCH 057/118] Fix #30505: bpy.context.copy() gives error running in the properties editor with cycles as render engine. --- .../blender/editors/space_buttons/buttons_context.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/space_buttons/buttons_context.c b/source/blender/editors/space_buttons/buttons_context.c index 9c47c407bd9..2da70468f0c 100644 --- a/source/blender/editors/space_buttons/buttons_context.c +++ b/source/blender/editors/space_buttons/buttons_context.c @@ -680,9 +680,9 @@ void buttons_context_compute(const bContext *C, SpaceButs *sbuts) /************************* Context Callback ************************/ const char *buttons_context_dir[] = { - "world", "object", "mesh", "armature", "lattice", "curve", + "texture_slot", "world", "object", "mesh", "armature", "lattice", "curve", "meta_ball", "lamp", "speaker", "camera", "material", "material_slot", - "texture", "texture_slot", "texture_user", "bone", "edit_bone", + "texture", "texture_user", "bone", "edit_bone", "pose_bone", "particle_system", "particle_system_editable", "particle_settings", "cloth", "soft_body", "fluid", "smoke", "collision", "brush", "dynamic_paint", NULL }; @@ -697,7 +697,12 @@ int buttons_context(const bContext *C, const char *member, bContextDataResult *r /* here we handle context, getting data from precomputed path */ if (CTX_data_dir(member)) { - CTX_data_dir_set(result, buttons_context_dir); + /* in case of new shading system we skip texture_slot, complex python + * UI script logic depends on checking if this is available */ + if (sbuts->texuser) + CTX_data_dir_set(result, buttons_context_dir + 1); + else + CTX_data_dir_set(result, buttons_context_dir); return 1; } else if (CTX_data_equals(member, "world")) { From 46dd1a9167dd55eb6153fb96ae32a465fa8aae16 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Fri, 9 Nov 2012 18:31:04 +0000 Subject: [PATCH 058/118] Cycles / CMake: * Removed PARTIO building code, partio code was removed already. * Include "app" dir only when building with CYCLES_TEST enabled. --- intern/cycles/CMakeLists.txt | 9 ++++----- intern/cycles/app/CMakeLists.txt | 4 ---- intern/cycles/cmake/external_libs.cmake | 27 ------------------------- 3 files changed, 4 insertions(+), 36 deletions(-) diff --git a/intern/cycles/CMakeLists.txt b/intern/cycles/CMakeLists.txt index 7562ee0a0a5..7495a98aed1 100644 --- a/intern/cycles/CMakeLists.txt +++ b/intern/cycles/CMakeLists.txt @@ -44,10 +44,6 @@ if(WITH_CYCLES_OSL) include_directories(${OSL_INCLUDES}) endif() -if(WITH_CYCLES_PARTIO) - add_definitions(-DWITH_PARTIO) -endif() - if(WITH_CYCLES_CUDA_BINARIES) add_definitions(-DWITH_CUDA_BINARIES) endif() @@ -69,7 +65,10 @@ if(WITH_CYCLES_BLENDER) add_subdirectory(blender) endif() -add_subdirectory(app) +if(WITH_CYCLES_TEST) + add_subdirectory(app) +endif() + add_subdirectory(bvh) add_subdirectory(device) add_subdirectory(doc) diff --git a/intern/cycles/app/CMakeLists.txt b/intern/cycles/app/CMakeLists.txt index 83b3f731ffe..3fb8aaf934f 100644 --- a/intern/cycles/app/CMakeLists.txt +++ b/intern/cycles/app/CMakeLists.txt @@ -35,10 +35,6 @@ if(WITH_CYCLES_OSL) list(APPEND LIBRARIES cycles_kernel_osl ${OSL_LIBRARIES}) endif() -if(WITH_CYCLES_PARTIO) - list(APPEND LIBRARIES ${PARTIO_LIBRARIES}) -endif() - include_directories(${INC}) include_directories(SYSTEM ${INC_SYS}) diff --git a/intern/cycles/cmake/external_libs.cmake b/intern/cycles/cmake/external_libs.cmake index 332d3d74715..790049898ff 100644 --- a/intern/cycles/cmake/external_libs.cmake +++ b/intern/cycles/cmake/external_libs.cmake @@ -17,33 +17,6 @@ else() set(CYCLES_GLEW_LIBRARY extern_glew) endif() -########################################################################### -# Partio - -if(WITH_CYCLES_PARTIO) - - set(CYCLES_PARTIO "" CACHE PATH "Path to Partio installation") - - message(STATUS "CYCLES_PARTIO = ${CYCLES_PARTIO}") - - find_library(PARTIO_LIBRARIES NAMES partio PATHS ${CYCLES_PARTIO}/lib) - find_path(PARTIO_INCLUDES Partio.h ${CYCLES_PARTIO}/include) - - find_package(ZLIB) - - if(PARTIO_INCLUDES AND PARTIO_LIBRARIES AND ZLIB_LIBRARIES) - list(APPEND PARTIO_LIBRARIES ${ZLIB_LIBRARIES}) - set(PARTIO_FOUND TRUE) - message(STATUS "PARTIO includes = ${PARTIO_INCLUDES}") - message(STATUS "PARTIO library = ${PARTIO_LIBRARIES}") - else() - message(STATUS "PARTIO not found") - endif() - - include_directories(${PARTIO_INCLUDES}) - -endif() - ########################################################################### # CUDA From dcca228906adfe08610174bb3d402ccb321f19cf Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 9 Nov 2012 20:38:09 +0000 Subject: [PATCH 059/118] Another fix for finding python stuff... Should work for everyone now! (I hope...). --- build_files/cmake/Modules/FindPythonLibsUnix.cmake | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build_files/cmake/Modules/FindPythonLibsUnix.cmake b/build_files/cmake/Modules/FindPythonLibsUnix.cmake index fdf2c29704d..7f272ee5b14 100644 --- a/build_files/cmake/Modules/FindPythonLibsUnix.cmake +++ b/build_files/cmake/Modules/FindPythonLibsUnix.cmake @@ -108,9 +108,10 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_ include/python${PYTHON_VERSION}${_CURRENT_ABI_FLAGS} include/${CMAKE_LIBRARY_ARCHITECTURE}/python${PYTHON_VERSION}${_CURRENT_ABI_FLAGS} ) - IF(NOT PYTHON_INCLUDE_CONFIG_DIR AND PYTHON_INCLUDE_DIR) + IF((NOT PYTHON_INCLUDE_CONFIG_DIR) AND PYTHON_INCLUDE_DIR) # Fallback... - SET(PYTHON_INCLUDE_CONFIG_DIR ${PYTHON_INCLUDE_DIR}) + UNSET(PYTHON_INCLUDE_CONFIG_DIR CACHE) + SET(PYTHON_INCLUDE_CONFIG_DIR ${PYTHON_INCLUDE_DIR} CACHE PATH "") ENDIF() ENDIF() @@ -134,8 +135,9 @@ IF((NOT _IS_INC_DEF) OR (NOT _IS_INC_CONF_DEF) OR (NOT _IS_LIB_DEF) OR (NOT _IS_ PATH_SUFFIXES lib64 lib ) - IF(NOT PYTHON_LIBPATH AND PYTHON_LIBRARY) + IF((NOT PYTHON_LIBPATH) AND PYTHON_LIBRARY) # Fallback... + UNSET(PYTHON_LIBPATH CACHE) GET_FILENAME_COMPONENT(PYTHON_LIBPATH ${PYTHON_LIBRARY} PATH) ENDIF() ENDIF() @@ -177,7 +179,6 @@ INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(PythonLibsUnix DEFAULT_MSG PYTHON_LIBRARY PYTHON_LIBPATH PYTHON_INCLUDE_DIR PYTHON_INCLUDE_CONFIG_DIR) - IF(PYTHONLIBSUNIX_FOUND) # Assign cache items SET(PYTHON_INCLUDE_DIRS ${PYTHON_INCLUDE_DIR} ${PYTHON_INCLUDE_CONFIG_DIR}) From 3f0fe65635a27f2ac20aa0fcecf0a56885cb26c5 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 9 Nov 2012 21:27:05 +0000 Subject: [PATCH 060/118] Fix #32972: cycles crash changing to GPU render with OSL enabled. --- intern/cycles/blender/blender_python.cpp | 2 ++ intern/cycles/render/scene.cpp | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index fbc88f1056f..e78c78e5eb2 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -284,6 +284,8 @@ static PyObject *osl_update_node_func(PyObject *self, PyObject *args) if(param->validdefault) default_string = param->sdefault[0]; } + else + continue; } else continue; diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index a2febc31f60..7834aa701ea 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -44,6 +44,10 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_) device = NULL; memset(&dscene.data, 0, sizeof(dscene.data)); + /* OSL only works on the CPU */ + if(device_info_.type != DEVICE_CPU) + params.shadingsystem = SceneParams::SVM; + camera = new Camera(); filter = new Filter(); film = new Film(); From 5fab174031ef6aee5c7481195ebd06358164ff12 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Fri, 9 Nov 2012 21:44:31 +0000 Subject: [PATCH 061/118] Cycles Test App: * Remove outdated hard coded path from path_init(). --- intern/cycles/app/cycles_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/app/cycles_test.cpp b/intern/cycles/app/cycles_test.cpp index e921cc46fe4..625e8cc1706 100644 --- a/intern/cycles/app/cycles_test.cpp +++ b/intern/cycles/app/cycles_test.cpp @@ -326,7 +326,7 @@ using namespace ccl; int main(int argc, const char **argv) { - path_init("../build/bin/2.59/scripts/addons/cycles/"); + path_init(); options_parse(argc, argv); From 4bcf0358a80180eecacec5e7f663e41e6564e22a Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Fri, 9 Nov 2012 22:01:37 +0000 Subject: [PATCH 062/118] Cycles / OSL: * UI fix for "shading_system" property, own fault from r51120 --- intern/cycles/blender/addon/ui.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index d8d8c11baa6..9ecd0d3e252 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -957,7 +957,7 @@ def draw_device(self, context): elif device_type == 'OPENCL' and cscene.feature_set == 'EXPERIMENTAL': layout.prop(cscene, "device") - if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'None'): + if engine.with_osl() and (cscene.device == 'CPU' or device_type == 'NONE'): layout.prop(cscene, "shading_system") From b3fb373f89c1caa1d596414bcac9a2ca96f98348 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 9 Nov 2012 22:08:51 +0000 Subject: [PATCH 063/118] Cycles OSL: auto update script node sockets when setting text datablock or filepath. --- source/blender/makesrna/intern/rna_nodetree.c | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 67e876b70a0..33a41ff6f6e 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -220,6 +220,7 @@ EnumPropertyItem prop_wave_items[] = { #include "ED_node.h" +#include "RE_engine.h" #include "RE_pipeline.h" #include "DNA_scene_types.h" @@ -1133,6 +1134,22 @@ static IDProperty *rna_ShaderNodeScript_idprops(PointerRNA *ptr, int create) return nss->prop; } +static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + bNodeTree *ntree = (bNodeTree *)ptr->id.data; + bNode *node = (bNode *)ptr->data; + RenderEngineType *engine_type = RE_engines_find(scene->r.engine); + + if(engine_type && engine_type->update_script_node) { + /* auto update node */ + RenderEngine *engine = RE_engine_create(engine_type); + engine_type->update_script_node(engine, ntree, node); + RE_engine_free(engine); + } + + node_update(bmain, scene, ntree, node); +} + #else static EnumPropertyItem prop_image_layer_items[] = { @@ -1930,14 +1947,14 @@ static void def_sh_script(StructRNA *srna) RNA_def_property_struct_type(prop, "Text"); RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_REFCOUNT); RNA_def_property_ui_text(prop, "Script", "Internal shader script to define the shader"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScript_update"); RNA_def_struct_sdna_from(srna, "NodeShaderScript", "storage"); RNA_def_struct_idprops_func(srna, "rna_ShaderNodeScript_idprops"); prop = RNA_def_property(srna, "filepath", PROP_STRING, PROP_FILEPATH); RNA_def_property_ui_text(prop, "File Path", "Shader script path"); - RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update"); + RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_ShaderNodeScript_update"); prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE); RNA_def_property_enum_funcs(prop, NULL, "rna_ShaderNodeScript_mode_set", NULL); From 09b34e69d4c5fb4bc305f84188959bb49d1979f2 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 9 Nov 2012 23:28:51 +0000 Subject: [PATCH 064/118] Fix #33131: more useful cycles behavior for layers that are both marked excluded and as mask layer. Now it will still use the mask, and have no further influence rather than just being excluded entirely. --- intern/cycles/blender/blender_object.cpp | 5 +++++ intern/cycles/blender/blender_sync.cpp | 11 +++++++++-- intern/cycles/blender/blender_sync.h | 4 +++- intern/cycles/render/light.cpp | 8 ++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index a18cb79c102..67255d9f707 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -253,6 +253,7 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P if(use_holdout != object->use_holdout) { object->use_holdout = use_holdout; scene->object_manager->tag_update(scene); + object_updated = true; } /* object sync @@ -278,6 +279,10 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P object->random_id ^= hash_int(hash_string(b_parent.name().c_str())); } + /* make holdout objects on excluded layer invisible for non-camera rays */ + if(use_holdout && (layer_flag & render_layer.exclude_layer)) + object->visibility &= ~(PATH_RAY_ALL - PATH_RAY_CAMERA); + /* camera flag is not actually used, instead is tested * against render layer flags */ if(object->visibility & PATH_RAY_CAMERA) { diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index eacfbdadba0..ce589f55e60 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -241,6 +241,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) render_layer.use_localview = (b_v3d.local_view() ? true : false); render_layer.scene_layer = get_layer(b_v3d.layers(), b_v3d.layers_local_view(), render_layer.use_localview); render_layer.layer = render_layer.scene_layer; + render_layer.exclude_layer = 0; render_layer.holdout_layer = 0; render_layer.material_override = PointerRNA_NULL; render_layer.use_background = true; @@ -258,10 +259,16 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) for(r.layers.begin(b_rlay); b_rlay != r.layers.end(); ++b_rlay) { if((!layer && first_layer) || (layer && b_rlay->name() == layer)) { render_layer.name = b_rlay->name(); - render_layer.scene_layer = get_layer(b_scene.layers()) & ~get_layer(b_rlay->layers_exclude()); - render_layer.layer = get_layer(b_rlay->layers()); + render_layer.holdout_layer = get_layer(b_rlay->layers_zmask()); + render_layer.exclude_layer = get_layer(b_rlay->layers_exclude()); + + render_layer.scene_layer = get_layer(b_scene.layers()) & ~render_layer.exclude_layer; + render_layer.scene_layer |= render_layer.exclude_layer & render_layer.holdout_layer; + + render_layer.layer = get_layer(b_rlay->layers()); render_layer.layer |= render_layer.holdout_layer; + render_layer.material_override = b_rlay->material_override(); render_layer.use_background = b_rlay->use_sky(); render_layer.use_viewport_visibility = false; diff --git a/intern/cycles/blender/blender_sync.h b/intern/cycles/blender/blender_sync.h index 9a478118c04..71781bc5459 100644 --- a/intern/cycles/blender/blender_sync.h +++ b/intern/cycles/blender/blender_sync.h @@ -116,7 +116,8 @@ private: struct RenderLayerInfo { RenderLayerInfo() - : scene_layer(0), layer(0), holdout_layer(0), + : scene_layer(0), layer(0), + holdout_layer(0), exclude_layer(0), material_override(PointerRNA_NULL), use_background(true), use_viewport_visibility(false), @@ -127,6 +128,7 @@ private: uint scene_layer; uint layer; uint holdout_layer; + uint exclude_layer; BL::Material material_override; bool use_background; bool use_viewport_visibility; diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp index d77516a1b18..4173da453fd 100644 --- a/intern/cycles/render/light.cpp +++ b/intern/cycles/render/light.cpp @@ -147,6 +147,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen Mesh *mesh = object->mesh; bool have_emission = false; + /* skip if we are not visible for BSDFs */ + if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) + continue; + /* skip if we have no emission shaders */ foreach(uint sindex, mesh->used_shaders) { Shader *shader = scene->shaders[sindex]; @@ -183,6 +187,10 @@ void LightManager::device_update_distribution(Device *device, DeviceScene *dscen Mesh *mesh = object->mesh; bool have_emission = false; + /* skip if we are not visible for BSDFs */ + if(!(object->visibility & (PATH_RAY_DIFFUSE|PATH_RAY_GLOSSY|PATH_RAY_TRANSMIT))) + continue; + /* skip if we have no emission shaders */ foreach(uint sindex, mesh->used_shaders) { Shader *shader = scene->shaders[sindex]; From 5a29885007c66752adbdcd62cdac5e7749f083fd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 23:47:06 +0000 Subject: [PATCH 065/118] code cleanup: bge static functions & use C++ guarded alloc for the character class. --- source/gameengine/GamePlayer/ghost/GPG_ghost.cpp | 6 +++--- source/gameengine/Ketsji/KX_CharacterWrapper.h | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 725c23c60e3..54457d0efdf 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -172,7 +172,7 @@ static BOOL scr_saver_init(int argc, char **argv) #endif /* WIN32 */ -void usage(const char* program, bool isBlenderPlayer) +static void usage(const char* program, bool isBlenderPlayer) { const char * consoleoption; const char * example_filename = ""; @@ -332,7 +332,7 @@ static BlendFileData *load_game_data(const char *progname, char *filename = NULL return bfd; } -bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exitcode, STR_String &exitstring, GlobalSettings *gs) +static bool GPG_NextFrame(GHOST_ISystem* system, GPG_Application *app, int &exitcode, STR_String &exitstring, GlobalSettings *gs) { bool run = true; system->processEvents(false); @@ -352,7 +352,7 @@ struct GPG_NextFrameState { GlobalSettings *gs; } gpg_nextframestate; -int GPG_PyNextFrame(void *state0) +static int GPG_PyNextFrame(void *state0) { GPG_NextFrameState *state = (GPG_NextFrameState *) state0; int exitcode; diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h index cc99aba99f6..04303064645 100644 --- a/source/gameengine/Ketsji/KX_CharacterWrapper.h +++ b/source/gameengine/Ketsji/KX_CharacterWrapper.h @@ -30,6 +30,10 @@ public: private: PHY_ICharacter* m_character; + +#ifdef WITH_CXX_GUARDEDALLOC + MEM_CXX_CLASS_ALLOC_FUNCS("GE:KX_CharacterWrapper") +#endif }; #endif //__KX_CHARACTERWRAPPER_H__ From 7d03e5c615a71fea9223d4fa4fb3bf4e98190c8c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 9 Nov 2012 23:54:58 +0000 Subject: [PATCH 066/118] Fix part of #33132: render resoltuion refresh issues after persistent images was added for cycles. This fixes the case where the option is disabled. I moved the option now to Blender itself and made it keep the engine around only when it's enabled. Also fixes case where there could be issues when switching to another renderer. --- intern/cycles/blender/addon/properties.py | 6 ------ intern/cycles/blender/addon/ui.py | 2 +- intern/cycles/blender/blender_sync.cpp | 3 ++- source/blender/editors/render/render_update.c | 3 +++ source/blender/makesdna/DNA_scene_types.h | 11 ++++++----- source/blender/makesrna/intern/rna_scene.c | 12 ++++++++++++ source/blender/render/extern/include/RE_pipeline.h | 2 ++ .../blender/render/intern/source/external_engine.c | 5 +++++ source/blender/render/intern/source/pipeline.c | 14 ++++++++++++++ 9 files changed, 45 insertions(+), 13 deletions(-) diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 32b07f47ba8..0b8ca6e0fbe 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -297,12 +297,6 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=False, ) - cls.use_persistent_images = BoolProperty( - name="Persistent Images", - description="Keep images loaded on the device so they could be reused by next render", - default=False, - ) - @classmethod def unregister(cls): del bpy.types.Scene.cycles diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index 9ecd0d3e252..4a651eb5aab 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -218,7 +218,7 @@ class CyclesRender_PT_performance(CyclesButtonsPanel, Panel): sub = col.column(align=True) sub.label(text="Final Render:") - sub.prop(cscene, "use_persistent_images") + sub.prop(rd, "use_persistent_data", text="Persistent Images") class CyclesRender_PT_layers(CyclesButtonsPanel, Panel): diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index ce589f55e60..9ebdcfd04bd 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -284,6 +284,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer) SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background) { + BL::RenderSettings r = b_scene.render(); SceneParams params; PointerRNA cscene = RNA_pointer_get(&b_scene.ptr, "cycles"); int shadingsystem = RNA_enum_get(&cscene, "shading_system"); @@ -301,7 +302,7 @@ SceneParams BlenderSync::get_scene_params(BL::Scene b_scene, bool background) params.use_bvh_spatial_split = RNA_boolean_get(&cscene, "debug_use_spatial_splits"); params.use_bvh_cache = (background)? RNA_boolean_get(&cscene, "use_cache"): false; - params.persistent_images = (background)? RNA_boolean_get(&cscene, "use_persistent_images"): false; + params.persistent_images = (background)? r.use_persistent_data(): false; return params; } diff --git a/source/blender/editors/render/render_update.c b/source/blender/editors/render/render_update.c index 0a2ca379518..5155f1001ab 100644 --- a/source/blender/editors/render/render_update.c +++ b/source/blender/editors/render/render_update.c @@ -58,6 +58,7 @@ #include "GPU_material.h" #include "RE_engine.h" +#include "RE_pipeline.h" #include "ED_node.h" #include "ED_render.h" @@ -157,6 +158,8 @@ void ED_render_engine_changed(Main *bmain) for (sc = bmain->screen.first; sc; sc = sc->id.next) for (sa = sc->areabase.first; sa; sa = sa->next) ED_render_engine_area_exit(sa); + + RE_FreePersistentData(); } /***************************** Updates *********************************** diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h index 1479d5268ed..251e6a7eb4e 100644 --- a/source/blender/makesdna/DNA_scene_types.h +++ b/source/blender/makesdna/DNA_scene_types.h @@ -1187,11 +1187,12 @@ typedef struct Scene { /* Use the same flag for autothreads */ #define R_FIXED_THREADS 0x80000 -#define R_SPEED 0x100000 -#define R_SSS 0x200000 -#define R_NO_OVERWRITE 0x400000 /* skip existing files */ -#define R_TOUCH 0x800000 /* touch files before rendering */ -#define R_SIMPLIFY 0x1000000 +#define R_SPEED 0x100000 +#define R_SSS 0x200000 +#define R_NO_OVERWRITE 0x400000 /* skip existing files */ +#define R_TOUCH 0x800000 /* touch files before rendering */ +#define R_SIMPLIFY 0x1000000 +#define R_PERSISTENT_DATA 0x2000000 /* keep data around for re-render */ /* seq_flag */ #define R_SEQ_GL_PREV 1 diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index b102d463195..5e4eb526b76 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -1254,6 +1254,12 @@ static void rna_Scene_simplify_update(Main *bmain, Scene *scene, PointerRNA *ptr rna_Scene_use_simplify_update(bmain, scene, ptr); } +static void rna_Scene_use_persistent_data_update(Main *bmain, Scene *scene, PointerRNA *UNUSED(ptr)) +{ + if (!(scene->r.mode & R_PERSISTENT_DATA)) + RE_FreePersistentData(); +} + static int rna_Scene_use_audio_get(PointerRNA *ptr) { Scene *scene = (Scene *)ptr->data; @@ -4036,6 +4042,12 @@ static void rna_def_scene_render_data(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "simplify_flag", R_SIMPLE_NO_TRIANGULATE); RNA_def_property_ui_text(prop, "Skip Quad to Triangles", "Disable non-planar quads being triangulated"); + /* persistent data */ + prop = RNA_def_property(srna, "use_persistent_data", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_boolean_sdna(prop, NULL, "mode", R_PERSISTENT_DATA); + RNA_def_property_ui_text(prop, "Persistent Data", "Keep render data around for faster re-renders"); + RNA_def_property_update(prop, 0, "rna_Scene_use_persistent_data_update"); + /* Scene API */ RNA_api_scene_render(srna); } diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 984b1a8e651..ecdd1774221 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -170,6 +170,8 @@ void RE_FreeRender (struct Render *re); void RE_FreeAllRender (void); /* only call on file load */ void RE_FreeAllRenderResults(void); +/* for external render engines that can keep persistent data */ +void RE_FreePersistentData(void); /* get results and statistics */ void RE_FreeRenderResult(struct RenderResult *rr); diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index 736cb5de7c3..d771cf2253d 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -382,6 +382,11 @@ int RE_engine_render(Render *re, int do_all) if (type->render) type->render(engine, re->scene); + if(!(re->r.mode & R_PERSISTENT_DATA)) { + RE_engine_free(re->engine); + re->engine = NULL; + } + if (re->result->do_exr_tile) { BLI_rw_mutex_lock(&re->resultmutex, THREAD_LOCK_WRITE); render_result_exr_file_end(re); diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 369818d37d5..3797430952c 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -244,6 +244,7 @@ Render *RE_GetRender(const char *name) return re; } + /* if you want to know exactly what has been done */ RenderResult *RE_AcquireResultRead(Render *re) { @@ -424,6 +425,19 @@ void RE_FreeAllRenderResults(void) } } +void RE_FreePersistentData() +{ + Render *re; + + /* render engines can be kept around for quick re-render, this clears all */ + for (re = RenderGlobal.renderlist.first; re; re = re->next) { + if (re->engine) { + RE_engine_free(re); + re->engine = NULL; + } + } +} + /* ********* initialize state ******** */ From 9117828902d6992ad18f41fd0aaa0f3406d698dd Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Nov 2012 23:59:16 +0000 Subject: [PATCH 067/118] fix for crashes running the BGE without colorspace enabled. --- source/blender/imbuf/intern/colormanagement.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index aadf547260d..b9774a9f7b0 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -890,7 +890,7 @@ void colormanage_imbuf_make_linear(ImBuf *ibuf, const char *from_colorspace) { ColorSpace *colorspace = colormanage_colorspace_get_named(from_colorspace); - if (colorspace->is_data) { + if (colorspace && colorspace->is_data) { ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; return; } @@ -1083,7 +1083,7 @@ void IMB_colormanagement_check_is_data(ImBuf *ibuf, const char *name) { ColorSpace *colorspace = colormanage_colorspace_get_named(name); - if (colorspace->is_data) + if (colorspace && colorspace->is_data) ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; else ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; @@ -1095,7 +1095,7 @@ void IMB_colormanagement_assign_float_colorspace(ImBuf *ibuf, const char *name) ibuf->float_colorspace = colorspace; - if (colorspace->is_data) + if (colorspace && colorspace->is_data) ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; else ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; @@ -1107,7 +1107,7 @@ void IMB_colormanagement_assign_rect_colorspace(ImBuf *ibuf, const char *name) ibuf->rect_colorspace = colorspace; - if (colorspace->is_data) + if (colorspace && colorspace->is_data) ibuf->colormanage_flag |= IMB_COLORMANAGE_IS_DATA; else ibuf->colormanage_flag &= ~IMB_COLORMANAGE_IS_DATA; From 026e29a042d1eb890e732ea94ba6dd4f5af68917 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 10 Nov 2012 02:38:16 +0000 Subject: [PATCH 068/118] simple optimization for library loading, just reduce pointer indirection and use unsigned int's, gives up to 2x overall speedup for loading some libraries. --- source/blender/blenloader/intern/readfile.c | 39 +++++++++++---------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 126c86d3b16..30331713463 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -360,36 +360,39 @@ static void *oldnewmap_lookup_and_inc(OldNewMap *onm, void *addr) } /* for libdata, nr has ID code, no increment */ -static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib) +static void *oldnewmap_liblookup(OldNewMap *onm, void *addr, void *lib) { - int i; - - if (addr == NULL) return NULL; - + if (addr == NULL) { + return NULL; + } + /* lasthit works fine for non-libdata, linking there is done in same sequence as writing */ if (onm->sorted) { OldNew entry_s, *entry; - + entry_s.old = addr; - + entry = bsearch(&entry_s, onm->entries, onm->nentries, sizeof(OldNew), verg_oldnewmap); if (entry) { ID *id = entry->newp; - + if (id && (!lib || id->lib)) { - return entry->newp; + return id; } } } - - for (i = 0; i < onm->nentries; i++) { - OldNew *entry = &onm->entries[i]; - - if (entry->old == addr) { - ID *id = entry->newp; - - if (id && (!lib || id->lib)) { - return entry->newp; + else { + /* note, this can be a bottle neck when loading some files */ + unsigned int nentries = (unsigned int)onm->nentries; + unsigned int i; + OldNew *entry; + + for (i = 0, entry = onm->entries; i < nentries; i++, entry++) { + if (entry->old == addr) { + ID *id = id = entry->newp; + if (id && (!lib || id->lib)) { + return id; + } } } } From 8a89515393612acf03be3f8f667a9cb225338ed4 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 10 Nov 2012 02:45:56 +0000 Subject: [PATCH 069/118] Fix #33084: lock camera to view + view smooth disabled incorrectly moved the camera when going into camera view (bug in revision 51256). --- source/blender/editors/space_view3d/view3d_view.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_view.c b/source/blender/editors/space_view3d/view3d_view.c index c16f04f01f3..714898fed21 100644 --- a/source/blender/editors/space_view3d/view3d_view.c +++ b/source/blender/editors/space_view3d/view3d_view.c @@ -247,9 +247,9 @@ void view3d_smooth_view(bContext *C, View3D *v3d, ARegion *ar, Object *oldcamera copy_qt_qt(rv3d->viewquat, sms.new_quat); rv3d->dist = sms.new_dist; v3d->lens = sms.new_lens; - } - ED_view3d_camera_lock_sync(v3d, rv3d); + ED_view3d_camera_lock_sync(v3d, rv3d); + } if (rv3d->viewlock & RV3D_BOXVIEW) view3d_boxview_copy(sa, ar); From 489e9cb7881ccf70153b125d34e148b96497ef8d Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 10 Nov 2012 03:05:08 +0000 Subject: [PATCH 070/118] Fix part of #31080: missing UV editor redraw after edge slide with correct UVs. --- source/blender/editors/transform/transform.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 1334db63865..896a2d3b66e 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -526,6 +526,10 @@ static void viewRedrawPost(bContext *C, TransInfo *t) /* if autokeying is enabled, send notifiers that keyframes were added */ if (IS_AUTOKEY_ON(t->scene)) WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + /* redraw UV editor */ + if (t->mode == TFM_EDGE_SLIDE && (t->settings->uvcalc_flag & UVCALC_TRANSFORM_CORRECT)) + WM_event_add_notifier(C, NC_GEOM | ND_DATA, NULL); /* XXX temp, first hack to get auto-render in compositor work (ton) */ WM_event_add_notifier(C, NC_SCENE | ND_TRANSFORM_DONE, CTX_data_scene(C)); From f6a110d6ea99b10be72203dee44175624adafa82 Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Sat, 10 Nov 2012 03:11:18 +0000 Subject: [PATCH 071/118] BGE: Committing patch [#32697] "New BGE gravity API" by HG1. This patch adds a gravity attribute to KX_Scene. --- doc/python_api/rst/bge.types.rst | 6 ++++ source/gameengine/Ketsji/KX_Scene.cpp | 33 ++++++++++++++++++- source/gameengine/Ketsji/KX_Scene.h | 3 ++ .../Physics/Dummy/DummyPhysicsEnvironment.cpp | 5 +-- .../Physics/Dummy/DummyPhysicsEnvironment.h | 1 + .../Physics/common/PHY_IPhysicsEnvironment.h | 1 + 6 files changed, 46 insertions(+), 3 deletions(-) diff --git a/doc/python_api/rst/bge.types.rst b/doc/python_api/rst/bge.types.rst index fdaeb61173f..431b264ba73 100644 --- a/doc/python_api/rst/bge.types.rst +++ b/doc/python_api/rst/bge.types.rst @@ -3113,6 +3113,12 @@ Types :type: list + .. attribute:: gravity + + The scene gravity using the world x, y and z axis. + + :type: list [fx, fy, fz] + .. method:: addObject(object, other, time=0) Adds an object to the scene like the Add Object Actuator would. diff --git a/source/gameengine/Ketsji/KX_Scene.cpp b/source/gameengine/Ketsji/KX_Scene.cpp index 96b4a21a36c..72be5f57b95 100644 --- a/source/gameengine/Ketsji/KX_Scene.cpp +++ b/source/gameengine/Ketsji/KX_Scene.cpp @@ -55,7 +55,7 @@ #include "SCA_BasicEventManager.h" #include "KX_Camera.h" #include "SCA_JoystickManager.h" - +#include "KX_PyMath.h" #include "RAS_MeshObject.h" #include "RAS_IRasterizer.h" @@ -1706,6 +1706,17 @@ void KX_Scene::SetGravity(const MT_Vector3& gravity) GetPhysicsEnvironment()->setGravity(gravity[0],gravity[1],gravity[2]); } +MT_Vector3 KX_Scene::GetGravity() +{ + PHY__Vector3 gravity; + MT_Vector3 vec; + + GetPhysicsEnvironment()->getGravity(gravity); + vec = gravity.m_vec; + + return vec; +} + void KX_Scene::SetSceneConverter(class KX_BlenderSceneConverter* sceneConverter) { m_sceneConverter = sceneConverter; @@ -2270,6 +2281,25 @@ int KX_Scene::pyattr_set_drawing_callback_post(void *self_v, const KX_PYATTRIBUT return PY_SET_ATTR_SUCCESS; } +PyObject *KX_Scene::pyattr_get_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) +{ + KX_Scene* self = static_cast(self_v); + + return PyObjectFrom(self->GetGravity()); +} + +int KX_Scene::pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value) +{ + KX_Scene* self = static_cast(self_v); + + MT_Vector3 vec; + if (!PyVecTo(value, vec)) + return PY_SET_ATTR_FAIL; + + self->SetGravity(vec); + return PY_SET_ATTR_SUCCESS; +} + PyAttributeDef KX_Scene::Attributes[] = { KX_PYATTRIBUTE_RO_FUNCTION("name", KX_Scene, pyattr_get_name), KX_PYATTRIBUTE_RO_FUNCTION("objects", KX_Scene, pyattr_get_objects), @@ -2280,6 +2310,7 @@ PyAttributeDef KX_Scene::Attributes[] = { KX_PYATTRIBUTE_RW_FUNCTION("active_camera", KX_Scene, pyattr_get_active_camera, pyattr_set_active_camera), KX_PYATTRIBUTE_RW_FUNCTION("pre_draw", KX_Scene, pyattr_get_drawing_callback_pre, pyattr_set_drawing_callback_pre), KX_PYATTRIBUTE_RW_FUNCTION("post_draw", KX_Scene, pyattr_get_drawing_callback_post, pyattr_set_drawing_callback_post), + KX_PYATTRIBUTE_RW_FUNCTION("gravity", KX_Scene, pyattr_get_gravity, pyattr_set_gravity), KX_PYATTRIBUTE_BOOL_RO("suspended", KX_Scene, m_suspend), KX_PYATTRIBUTE_BOOL_RO("activity_culling", KX_Scene, m_activity_culling), KX_PYATTRIBUTE_FLOAT_RW("activity_culling_radius", 0.5f, FLT_MAX, KX_Scene, m_activity_box_radius), diff --git a/source/gameengine/Ketsji/KX_Scene.h b/source/gameengine/Ketsji/KX_Scene.h index c2e468e6da6..29473949535 100644 --- a/source/gameengine/Ketsji/KX_Scene.h +++ b/source/gameengine/Ketsji/KX_Scene.h @@ -573,6 +573,7 @@ public: void SetPhysicsEnvironment(class PHY_IPhysicsEnvironment* physEnv); void SetGravity(const MT_Vector3& gravity); + MT_Vector3 GetGravity(); short GetAnimationFPS(); @@ -616,6 +617,8 @@ public: static int pyattr_set_drawing_callback_pre(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); static PyObject* pyattr_get_drawing_callback_post(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef); static int pyattr_set_drawing_callback_post(void *selv_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); + static PyObject* pyattr_get_gravity(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static int pyattr_set_gravity(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef, PyObject *value); virtual PyObject *py_repr(void) { return PyUnicode_From_STR_String(GetName()); } diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp index d1a8143fa88..d1fabba18f9 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.cpp @@ -85,8 +85,9 @@ void DummyPhysicsEnvironment::setGravity(float x,float y,float z) { } - - +void DummyPhysicsEnvironment::getGravity(PHY__Vector3& grav) +{ +} diff --git a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h index 233c4412d9e..5ce34bdf7cf 100644 --- a/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h +++ b/source/gameengine/Physics/Dummy/DummyPhysicsEnvironment.h @@ -56,6 +56,7 @@ public: virtual float getFixedTimeStep(); virtual void setGravity(float x,float y,float z); + virtual void getGravity(PHY__Vector3& grav); virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type, float pivotX,float pivotY,float pivotZ, diff --git a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h index 077d225903c..bfbe570ad0c 100644 --- a/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h +++ b/source/gameengine/Physics/common/PHY_IPhysicsEnvironment.h @@ -143,6 +143,7 @@ class PHY_IPhysicsEnvironment virtual void setUseEpa(bool epa) {} virtual void setGravity(float x,float y,float z)=0; + virtual void getGravity(PHY__Vector3& grav) = 0; virtual int createConstraint(class PHY_IPhysicsController* ctrl,class PHY_IPhysicsController* ctrl2,PHY_ConstraintType type, float pivotX,float pivotY,float pivotZ, From 819ca0accc482226e28d756f1311a30cfd740834 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 10 Nov 2012 04:59:32 +0000 Subject: [PATCH 072/118] Fixes for movie distortion node - Somehow this node was using nearest interpolation which seems have been passed from compositor node. It was using b-spline interpolation with old compositor implementation. Now forced this node to use bilinear interpolation, which should be close enough. - Operation should be marked as complex it seems, otherwise area of interest wouldn't make any affect on it's behavior. --- .../compositor/operations/COM_MovieDistortionOperation.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index df48c7a6716..7106b015fe6 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -49,7 +49,9 @@ MovieDistortionOperation::MovieDistortionOperation(bool distortion) : NodeOperat this->m_movieClip = NULL; this->m_cache = NULL; this->m_distortion = distortion; + setComplex(true); } + void MovieDistortionOperation::initExecution() { this->m_inputOperation = this->getInputSocketReader(0); @@ -105,10 +107,10 @@ void MovieDistortionOperation::executePixel(float output[4], float x, float y, P if (this->m_cache != NULL) { float u, v; this->m_cache->getUV(&this->m_movieClip->tracking, x, y, &u, &v); - this->m_inputOperation->read(output, u, v, sampler); + this->m_inputOperation->read(output, u, v, COM_PS_BILINEAR); } else { - this->m_inputOperation->read(output, x, y, sampler); + this->m_inputOperation->read(output, x, y, COM_PS_BILINEAR); } } From e5a9bd51ffee9e601188352131e91013225c9d29 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 10 Nov 2012 04:59:52 +0000 Subject: [PATCH 073/118] Updated stubs to make blender player compilable --- source/blender/render/intern/source/pipeline.c | 2 +- source/blenderplayer/bad_level_call_stubs/stubs.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 3797430952c..971ea65ba73 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -425,7 +425,7 @@ void RE_FreeAllRenderResults(void) } } -void RE_FreePersistentData() +void RE_FreePersistentData(void) { Render *re; diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index 3dcfecac542..5e38dad74ed 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -461,6 +461,8 @@ ListBase R_engines = {NULL, NULL}; void RE_engine_free(struct RenderEngine *engine) {} struct RenderEngineType *RE_engines_find(const char *idname) { return NULL; } void RE_engine_update_memory_stats(struct RenderEngine *engine, float mem_used, float mem_peak) {}; +struct RenderEngine *RE_engine_create(struct RenderEngineType *type) { return NULL; }; +void RE_FreePersistentData(void) {} /* python */ struct wmOperatorType *WM_operatortype_find(const char *idname, int quiet) {return (struct wmOperatorType *) NULL;} From fc2b52b837daa5d92848d3afc71bddc58d8e92e5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 10 Nov 2012 05:03:45 +0000 Subject: [PATCH 074/118] Fix for wrong usage of RE_engine_free --- source/blender/render/intern/source/pipeline.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/render/intern/source/pipeline.c b/source/blender/render/intern/source/pipeline.c index 971ea65ba73..85cafa07759 100644 --- a/source/blender/render/intern/source/pipeline.c +++ b/source/blender/render/intern/source/pipeline.c @@ -432,7 +432,7 @@ void RE_FreePersistentData(void) /* render engines can be kept around for quick re-render, this clears all */ for (re = RenderGlobal.renderlist.first; re; re = re->next) { if (re->engine) { - RE_engine_free(re); + RE_engine_free(re->engine); re->engine = NULL; } } From 936f0388e843ba3a261b364d633eb3bdd5b3ca99 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 10 Nov 2012 05:42:50 +0000 Subject: [PATCH 075/118] code cleanup: some warnings and formatting for PyMethodDef's in the BGE. --- intern/guardedalloc/cpp/mallocn.cpp | 3 +++ .../Converter/BL_ArmatureChannel.cpp | 2 +- .../Converter/BL_ArmatureConstraint.cpp | 2 +- .../Converter/BL_ArmatureObject.cpp | 1 - .../Converter/KX_BlenderSceneConverter.cpp | 11 +++++++--- .../gameengine/Expressions/PyObjectPlus.cpp | 2 +- .../gameengine/GameLogic/SCA_ILogicBrick.cpp | 2 +- .../gameengine/Ketsji/KX_CharacterWrapper.h | 6 +---- source/gameengine/Ketsji/KX_MeshProxy.cpp | 14 ++++++------ .../Ketsji/KX_SCA_AddObjectActuator.cpp | 4 ++-- .../Ketsji/KX_SCA_EndObjectActuator.cpp | 2 +- source/gameengine/Ketsji/KX_VertexProxy.cpp | 22 +++++++++---------- .../gameengine/VideoTexture/ImageRender.cpp | 2 +- 13 files changed, 38 insertions(+), 35 deletions(-) diff --git a/intern/guardedalloc/cpp/mallocn.cpp b/intern/guardedalloc/cpp/mallocn.cpp index da77f0e1c83..8b05d25018f 100644 --- a/intern/guardedalloc/cpp/mallocn.cpp +++ b/intern/guardedalloc/cpp/mallocn.cpp @@ -28,6 +28,9 @@ #include #include "../MEM_guardedalloc.h" +void *operator new(size_t size, const char *str) throw(std::bad_alloc); +void *operator new[](size_t size, const char *str) throw(std::bad_alloc); + /* not default but can be used when needing to set a string */ void *operator new(size_t size, const char *str) throw(std::bad_alloc) { diff --git a/source/gameengine/Converter/BL_ArmatureChannel.cpp b/source/gameengine/Converter/BL_ArmatureChannel.cpp index 7cf895255ba..11e90e1797d 100644 --- a/source/gameengine/Converter/BL_ArmatureChannel.cpp +++ b/source/gameengine/Converter/BL_ArmatureChannel.cpp @@ -95,7 +95,7 @@ BL_ArmatureChannel::~BL_ArmatureChannel() // PYTHON PyMethodDef BL_ArmatureChannel::Methods[] = { - {NULL,NULL} //Sentinel + {NULL,NULL} //Sentinel }; // order of definition of attributes, must match Attributes[] array diff --git a/source/gameengine/Converter/BL_ArmatureConstraint.cpp b/source/gameengine/Converter/BL_ArmatureConstraint.cpp index b8ad117a220..379be91b523 100644 --- a/source/gameengine/Converter/BL_ArmatureConstraint.cpp +++ b/source/gameengine/Converter/BL_ArmatureConstraint.cpp @@ -246,7 +246,7 @@ void BL_ArmatureConstraint::SetSubtarget(KX_GameObject* subtarget) // PYTHON PyMethodDef BL_ArmatureConstraint::Methods[] = { - {NULL,NULL} //Sentinel + {NULL,NULL} //Sentinel }; // order of definition of attributes, must match Attributes[] array diff --git a/source/gameengine/Converter/BL_ArmatureObject.cpp b/source/gameengine/Converter/BL_ArmatureObject.cpp index ed97b9ff73f..1f1c404efcb 100644 --- a/source/gameengine/Converter/BL_ArmatureObject.cpp +++ b/source/gameengine/Converter/BL_ArmatureObject.cpp @@ -639,7 +639,6 @@ PyTypeObject BL_ArmatureObject::Type = { }; PyMethodDef BL_ArmatureObject::Methods[] = { - KX_PYMETHODTABLE_NOARGS(BL_ArmatureObject, update), {NULL,NULL} //Sentinel }; diff --git a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp index 30a4209965e..d1684db0f5a 100644 --- a/source/gameengine/Converter/KX_BlenderSceneConverter.cpp +++ b/source/gameengine/Converter/KX_BlenderSceneConverter.cpp @@ -103,6 +103,7 @@ extern "C" #include "KX_MeshProxy.h" #include "RAS_MeshObject.h" extern "C" { + #include "PIL_time.h" #include "BKE_context.h" #include "BLO_readfile.h" #include "BKE_idcode.h" @@ -957,10 +958,12 @@ static void load_datablocks(Main *main_newlib, BlendHandle *bpy_openlib, const c bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const char *path, char *group, KX_Scene *scene_merge, char **err_str, short options) { Main *main_newlib; /* stored as a dynamic 'main' until we free it */ - int idcode= BKE_idcode_from_name(group); + const int idcode = BKE_idcode_from_name(group); ReportList reports; static char err_local[255]; - + +// TIMEIT_START(bge_link_blend_file); + /* only scene and mesh supported right now */ if (idcode!=ID_SCE && idcode!=ID_ME &&idcode!=ID_AC) { snprintf(err_local, sizeof(err_local), "invalid ID type given \"%s\"\n", group); @@ -1059,7 +1062,9 @@ bool KX_BlenderSceneConverter::LinkBlendFile(BlendHandle *bpy_openlib, const cha } } } - + +// TIMEIT_END(bge_link_blend_file); + return true; } diff --git a/source/gameengine/Expressions/PyObjectPlus.cpp b/source/gameengine/Expressions/PyObjectPlus.cpp index 03f9fb5fb19..77c76ca8153 100644 --- a/source/gameengine/Expressions/PyObjectPlus.cpp +++ b/source/gameengine/Expressions/PyObjectPlus.cpp @@ -259,7 +259,7 @@ void PyObjectPlus::py_base_dealloc(PyObject *self) // python wrapper * PyObjectPlus Methods -- Every class, even the abstract one should have a Methods ------------------------------*/ PyMethodDef PyObjectPlus::Methods[] = { - {NULL, NULL} /* Sentinel */ + {NULL, NULL} /* Sentinel */ }; #define BGE_PY_ATTR_INVALID (&(PyObjectPlus::Attributes[0])) diff --git a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp index ab0e6c5edcb..4916d8a0a57 100644 --- a/source/gameengine/GameLogic/SCA_ILogicBrick.cpp +++ b/source/gameengine/GameLogic/SCA_ILogicBrick.cpp @@ -202,7 +202,7 @@ PyTypeObject SCA_ILogicBrick::Type = { }; PyMethodDef SCA_ILogicBrick::Methods[] = { - {NULL,NULL} //Sentinel + {NULL,NULL} //Sentinel }; PyAttributeDef SCA_ILogicBrick::Attributes[] = { diff --git a/source/gameengine/Ketsji/KX_CharacterWrapper.h b/source/gameengine/Ketsji/KX_CharacterWrapper.h index 04303064645..3b0058aca6f 100644 --- a/source/gameengine/Ketsji/KX_CharacterWrapper.h +++ b/source/gameengine/Ketsji/KX_CharacterWrapper.h @@ -30,10 +30,6 @@ public: private: PHY_ICharacter* m_character; - -#ifdef WITH_CXX_GUARDEDALLOC - MEM_CXX_CLASS_ALLOC_FUNCS("GE:KX_CharacterWrapper") -#endif }; -#endif //__KX_CHARACTERWRAPPER_H__ +#endif /* __KX_CHARACTERWRAPPER_H__ */ diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 87c366046ad..69be584343a 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -70,13 +70,13 @@ PyTypeObject KX_MeshProxy::Type = { }; PyMethodDef KX_MeshProxy::Methods[] = { -{"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS}, -{"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS}, -{"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS}, -{"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS}, -{"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS}, -//{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS}, - {NULL,NULL} //Sentinel + {"getMaterialName", (PyCFunction)KX_MeshProxy::sPyGetMaterialName,METH_VARARGS}, + {"getTextureName", (PyCFunction)KX_MeshProxy::sPyGetTextureName,METH_VARARGS}, + {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS}, + {"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS}, + {"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS}, + //{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS}, + {NULL,NULL} //Sentinel }; PyAttributeDef KX_MeshProxy::Attributes[] = { diff --git a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp index d850168afdf..56dccc1d045 100644 --- a/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_AddObjectActuator.cpp @@ -190,8 +190,8 @@ PyTypeObject KX_SCA_AddObjectActuator::Type = { }; PyMethodDef KX_SCA_AddObjectActuator::Methods[] = { - {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS,"instantAddObject() : immediately add object without delay\n"}, - {NULL,NULL} //Sentinel + {"instantAddObject", (PyCFunction) KX_SCA_AddObjectActuator::sPyInstantAddObject, METH_NOARGS, NULL}, + {NULL,NULL} //Sentinel }; PyAttributeDef KX_SCA_AddObjectActuator::Attributes[] = { diff --git a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp index e6209d2d47b..81c9dc91603 100644 --- a/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp +++ b/source/gameengine/Ketsji/KX_SCA_EndObjectActuator.cpp @@ -113,7 +113,7 @@ PyTypeObject KX_SCA_EndObjectActuator::Type = { }; PyMethodDef KX_SCA_EndObjectActuator::Methods[] = { - {NULL,NULL} //Sentinel + {NULL,NULL} //Sentinel }; PyAttributeDef KX_SCA_EndObjectActuator::Attributes[] = { diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index dabb79b357d..02333f8ae2f 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -61,19 +61,19 @@ PyTypeObject KX_VertexProxy::Type = { }; PyMethodDef KX_VertexProxy::Methods[] = { -{"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS}, -{"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O}, -{"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_NOARGS}, -{"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_O}, + {"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS}, + {"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O}, + {"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_NOARGS}, + {"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_O}, -{"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS}, -{"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS}, + {"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS}, + {"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS}, -{"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_NOARGS}, -{"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_O}, -{"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_NOARGS}, -{"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_O}, - {NULL,NULL} //Sentinel + {"getRGBA", (PyCFunction)KX_VertexProxy::sPyGetRGBA,METH_NOARGS}, + {"setRGBA", (PyCFunction)KX_VertexProxy::sPySetRGBA,METH_O}, + {"getNormal", (PyCFunction)KX_VertexProxy::sPyGetNormal,METH_NOARGS}, + {"setNormal", (PyCFunction)KX_VertexProxy::sPySetNormal,METH_O}, + {NULL,NULL} //Sentinel }; PyAttributeDef KX_VertexProxy::Attributes[] = { diff --git a/source/gameengine/VideoTexture/ImageRender.cpp b/source/gameengine/VideoTexture/ImageRender.cpp index 85857165403..2cc2cfb6bfc 100644 --- a/source/gameengine/VideoTexture/ImageRender.cpp +++ b/source/gameengine/VideoTexture/ImageRender.cpp @@ -375,7 +375,7 @@ static PyMethodDef imageRenderMethods[] = static PyGetSetDef imageRenderGetSets[] = { {(char*)"background", (getter)getBackground, (setter)setBackground, (char*)"background color", NULL}, - // attribute from ImageViewport + // attribute from ImageViewport {(char*)"capsize", (getter)ImageViewport_getCaptureSize, (setter)ImageViewport_setCaptureSize, (char*)"size of render area", NULL}, {(char*)"alpha", (getter)ImageViewport_getAlpha, (setter)ImageViewport_setAlpha, (char*)"use alpha in texture", NULL}, {(char*)"whole", (getter)ImageViewport_getWhole, (setter)ImageViewport_setWhole, (char*)"use whole viewport to render", NULL}, From c9cd4d61ba4ed9ac8285ec991d14964c3e98dd3c Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 10 Nov 2012 08:13:13 +0000 Subject: [PATCH 076/118] Fix #33132: Incorrect render session update when using persistent images issue and changing resolution --- intern/cycles/blender/blender_session.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/intern/cycles/blender/blender_session.cpp b/intern/cycles/blender/blender_session.cpp index fcc3d89f5d8..ad43c39469c 100644 --- a/intern/cycles/blender/blender_session.cpp +++ b/intern/cycles/blender/blender_session.cpp @@ -117,6 +117,9 @@ void BlenderSession::reset_session(BL::BlendData b_data_, BL::Scene b_scene_) SceneParams scene_params = BlenderSync::get_scene_params(b_scene, background); SessionParams session_params = BlenderSync::get_session_params(b_engine, b_userpref, b_scene, background); + width = b_engine.resolution_x(); + height = b_engine.resolution_y(); + if(scene->params.modified(scene_params) || session->params.modified(session_params)) { From f5c9f2c2530d21474f8e2ee5ea7dfdb483b7ba7d Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 10 Nov 2012 08:37:02 +0000 Subject: [PATCH 077/118] Cycles: correction to how device of lists is exposed to blender compute_device_list is using static vector of device information which had pointers (identifier and name) to values from device information structures. That structures are also stored in static vector and being refreshed every 5 seconds. The issue is, as soon as device information is being updated, pointers in vector from compute_device_list became incorrect. Seems it was the reason of issues with sudden switching from CUDA to OpenCL on my desktop and from CUDA to CPU on my laptop, It was also seems to be making persistent images behaves instable. Made it so device identifier and name are copied from device info to structures used by RNA (CCLDeviceInfo). Alternative could be avoid cacheing CCLDeviceInfo and always use actual list of device information by RNA. It shouldn't be so much slow. --- intern/cycles/blender/CCL_api.h | 6 +++--- intern/cycles/blender/blender_python.cpp | 13 +++++++++++-- source/blender/makesrna/intern/rna_userdef.c | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/intern/cycles/blender/CCL_api.h b/intern/cycles/blender/CCL_api.h index 469d63d1530..b8a30b71717 100644 --- a/intern/cycles/blender/CCL_api.h +++ b/intern/cycles/blender/CCL_api.h @@ -23,12 +23,12 @@ extern "C" { #endif -/* returns a list of devices for selection, array is name NULL pointer +/* returns a list of devices for selection, array is empty identifier * terminated and must not be freed */ typedef struct CCLDeviceInfo { - const char *identifier; - const char *name; + char identifier[128]; + char name[512]; int value; } CCLDeviceInfo; diff --git a/intern/cycles/blender/blender_python.cpp b/intern/cycles/blender/blender_python.cpp index e78c78e5eb2..d164920ceff 100644 --- a/intern/cycles/blender/blender_python.cpp +++ b/intern/cycles/blender/blender_python.cpp @@ -418,14 +418,23 @@ static CCLDeviceInfo *compute_device_list(DeviceType type) if(info.type == type || (info.type == DEVICE_MULTI && info.multi_devices[0].type == type)) { - CCLDeviceInfo cinfo = {info.id.c_str(), info.description.c_str(), i++}; + CCLDeviceInfo cinfo; + + strncpy(cinfo.identifier, info.id.c_str(), sizeof(cinfo.identifier)); + cinfo.identifier[info.id.length()] = '\0'; + + strncpy(cinfo.name, info.description.c_str(), sizeof(cinfo.name)); + cinfo.name[info.description.length()] = '\0'; + + cinfo.value = i++; + device_list.push_back(cinfo); } } /* null terminate */ if(!device_list.empty()) { - CCLDeviceInfo cinfo = {NULL, NULL, 0}; + CCLDeviceInfo cinfo = {"", "", 0}; device_list.push_back(cinfo); } } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 31a1360829e..13219ea133d 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -395,7 +395,7 @@ static EnumPropertyItem *rna_userdef_compute_device_itemf(bContext *UNUSED(C), P int a; if (devices) { - for (a = 0; devices[a].name; a++) { + for (a = 0; devices[a].identifier[0]; a++) { tmp.value = devices[a].value; tmp.identifier = devices[a].identifier; tmp.name = devices[a].name; From fecc3b9d68102630fc53f451a3f405f180b31384 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 10 Nov 2012 09:45:43 +0000 Subject: [PATCH 078/118] add 2 new utility functions to the BGE mesh py api. mesh.transform(matid, matrix) mesh.transform_uv(matid, matrix, uv_index=-1)) much more efficient then looping over verts in python to transform them. --- doc/python_api/rst/bge.types.rst | 20 +++ intern/itasc/CMakeLists.txt | 2 +- source/gameengine/Ketsji/KX_MeshProxy.cpp | 140 ++++++++++++++++++ source/gameengine/Ketsji/KX_MeshProxy.h | 4 +- .../Rasterizer/RAS_MaterialBucket.h | 2 + source/gameengine/Rasterizer/RAS_TexVert.cpp | 9 ++ source/gameengine/Rasterizer/RAS_TexVert.h | 2 + 7 files changed, 177 insertions(+), 2 deletions(-) diff --git a/doc/python_api/rst/bge.types.rst b/doc/python_api/rst/bge.types.rst index 431b264ba73..5093cfe0ace 100644 --- a/doc/python_api/rst/bge.types.rst +++ b/doc/python_api/rst/bge.types.rst @@ -1957,6 +1957,26 @@ Types :return: a polygon object. :rtype: :class:`PolyProxy` + .. method:: transform(matid, matrix) + + Transforms the vertices of a mesh. + + :arg matid: material index, -1 transforms all. + :type matid: integer + :arg matrix: transformation matrix. + :type matrix: 4x4 matrix [[float]] + + .. method:: transform_uv(matid, matrix, uv_index=-1) + + Transforms the vertices UV's of a mesh. + + :arg matid: material index, -1 transforms all. + :type matid: integer + :arg matrix: transformation matrix. + :type matrix: 4x4 matrix [[float]] + :arg matid: optional uv index, -1 for all, otherwise 0 or 1. + :type matid: integer + .. class:: SCA_MouseSensor(SCA_ISensor) Mouse Sensor logic brick. diff --git a/intern/itasc/CMakeLists.txt b/intern/itasc/CMakeLists.txt index 99c64d956cb..bc3ea0cf24c 100644 --- a/intern/itasc/CMakeLists.txt +++ b/intern/itasc/CMakeLists.txt @@ -22,7 +22,7 @@ # Contributor(s): Jacques Beaurain. # # ***** END GPL LICENSE BLOCK ***** - +remove_strict_flags() set(INC ) diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index 69be584343a..be4b0cd8031 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -75,6 +75,8 @@ PyMethodDef KX_MeshProxy::Methods[] = { {"getVertexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetVertexArrayLength,METH_VARARGS}, {"getVertex", (PyCFunction)KX_MeshProxy::sPyGetVertex,METH_VARARGS}, {"getPolygon", (PyCFunction)KX_MeshProxy::sPyGetPolygon,METH_VARARGS}, + {"transform", (PyCFunction)KX_MeshProxy::sPyTransform,METH_VARARGS}, + {"transform_uv", (PyCFunction)KX_MeshProxy::sPyTransformUV,METH_VARARGS}, //{"getIndexArrayLength", (PyCFunction)KX_MeshProxy::sPyGetIndexArrayLength,METH_VARARGS}, {NULL,NULL} //Sentinel }; @@ -218,6 +220,144 @@ PyObject *KX_MeshProxy::PyGetPolygon(PyObject *args, PyObject *kwds) return polyob; } +PyObject *KX_MeshProxy::PyTransform(PyObject *args, PyObject *kwds) +{ + int matindex; + PyObject *pymat; + bool ok = false; + + MT_Matrix4x4 transform; + + if (!PyArg_ParseTuple(args,"iO:transform", &matindex, &pymat) || + !PyMatTo(pymat, transform)) + { + return NULL; + } + + MT_Matrix4x4 ntransform = transform.inverse().transposed(); + ntransform[0][3] = ntransform[1][3] = ntransform[2][3] = 0.0f; + + /* transform mesh verts */ + unsigned int mit_index = 0; + for (list::iterator mit = m_meshobj->GetFirstMaterial(); + (mit != m_meshobj->GetLastMaterial()); + ++mit, ++mit_index) + { + if (matindex == -1) { + /* always transform */ + } + else if (matindex == mit_index) { + /* we found the right index! */ + } + else { + continue; + } + + RAS_MeshSlot *slot = mit->m_baseslot; + RAS_MeshSlot::iterator it; + ok = true; + + for (slot->begin(it); !slot->end(it); slot->next(it)) { + size_t i; + for (i = it.startvertex; i < it.endvertex; i++) { + it.vertex[i].Transform(transform, ntransform); + } + } + + /* if we set a material index, quit when done */ + if (matindex == mit_index) { + break; + } + } + + if (ok == false) { + PyErr_Format(PyExc_ValueError, + "mesh.transform(...): invalid material index %d", matindex); + return NULL; + } + + m_meshobj->SetMeshModified(true); + + Py_RETURN_NONE; +} + +PyObject *KX_MeshProxy::PyTransformUV(PyObject *args, PyObject *kwds) +{ + int matindex; + PyObject *pymat; + int uvindex = -1; + bool ok = false; + + MT_Matrix4x4 transform; + + if (!PyArg_ParseTuple(args,"iO|ii:transform_uv", &matindex, &pymat, &uvindex) || + !PyMatTo(pymat, transform)) + { + return NULL; + } + + if (uvindex < -1 || uvindex > 1) { + PyErr_Format(PyExc_ValueError, + "mesh.transform_uv(...): invalid uv index %d", uvindex); + return NULL; + } + + /* transform mesh verts */ + unsigned int mit_index = 0; + for (list::iterator mit = m_meshobj->GetFirstMaterial(); + (mit != m_meshobj->GetLastMaterial()); + ++mit, ++mit_index) + { + if (matindex == -1) { + /* always transform */ + } + else if (matindex == mit_index) { + /* we found the right index! */ + } + else { + continue; + } + + RAS_MeshSlot *slot = mit->m_baseslot; + RAS_MeshSlot::iterator it; + ok = true; + + for (slot->begin(it); !slot->end(it); slot->next(it)) { + size_t i; + + for (i = it.startvertex; i < it.endvertex; i++) { + switch (uvindex) { + case 0: + it.vertex[i].TransformUV(transform); + break; + case 1: + it.vertex[i].TransformUV2(transform); + break; + case -1: + it.vertex[i].TransformUV(transform); + it.vertex[i].TransformUV2(transform); + break; + } + } + } + + /* if we set a material index, quit when done */ + if (matindex == mit_index) { + break; + } + } + + if (ok == false) { + PyErr_Format(PyExc_ValueError, + "mesh.transform_uv(...): invalid material index %d", matindex); + return NULL; + } + + m_meshobj->SetMeshModified(true); + + Py_RETURN_NONE; +} + PyObject *KX_MeshProxy::pyattr_get_materials(void *self_v, const KX_PYATTRIBUTE_DEF *attrdef) { KX_MeshProxy* self = static_cast(self_v); diff --git a/source/gameengine/Ketsji/KX_MeshProxy.h b/source/gameengine/Ketsji/KX_MeshProxy.h index 98e73aa626f..5366634ef98 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.h +++ b/source/gameengine/Ketsji/KX_MeshProxy.h @@ -71,8 +71,10 @@ public: KX_PYMETHOD(KX_MeshProxy,GetVertexArrayLength); KX_PYMETHOD(KX_MeshProxy,GetVertex); KX_PYMETHOD(KX_MeshProxy,GetPolygon); + KX_PYMETHOD(KX_MeshProxy,Transform); + KX_PYMETHOD(KX_MeshProxy,TransformUV); - static PyObject* pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); + static PyObject *pyattr_get_materials(void* self_v, const KX_PYATTRIBUTE_DEF *attrdef); static PyObject *pyattr_get_numMaterials(void * self, const KX_PYATTRIBUTE_DEF * attrdef); static PyObject *pyattr_get_numPolygons(void * self, const KX_PYATTRIBUTE_DEF * attrdef); }; diff --git a/source/gameengine/Rasterizer/RAS_MaterialBucket.h b/source/gameengine/Rasterizer/RAS_MaterialBucket.h index 16ecffb9a32..4c72f128817 100644 --- a/source/gameengine/Rasterizer/RAS_MaterialBucket.h +++ b/source/gameengine/Rasterizer/RAS_MaterialBucket.h @@ -189,6 +189,8 @@ class RAS_MeshMaterial public: RAS_MeshSlot *m_baseslot; class RAS_MaterialBucket *m_bucket; + + /* the KX_GameObject is used as a key here */ CTR_Map m_slots; diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index 3b4f4cae30e..6d8cbfece15 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -151,3 +151,12 @@ void RAS_TexVert::Transform(const MT_Matrix4x4& mat, const MT_Matrix4x4& nmat) SetTangent((nmat*MT_Vector4(m_tangent[0], m_tangent[1], m_tangent[2], 1.0)).getValue()); } +void RAS_TexVert::TransformUV(const MT_Matrix4x4& mat) +{ + SetUV((mat * MT_Vector4(m_uv1[0], m_uv1[1], 0.0, 1.0)).getValue()); +} + +void RAS_TexVert::TransformUV2(const MT_Matrix4x4& mat) +{ + SetUV2((mat * MT_Vector4(m_uv2[0], m_uv2[1], 0.0, 1.0)).getValue()); +} diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h index 889769da5ed..bb151a64814 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.h +++ b/source/gameengine/Rasterizer/RAS_TexVert.h @@ -137,6 +137,8 @@ public: void Transform(const class MT_Matrix4x4& mat, const class MT_Matrix4x4& nmat); + void TransformUV(const MT_Matrix4x4& mat); + void TransformUV2(const MT_Matrix4x4& mat); // compare two vertices, to test if they can be shared, used for // splitting up based on uv's, colors, etc From 250109f5ace8471451a6d8bda8f67ffc955eb4b7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 10 Nov 2012 10:26:39 +0000 Subject: [PATCH 079/118] add argument so recent bge function mesh.transform_uv() so you can optionally transform between UV1 / UV2 --- doc/python_api/rst/bge.types.rst | 8 ++++-- source/gameengine/Ketsji/KX_MeshProxy.cpp | 30 +++++++++++++++----- source/gameengine/Ketsji/KX_VertexProxy.cpp | 19 ++++++------- source/gameengine/Ketsji/KX_VertexProxy.h | 4 +-- source/gameengine/Rasterizer/RAS_TexVert.cpp | 19 ++++++++++--- source/gameengine/Rasterizer/RAS_TexVert.h | 8 ++++-- 6 files changed, 59 insertions(+), 29 deletions(-) diff --git a/doc/python_api/rst/bge.types.rst b/doc/python_api/rst/bge.types.rst index 5093cfe0ace..7ce913a54f3 100644 --- a/doc/python_api/rst/bge.types.rst +++ b/doc/python_api/rst/bge.types.rst @@ -1966,7 +1966,7 @@ Types :arg matrix: transformation matrix. :type matrix: 4x4 matrix [[float]] - .. method:: transform_uv(matid, matrix, uv_index=-1) + .. method:: transform_uv(matid, matrix, uv_index=-1, uv_index_from=-1) Transforms the vertices UV's of a mesh. @@ -1974,8 +1974,10 @@ Types :type matid: integer :arg matrix: transformation matrix. :type matrix: 4x4 matrix [[float]] - :arg matid: optional uv index, -1 for all, otherwise 0 or 1. - :type matid: integer + :arg uv_index: optional uv index, -1 for all, otherwise 0 or 1. + :type uv_index: integer + :arg uv_index_from: optional uv index to copy from, -1 to transform the current uv. + :type uv_index_from: integer .. class:: SCA_MouseSensor(SCA_ISensor) diff --git a/source/gameengine/Ketsji/KX_MeshProxy.cpp b/source/gameengine/Ketsji/KX_MeshProxy.cpp index be4b0cd8031..9430179e344 100644 --- a/source/gameengine/Ketsji/KX_MeshProxy.cpp +++ b/source/gameengine/Ketsji/KX_MeshProxy.cpp @@ -260,7 +260,8 @@ PyObject *KX_MeshProxy::PyTransform(PyObject *args, PyObject *kwds) for (slot->begin(it); !slot->end(it); slot->next(it)) { size_t i; for (i = it.startvertex; i < it.endvertex; i++) { - it.vertex[i].Transform(transform, ntransform); + RAS_TexVert *vert = &it.vertex[i]; + vert->Transform(transform, ntransform); } } @@ -286,11 +287,12 @@ PyObject *KX_MeshProxy::PyTransformUV(PyObject *args, PyObject *kwds) int matindex; PyObject *pymat; int uvindex = -1; + int uvindex_from = -1; bool ok = false; MT_Matrix4x4 transform; - if (!PyArg_ParseTuple(args,"iO|ii:transform_uv", &matindex, &pymat, &uvindex) || + if (!PyArg_ParseTuple(args,"iO|iii:transform_uv", &matindex, &pymat, &uvindex, &uvindex_from) || !PyMatTo(pymat, transform)) { return NULL; @@ -298,9 +300,17 @@ PyObject *KX_MeshProxy::PyTransformUV(PyObject *args, PyObject *kwds) if (uvindex < -1 || uvindex > 1) { PyErr_Format(PyExc_ValueError, - "mesh.transform_uv(...): invalid uv index %d", uvindex); + "mesh.transform_uv(...): invalid uv_index %d", uvindex); return NULL; } + if (uvindex_from < -1 || uvindex_from > 1 || uvindex == -1) { + PyErr_Format(PyExc_ValueError, + "mesh.transform_uv(...): invalid uv_index_from %d", uvindex); + return NULL; + } + if (uvindex_from == uvindex) { + uvindex_from = -1; + } /* transform mesh verts */ unsigned int mit_index = 0; @@ -326,16 +336,22 @@ PyObject *KX_MeshProxy::PyTransformUV(PyObject *args, PyObject *kwds) size_t i; for (i = it.startvertex; i < it.endvertex; i++) { + RAS_TexVert *vert = &it.vertex[i]; + if (uvindex_from != -1) { + if (uvindex_from == 0) vert->SetUV2(vert->getUV1()); + else vert->SetUV1(vert->getUV2()); + } + switch (uvindex) { case 0: - it.vertex[i].TransformUV(transform); + vert->TransformUV1(transform); break; case 1: - it.vertex[i].TransformUV2(transform); + vert->TransformUV2(transform); break; case -1: - it.vertex[i].TransformUV(transform); - it.vertex[i].TransformUV2(transform); + vert->TransformUV1(transform); + vert->TransformUV2(transform); break; } } diff --git a/source/gameengine/Ketsji/KX_VertexProxy.cpp b/source/gameengine/Ketsji/KX_VertexProxy.cpp index 02333f8ae2f..82e414d7c42 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.cpp +++ b/source/gameengine/Ketsji/KX_VertexProxy.cpp @@ -63,8 +63,8 @@ PyTypeObject KX_VertexProxy::Type = { PyMethodDef KX_VertexProxy::Methods[] = { {"getXYZ", (PyCFunction)KX_VertexProxy::sPyGetXYZ,METH_NOARGS}, {"setXYZ", (PyCFunction)KX_VertexProxy::sPySetXYZ,METH_O}, - {"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV,METH_NOARGS}, - {"setUV", (PyCFunction)KX_VertexProxy::sPySetUV,METH_O}, + {"getUV", (PyCFunction)KX_VertexProxy::sPyGetUV1, METH_NOARGS}, + {"setUV", (PyCFunction)KX_VertexProxy::sPySetUV1, METH_O}, {"getUV2", (PyCFunction)KX_VertexProxy::sPyGetUV2,METH_NOARGS}, {"setUV2", (PyCFunction)KX_VertexProxy::sPySetUV2,METH_VARARGS}, @@ -247,7 +247,7 @@ int KX_VertexProxy::pyattr_set_u(void *self_v, const struct KX_PYATTRIBUTE_DEF * float val = PyFloat_AsDouble(value); MT_Point2 uv = self->m_vertex->getUV1(); uv[0] = val; - self->m_vertex->SetUV(uv); + self->m_vertex->SetUV1(uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -262,7 +262,7 @@ int KX_VertexProxy::pyattr_set_v(void *self_v, const struct KX_PYATTRIBUTE_DEF * float val = PyFloat_AsDouble(value); MT_Point2 uv = self->m_vertex->getUV1(); uv[1] = val; - self->m_vertex->SetUV(uv); + self->m_vertex->SetUV1(uv); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -389,9 +389,8 @@ int KX_VertexProxy::pyattr_set_UV(void *self_v, const struct KX_PYATTRIBUTE_DEF if (PySequence_Check(value)) { MT_Point2 vec; - if (PyVecTo(value, vec)) - { - self->m_vertex->SetUV(vec); + if (PyVecTo(value, vec)) { + self->m_vertex->SetUV1(vec); self->m_mesh->SetMeshModified(true); return PY_SET_ATTR_SUCCESS; } @@ -521,18 +520,18 @@ PyObject *KX_VertexProxy::PySetRGBA(PyObject *value) } -PyObject *KX_VertexProxy::PyGetUV() +PyObject *KX_VertexProxy::PyGetUV1() { return PyObjectFrom(MT_Vector2(m_vertex->getUV1())); } -PyObject *KX_VertexProxy::PySetUV(PyObject *value) +PyObject *KX_VertexProxy::PySetUV1(PyObject *value) { MT_Point2 vec; if (!PyVecTo(value, vec)) return NULL; - m_vertex->SetUV(vec); + m_vertex->SetUV1(vec); m_mesh->SetMeshModified(true); Py_RETURN_NONE; } diff --git a/source/gameengine/Ketsji/KX_VertexProxy.h b/source/gameengine/Ketsji/KX_VertexProxy.h index 6e193d35b4c..4247d138a66 100644 --- a/source/gameengine/Ketsji/KX_VertexProxy.h +++ b/source/gameengine/Ketsji/KX_VertexProxy.h @@ -92,8 +92,8 @@ public: KX_PYMETHOD_NOARGS(KX_VertexProxy,GetXYZ); KX_PYMETHOD_O(KX_VertexProxy,SetXYZ); - KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV); - KX_PYMETHOD_O(KX_VertexProxy,SetUV); + KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV1); + KX_PYMETHOD_O(KX_VertexProxy,SetUV1); KX_PYMETHOD_NOARGS(KX_VertexProxy,GetUV2); KX_PYMETHOD_VARARGS(KX_VertexProxy,SetUV2); diff --git a/source/gameengine/Rasterizer/RAS_TexVert.cpp b/source/gameengine/Rasterizer/RAS_TexVert.cpp index 6d8cbfece15..945644ff3e6 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.cpp +++ b/source/gameengine/Rasterizer/RAS_TexVert.cpp @@ -75,21 +75,32 @@ void RAS_TexVert::SetXYZ(const MT_Point3& xyz) xyz.getValue(m_localxyz); } -void RAS_TexVert::SetXYZ(const float *xyz) +void RAS_TexVert::SetXYZ(const float xyz[3]) { m_localxyz[0] = xyz[0]; m_localxyz[1] = xyz[1]; m_localxyz[2] = xyz[2]; } -void RAS_TexVert::SetUV(const MT_Point2& uv) +void RAS_TexVert::SetUV1(const MT_Point2& uv) { uv.getValue(m_uv1); } +void RAS_TexVert::SetUV1(const float uv[3]) +{ + m_uv1[0] = uv[0]; + m_uv1[1] = uv[1]; +} + void RAS_TexVert::SetUV2(const MT_Point2& uv) { uv.getValue(m_uv2); } +void RAS_TexVert::SetUV2(const float uv[3]) +{ + m_uv2[0] = uv[0]; + m_uv2[1] = uv[1]; +} void RAS_TexVert::SetRGBA(const unsigned int rgba) { @@ -151,9 +162,9 @@ void RAS_TexVert::Transform(const MT_Matrix4x4& mat, const MT_Matrix4x4& nmat) SetTangent((nmat*MT_Vector4(m_tangent[0], m_tangent[1], m_tangent[2], 1.0)).getValue()); } -void RAS_TexVert::TransformUV(const MT_Matrix4x4& mat) +void RAS_TexVert::TransformUV1(const MT_Matrix4x4& mat) { - SetUV((mat * MT_Vector4(m_uv1[0], m_uv1[1], 0.0, 1.0)).getValue()); + SetUV1((mat * MT_Vector4(m_uv1[0], m_uv1[1], 0.0, 1.0)).getValue()); } void RAS_TexVert::TransformUV2(const MT_Matrix4x4& mat) diff --git a/source/gameengine/Rasterizer/RAS_TexVert.h b/source/gameengine/Rasterizer/RAS_TexVert.h index bb151a64814..98ea4dd60aa 100644 --- a/source/gameengine/Rasterizer/RAS_TexVert.h +++ b/source/gameengine/Rasterizer/RAS_TexVert.h @@ -122,9 +122,11 @@ public: } void SetXYZ(const MT_Point3& xyz); - void SetXYZ(const float *xyz); - void SetUV(const MT_Point2& uv); + void SetXYZ(const float xyz[3]); + void SetUV1(const MT_Point2& uv); void SetUV2(const MT_Point2& uv); + void SetUV1(const float uv[2]); + void SetUV2(const float uv[2]); void SetRGBA(const unsigned int rgba); void SetNormal(const MT_Vector3& normal); @@ -137,7 +139,7 @@ public: void Transform(const class MT_Matrix4x4& mat, const class MT_Matrix4x4& nmat); - void TransformUV(const MT_Matrix4x4& mat); + void TransformUV1(const MT_Matrix4x4& mat); void TransformUV2(const MT_Matrix4x4& mat); // compare two vertices, to test if they can be shared, used for From 4121e4b7e7420bfafe218da501162c8eae22a158 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sat, 10 Nov 2012 11:55:45 +0000 Subject: [PATCH 080/118] Added UI support to set OpenGL MultiSample. Code to support it was lying around for long already, but not controlled by UI nicely. Now you have in user preferences "System" tab an option to set it. NOTE: - it only works saving as User startup.blend, and restart Blender. - your system should support it, no check for it is visible in UI - tested only on iMac OSX 10.7 Screenshot: http://www.blender.org/bf/chinchilla.blend.png --- release/scripts/startup/bl_ui/space_userpref.py | 1 + .../blender/editors/space_view3d/view3d_draw.c | 16 ++++++++-------- source/blender/makesdna/DNA_userdef_types.h | 15 ++++++++++++++- source/blender/makesrna/intern/rna_userdef.c | 17 ++++++++++++++++- source/blender/windowmanager/intern/wm_window.c | 3 +-- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index c5a0a851fc5..3c426ade54b 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -446,6 +446,7 @@ class USERPREF_PT_system(Panel): #~ col.prop(system, "use_antialiasing") col.label(text="Window Draw Method:") col.prop(system, "window_draw_method", text="") + col.prop(system, "ogl_multisamples", text="") col.label(text="Text Draw Options:") col.prop(system, "use_text_antialiasing") col.label(text="Textures:") diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index db74179b569..24fc6adae6d 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -2985,10 +2985,10 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const v3d->zbuf = FALSE; /* enables anti-aliasing for 3D view drawing */ -#if 0 - if (!(U.gameflags & USER_DISABLE_AA)) - glEnable(GL_MULTISAMPLE_ARB); -#endif + if (U.ogl_multisamples) + if (!(U.gameflags & USER_DISABLE_AA)) + glEnable(GL_MULTISAMPLE_ARB); + /* needs to be done always, gridview is adjusted in drawgrid() now */ rv3d->gridview = v3d->grid; @@ -3101,12 +3101,12 @@ static void view3d_main_area_draw_objects(const bContext *C, ARegion *ar, const BIF_draw_manipulator(C); -#if 0 /* Disable back anti-aliasing */ - if (!(U.gameflags & USER_DISABLE_AA)) - glDisable(GL_MULTISAMPLE_ARB); -#endif + if (U.ogl_multisamples) + if (!(U.gameflags & USER_DISABLE_AA)) + glDisable(GL_MULTISAMPLE_ARB); + if (v3d->zbuf) { v3d->zbuf = FALSE; glDisable(GL_DEPTH_TEST); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index caa7c880aee..69e67461a56 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -418,9 +418,11 @@ typedef struct UserDef { float ndof_sensitivity; /* overall sensitivity of 3D mouse */ float ndof_orbit_sensitivity; - float pad4; int ndof_flag; /* flags for 3D mouse */ + short ogl_multisamples; /* amount of samples for OpenGL FSA, if zero no FSA */ + short pad4; + float glalphaclip; short autokey_mode; /* autokeying mode */ @@ -703,6 +705,17 @@ typedef enum eCompute_Device_Type { USER_COMPUTE_DEVICE_CUDA = 2, } eCompute_Device_Type; + +typedef enum eMultiSample_Type { + USER_MULTISAMPLE_NONE = 0, + USER_MULTISAMPLE_2 = 2, + USER_MULTISAMPLE_4 = 4, + USER_MULTISAMPLE_8 = 8, + USER_MULTISAMPLE_16 = 16, +} eMultiSample_Type; + + + #ifdef __cplusplus } #endif diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 13219ea133d..3e9f5b44a3d 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3018,6 +3018,15 @@ static void rna_def_userdef_system(BlenderRNA *brna) {0, NULL, 0, NULL, NULL} }; + static EnumPropertyItem multi_sample_levels[] = { + {USER_MULTISAMPLE_NONE, "MULTISAMPLE_NONE", 0, "No MultiSample", "Do not use OpenGL MultiSample"}, + {USER_MULTISAMPLE_2, "MULTISAMPLE_2", 0, "MultiSample: 2", "Use 2x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_4, "MULTISAMPLE_4", 0, "MultiSample: 4", "Use 4x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_8, "MULTISAMPLE_8", 0, "MultiSample: 8", "Use 8x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_16, "MULTISAMPLE_16", 0, "MultiSample: 16", "Use 16x OpenGL MultiSample (requires restart)"}, + {0, NULL, 0, NULL, NULL} + }; + #if 0 /* hardcoded here, could become dynamic somehow */ /* locale according to http://www.roseindia.net/tutorials/I18N/locales-list.shtml */ @@ -3312,6 +3321,12 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_ui_text(prop, "Text Anti-aliasing", "Draw user interface text anti-aliased"); RNA_def_property_update(prop, 0, "rna_userdef_text_update"); + /* Full scene anti-aliasing */ + prop = RNA_def_property(srna, "ogl_multisamples", PROP_ENUM, PROP_NONE); + RNA_def_property_enum_bitflag_sdna(prop, NULL, "ogl_multisamples"); + RNA_def_property_enum_items(prop, multi_sample_levels); + RNA_def_property_ui_text(prop, "MultiSample", "Enable OpenGL multi-sampling, only for systems that support it, requires restart"); + #ifdef WITH_CYCLES prop = RNA_def_property(srna, "compute_device_type", PROP_ENUM, PROP_NONE); RNA_def_property_flag(prop, PROP_ENUM_NO_CONTEXT); @@ -3441,7 +3456,7 @@ static void rna_def_userdef_input(BlenderRNA *brna) RNA_def_property_boolean_sdna(prop, NULL, "ndof_flag", NDOF_SHOW_GUIDE); RNA_def_property_ui_text(prop, "Show Navigation Guide", "Display the center and axis during rotation"); /* TODO: update description when fly-mode visuals are in place ("projected position in fly mode")*/ - + /* 3D view */ prop = RNA_def_property(srna, "ndof_view_rotate_method", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "ndof_flag"); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 616567e8184..87d80402af6 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -345,7 +345,7 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win) (GHOST_TWindowState)win->windowstate, GHOST_kDrawingContextTypeOpenGL, 0 /* no stereo */, - 0 /* no AA */); + U.ogl_multisamples /* AA */); if (ghostwin) { /* needed so we can detect the graphics card below */ @@ -373,7 +373,6 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win) /* standard state vars for window */ glEnable(GL_SCISSOR_TEST); - GPU_state_init(); } } From cb2f91b9d2660ddf1c8b730c7b1ee2b2e1170a0b Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Sat, 10 Nov 2012 13:50:28 +0000 Subject: [PATCH 081/118] OSX/cmake: rework the optional frameworks handling more osx-like, make jack weak-linked --- CMakeLists.txt | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 822c77ba094..cb656614b00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1383,10 +1383,13 @@ elseif(APPLE) endif() if(WITH_JACK) - set(JACK /usr/local) - set(JACK_INCLUDE_DIRS ${JACK}/include/jack) - set(JACK_LIBRARIES jack) - set(JACK_LIBPATH ${JACK}/lib) + find_library(JACK_FRAMEWORK + NAMES jackmp + ) + set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers) + if(NOT JACK_FRAMEWORK) + set(WITH_JACK OFF) + endif() endif() if(WITH_CODEC_SNDFILE) @@ -1497,10 +1500,10 @@ elseif(APPLE) if(WITH_INPUT_NDOF) # This thread it *should* work and check the framework - campbell # http://www.cmake.org/pipermail/cmake/2005-December/007740.html - find_library(3D_CONNEXION_CLIENT_LIBRARY + find_library(3DCONNEXION_CLIENT_FRAMEWORK NAMES 3DconnexionClient ) - if(NOT 3D_CONNEXION_CLIENT_LIBRARY) + if(NOT 3DCONNEXION_CLIENT_FRAMEWORK) set(WITH_INPUT_NDOF OFF) endif() @@ -1508,7 +1511,11 @@ elseif(APPLE) set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework 3DconnexionClient") endif() endif() - + + if(WITH_JACK) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework jackmp") + endif() + else() set(PLATFORM_CFLAGS "-pipe -funsigned-char") set(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime") From 472b3d47f90f22144de2466d11671efa6c23c7e8 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Sat, 10 Nov 2012 13:53:02 +0000 Subject: [PATCH 082/118] OSX/ndof: test link whole framework weak rather than single functions to fix clang compile issue --- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index d29dd4dd3e8..454e601ea18 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -168,7 +168,7 @@ GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() extern "C" { bool GHOST_NDOFManagerCocoa::available() { - extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); + extern OSErr InstallConnexionHandlers(); // (testing whole framework weak) __attribute__((weak_import)); // Make the linker happy for the framework check (see link below for more info) // http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html return InstallConnexionHandlers != NULL; @@ -177,7 +177,7 @@ extern "C" { bool GHOST_NDOFManagerCocoa::oldDRV() { - extern OSErr SetConnexionClientButtonMask() __attribute__((weak_import)); + extern OSErr SetConnexionClientButtonMask(); // (testing whole framework weak) __attribute__((weak_import)); // Make the linker happy for the framework check (see link below for more info) // http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html return SetConnexionClientButtonMask != NULL; From 4ec5a42456bf64e19377cd4ebd9dd7210dbe45c2 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Sat, 10 Nov 2012 13:53:58 +0000 Subject: [PATCH 083/118] OSX/cmake: little cleanup in ghost --- intern/ghost/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt index e52ac0af2ed..ea09987c564 100644 --- a/intern/ghost/CMakeLists.txt +++ b/intern/ghost/CMakeLists.txt @@ -189,7 +189,6 @@ elseif(APPLE) if(WITH_INPUT_NDOF) list(APPEND SRC intern/GHOST_NDOFManagerCocoa.mm - intern/GHOST_NDOFManagerCocoa.h ) endif() From 5ebe7d6a139c1062c4bf9de87b20eac8eff9ff59 Mon Sep 17 00:00:00 2001 From: Howard Trickey Date: Sat, 10 Nov 2012 13:59:45 +0000 Subject: [PATCH 084/118] Bevel: patch from Thomas Beck fixes numeric offset input and adds wheel input for number of segments. --- source/blender/editors/mesh/editmesh_tools.c | 43 +++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 20b52f50b2d..0c5c756a0fc 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -4627,19 +4627,16 @@ static void edbm_bevel_update_header(wmOperator *op, bContext *C) static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), offset: %s, segments: %d"; #else static char str[] = "Confirm: Enter/LClick, Cancel: (Esc/RMB), factor: %s, Use Dist (D): %s: Use Even (E): %s"; + BevelData *opdata = op->customdata; #endif char msg[HEADER_LENGTH]; ScrArea *sa = CTX_wm_area(C); - BevelData *opdata = op->customdata; if (sa) { #ifdef NEW_BEVEL char offset_str[NUM_STR_REP_LEN]; - if (hasNumInput(&opdata->num_input)) - outputNumInput(&opdata->num_input, offset_str); - else - BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset")); + BLI_snprintf(offset_str, NUM_STR_REP_LEN, "%f", RNA_float_get(op->ptr, "offset")); BLI_snprintf(msg, HEADER_LENGTH, str, offset_str, RNA_int_get(op->ptr, "segments") @@ -4940,9 +4937,21 @@ static float edbm_bevel_mval_factor(wmOperator *op, wmEvent *event) static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) { BevelData *opdata = op->customdata; + int segments = RNA_int_get(op->ptr, "segments"); if (event->val == KM_PRESS) { /* Try to handle numeric inputs... */ +#ifdef NEW_BEVEL + float value; + + if (handleNumInput(&opdata->num_input, event)) { + applyNumInput(&opdata->num_input, &value); + RNA_float_set(op->ptr, "offset", value); + edbm_bevel_calc(C, op); + edbm_bevel_update_header(op, C); + return OPERATOR_RUNNING_MODAL; + } +#else float factor; if (handleNumInput(&opdata->num_input, event)) { @@ -4954,6 +4963,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) edbm_bevel_update_header(op, C); return OPERATOR_RUNNING_MODAL; } +#endif } switch (event->type) { @@ -4983,6 +4993,28 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) edbm_bevel_exit(C, op); return OPERATOR_FINISHED; +#ifdef NEW_BEVEL + case WHEELUPMOUSE: /* change number of segments */ + if (event->val == KM_RELEASE) + break; + + segments++; + RNA_int_set(op->ptr, "segments", segments); + edbm_bevel_calc(C, op); + edbm_bevel_update_header(op, C); + break; + + case WHEELDOWNMOUSE: /* change number of segments */ + if (event->val == KM_RELEASE) + break; + + segments = max_ii(segments - 1, 1); + RNA_int_set(op->ptr, "segments", segments); + edbm_bevel_calc(C, op); + edbm_bevel_update_header(op, C); + break; + +#else case EKEY: if (event->val == KM_PRESS) { int use_even = RNA_boolean_get(op->ptr, "use_even"); @@ -5007,6 +5039,7 @@ static int edbm_bevel_modal(bContext *C, wmOperator *op, wmEvent *event) edbm_bevel_update_header(op, C); } break; +#endif } return OPERATOR_RUNNING_MODAL; From 5ddc5fbfb365a79b5ffa8ab7fbec7c4a89321e06 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 10 Nov 2012 14:50:34 +0000 Subject: [PATCH 085/118] Fix #33135: cycles object info random number not working anymore. --- intern/cycles/blender/blender_object.cpp | 7 ++++++- release/scripts/startup/bl_ui/space_userpref.py | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp index 67255d9f707..e8fa5c0ff3d 100644 --- a/intern/cycles/blender/blender_object.cpp +++ b/intern/cycles/blender/blender_object.cpp @@ -267,10 +267,15 @@ Object *BlenderSync::sync_object(BL::Object b_parent, int persistent_id[OBJECT_P object->motion.post = tfm; object->use_motion = false; + /* random number */ object->random_id = hash_string(object->name.c_str()); - if(persistent_id) + + if(persistent_id) { for(int i = 0; i < OBJECT_PERSISTENT_ID_SIZE; i++) object->random_id = hash_int_2d(object->random_id, persistent_id[i]); + } + else + object->random_id = hash_int_2d(object->random_id, 0); /* visibility flags for both parent */ object->visibility = object_ray_visibility(b_ob) & PATH_RAY_ALL; diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index 3c426ade54b..de55eaba775 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -422,7 +422,7 @@ class USERPREF_PT_system(Panel): col.separator() col.separator() - if hasattr(system, "compute_device"): + if hasattr(system, "compute_device_type"): col.label(text="Compute Device:") col.row().prop(system, "compute_device_type", expand=True) sub = col.row() From 45cd54bcd11d9b1fb62d986328917ca5cebf9b17 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Sat, 10 Nov 2012 15:13:41 +0000 Subject: [PATCH 086/118] OSX/ndof: rollback 52072, test showed we need individually weak functions -> todo: solve the clang link issue other way --- intern/ghost/intern/GHOST_NDOFManagerCocoa.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm index 454e601ea18..d29dd4dd3e8 100644 --- a/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm +++ b/intern/ghost/intern/GHOST_NDOFManagerCocoa.mm @@ -168,7 +168,7 @@ GHOST_NDOFManagerCocoa::~GHOST_NDOFManagerCocoa() extern "C" { bool GHOST_NDOFManagerCocoa::available() { - extern OSErr InstallConnexionHandlers(); // (testing whole framework weak) __attribute__((weak_import)); + extern OSErr InstallConnexionHandlers() __attribute__((weak_import)); // Make the linker happy for the framework check (see link below for more info) // http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html return InstallConnexionHandlers != NULL; @@ -177,7 +177,7 @@ extern "C" { bool GHOST_NDOFManagerCocoa::oldDRV() { - extern OSErr SetConnexionClientButtonMask(); // (testing whole framework weak) __attribute__((weak_import)); + extern OSErr SetConnexionClientButtonMask() __attribute__((weak_import)); // Make the linker happy for the framework check (see link below for more info) // http://developer.apple.com/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/WeakLinking.html return SetConnexionClientButtonMask != NULL; From f81e30a41f961fe681d06fb98fec6e722297292e Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 10 Nov 2012 19:11:25 +0000 Subject: [PATCH 087/118] Solved issue with distorted compositor results in some cases Originally issue was discovered when using stabilization and movie distortion nodes, but in fact issue was caused by render layer node always doing nearest interpolation. Now made it so this node will respect sampler passed to it's executePixel function and do an interpolation. Added two new functions to do bilinear/bicubic interpolation in float buffer with variable number of components per element, so it could interpolate 1, 3 and 4 component vectors. This functions currently mostly duplicates the same functions from imageprocess.c and it should actually be de-duplicated. Think it's ok to leave a bit of time with such duplication, since functions should be generalized one more time to support byte buffers, which could backfire on readability. Also removed mark as complex from stabilization node, which isn't needed sine int fact this node is not complex. --- source/blender/blenlib/BLI_math.h | 1 + source/blender/blenlib/BLI_math_interp.h | 35 +++ source/blender/blenlib/CMakeLists.txt | 1 + source/blender/blenlib/intern/math_interp.c | 235 ++++++++++++++++++ .../compositor/nodes/COM_ScaleNode.cpp | 22 +- .../compositor/nodes/COM_Stabilize2dNode.cpp | 2 + .../COM_MovieDistortionOperation.cpp | 1 - .../operations/COM_RenderLayersBaseProg.cpp | 55 ++-- .../operations/COM_RenderLayersBaseProg.h | 1 + .../operations/COM_ScaleOperation.cpp | 51 ++-- .../operations/COM_ScaleOperation.h | 18 +- 11 files changed, 372 insertions(+), 50 deletions(-) create mode 100644 source/blender/blenlib/BLI_math_interp.h create mode 100644 source/blender/blenlib/intern/math_interp.c diff --git a/source/blender/blenlib/BLI_math.h b/source/blender/blenlib/BLI_math.h index 89c37daae84..db2fed433da 100644 --- a/source/blender/blenlib/BLI_math.h +++ b/source/blender/blenlib/BLI_math.h @@ -58,6 +58,7 @@ #include "BLI_math_rotation.h" #include "BLI_math_vector.h" #include "BLI_math_geom.h" +#include "BLI_math_interp.h" #endif /* __BLI_MATH_H__ */ diff --git a/source/blender/blenlib/BLI_math_interp.h b/source/blender/blenlib/BLI_math_interp.h new file mode 100644 index 00000000000..3a107be32bd --- /dev/null +++ b/source/blender/blenlib/BLI_math_interp.h @@ -0,0 +1,35 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 by Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#ifndef BLI_MATH_INTERP +#define BLI_MATH_INTERP + +void BLI_bicubic_interpolation(const float *buffer, float *output, int width, int height, int components, float u, float v); +void BLI_bilinear_interpolation(const float *buffer, float *output, int width, int height, int components, float u, float v); + +#endif diff --git a/source/blender/blenlib/CMakeLists.txt b/source/blender/blenlib/CMakeLists.txt index 6839f05bfbc..a6435bcbd50 100644 --- a/source/blender/blenlib/CMakeLists.txt +++ b/source/blender/blenlib/CMakeLists.txt @@ -70,6 +70,7 @@ set(SRC intern/math_color_inline.c intern/math_geom.c intern/math_geom_inline.c + intern/math_interp.c intern/math_matrix.c intern/math_rotation.c intern/math_vector.c diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c new file mode 100644 index 00000000000..742669354a9 --- /dev/null +++ b/source/blender/blenlib/intern/math_interp.c @@ -0,0 +1,235 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012 by Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Sergey Sharybin + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#include + +#include "BLI_math.h" + +/************************************************************************** + * INTERPOLATIONS + * + * Reference and docs: + * http://wiki.blender.org/index.php/User:Damiles#Interpolations_Algorithms + ***************************************************************************/ + +/* BICUBIC Interpolation functions + * More info: http://wiki.blender.org/index.php/User:Damiles#Bicubic_pixel_interpolation + * function assumes out to be zero'ed, only does RGBA */ + +static float P(float k) +{ + float p1, p2, p3, p4; + p1 = MAX2(k + 2.0f, 0); + p2 = MAX2(k + 1.0f, 0); + p3 = MAX2(k, 0); + p4 = MAX2(k - 1.0f, 0); + return (float)(1.0f / 6.0f) * (p1 * p1 * p1 - 4.0f * p2 * p2 * p2 + 6.0f * p3 * p3 * p3 - 4.0f * p4 * p4 * p4); +} + + +#if 0 +/* older, slower function, works the same as above */ +static float P(float k) +{ + return (float)(1.0f / 6.0f) * (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f * pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f * pow(MAX2(k, 0), 3.0f) - 4.0f * pow(MAX2(k - 1.0f, 0), 3.0f)); +} +#endif + +/* BICUBIC INTERPOLATION */ +void BLI_bicubic_interpolation(const float *buffer, float *output, int width, int height, int components, float u, float v) +{ + int i, j, n, m, x1, y1; + float a, b, w, wx, wy[4], out[4]; + const float *data; + + /* sample area entirely outside image? */ + if (ceil(u) < 0 || floor(u) > width - 1 || ceil(v) < 0 || floor(v) > height - 1) { + return; + } + + i = (int)floor(u); + j = (int)floor(v); + a = u - i; + b = v - j; + + zero_v4(out); + +/* Optimized and not so easy to read */ + + /* avoid calling multiple times */ + wy[0] = P(b - (-1)); + wy[1] = P(b - 0); + wy[2] = P(b - 1); + wy[3] = P(b - 2); + + for (n = -1; n <= 2; n++) { + x1 = i + n; + CLAMP(x1, 0, width - 1); + wx = P(n - a); + for (m = -1; m <= 2; m++) { + y1 = j + m; + CLAMP(y1, 0, height - 1); + /* normally we could do this */ + /* w = P(n-a) * P(b-m); */ + /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */ + w = wx * wy[m + 1]; + + data = buffer + width * y1 * 4 + 4 * x1; + + if (components == 1) { + out[0] += data[0] * w; + } + else if (components == 2) { + out[0] += data[0] * w; + out[1] += data[1] * w; + } + else if (components == 3) { + out[0] += data[0] * w; + out[1] += data[1] * w; + out[2] += data[2] * w; + } + else { + out[0] += data[0] * w; + out[1] += data[1] * w; + out[2] += data[2] * w; + out[3] += data[3] * w; + } + } + } + +/* Done with optimized part */ + +#if 0 + /* older, slower function, works the same as above */ + for (n = -1; n <= 2; n++) { + for (m = -1; m <= 2; m++) { + x1 = i + n; + y1 = j + m; + if (x1 > 0 && x1 < width && y1 > 0 && y1 < height) { + data = in->rect_float + width * y1 * 4 + 4 * x1; + + if (components == 1) { + out[0] += data[0] * P(n - a) * P(b - m); + } + else if (components == 2) { + out[0] += data[0] * P(n - a) * P(b - m); + out[1] += data[1] * P(n - a) * P(b - m); + } + else if (components == 3) { + out[0] += data[0] * P(n - a) * P(b - m); + out[1] += data[1] * P(n - a) * P(b - m); + out[2] += data[2] * P(n - a) * P(b - m); + } + else { + out[0] += data[0] * P(n - a) * P(b - m); + out[1] += data[1] * P(n - a) * P(b - m); + out[2] += data[2] * P(n - a) * P(b - m); + out[3] += data[3] * P(n - a) * P(b - m); + } + } + } + } +#endif + + if (components == 1) { + output[0] = out[0]; + } + else if (components == 2) { + output[0] = out[0]; + output[1] = out[1]; + } + else if (components == 3) { + output[0] = out[0]; + output[1] = out[1]; + output[2] = out[2]; + } + else { + output[0] = out[0]; + output[1] = out[1]; + output[2] = out[2]; + output[3] = out[3]; + } +} + +/* BILINEAR INTERPOLATION */ +void BLI_bilinear_interpolation(const float *buffer, float *output, int width, int height, int components, float u, float v) +{ + const float *row1, *row2, *row3, *row4; + float a, b; + float a_b, ma_b, a_mb, ma_mb; + float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + int y1, y2, x1, x2; + + /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ + + x1 = (int)floor(u); + x2 = (int)ceil(u); + y1 = (int)floor(v); + y2 = (int)ceil(v); + + /* sample area entirely outside image? */ + if (x2 < 0 || x1 > width - 1 || y2 < 0 || y1 > height - 1) { + return; + } + + /* sample including outside of edges of image */ + if (x1 < 0 || y1 < 0) row1 = empty; + else row1 = buffer + width * y1 * 4 + 4 * x1; + + if (x1 < 0 || y2 > height - 1) row2 = empty; + else row2 = buffer + width * y2 * 4 + 4 * x1; + + if (x2 > width - 1 || y1 < 0) row3 = empty; + else row3 = buffer + width * y1 * 4 + 4 * x2; + + if (x2 > width - 1 || y2 > height - 1) row4 = empty; + else row4 = buffer + width * y2 * 4 + 4 * x2; + + a = u - floorf(u); + b = v - floorf(v); + a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); + + if (components == 1) { + output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + } + else if (components == 2) { + output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + } + else if (components == 3) { + output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + } + else { + output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + } +} diff --git a/source/blender/compositor/nodes/COM_ScaleNode.cpp b/source/blender/compositor/nodes/COM_ScaleNode.cpp index c51782b77af..d535e71a33c 100644 --- a/source/blender/compositor/nodes/COM_ScaleNode.cpp +++ b/source/blender/compositor/nodes/COM_ScaleNode.cpp @@ -26,6 +26,7 @@ #include "COM_ExecutionSystem.h" #include "BKE_node.h" #include "COM_SetValueOperation.h" +#include "COM_SetSamplerOperation.h" ScaleNode::ScaleNode(bNode *editorNode) : Node(editorNode) { @@ -38,7 +39,9 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c InputSocket *inputXSocket = this->getInputSocket(1); InputSocket *inputYSocket = this->getInputSocket(2); OutputSocket *outputSocket = this->getOutputSocket(0); + BaseScaleOperation *scaleoperation; bNode *bnode = this->getbNode(); + switch (bnode->custom1) { case CMP_SCALE_RELATIVE: { ScaleOperation *operation = new ScaleOperation(); @@ -46,8 +49,8 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); inputXSocket->relinkConnections(operation->getInputSocket(1), 1, graph); inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph); - outputSocket->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); + + scaleoperation = operation; } break; case CMP_SCALE_SCENEPERCENT: { @@ -57,9 +60,9 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); addLink(graph, scaleFactorOperation->getOutputSocket(), operation->getInputSocket(1)); addLink(graph, scaleFactorOperation->getOutputSocket(), operation->getInputSocket(2)); - outputSocket->relinkConnections(operation->getOutputSocket(0)); graph->addOperation(scaleFactorOperation); - graph->addOperation(operation); + + scaleoperation = operation; } break; @@ -75,9 +78,9 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c operation->setNewWidth(rd->xsch * rd->size / 100.0f); operation->setNewHeight(rd->ysch * rd->size / 100.0f); inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); - outputSocket->relinkConnections(operation->getOutputSocket(0)); operation->getInputSocket(0)->getConnection()->setIgnoreResizeCheck(true); - graph->addOperation(operation); + + scaleoperation = operation; } break; @@ -87,9 +90,12 @@ void ScaleNode::convertToOperations(ExecutionSystem *graph, CompositorContext *c inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); inputXSocket->relinkConnections(operation->getInputSocket(1), 1, graph); inputYSocket->relinkConnections(operation->getInputSocket(2), 2, graph); - outputSocket->relinkConnections(operation->getOutputSocket(0)); - graph->addOperation(operation); + + scaleoperation = operation; } break; } + + outputSocket->relinkConnections(scaleoperation->getOutputSocket(0)); + graph->addOperation(scaleoperation); } diff --git a/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp b/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp index b28ee3eade1..a579503a829 100644 --- a/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp +++ b/source/blender/compositor/nodes/COM_Stabilize2dNode.cpp @@ -72,6 +72,8 @@ void Stabilize2dNode::convertToOperations(ExecutionSystem *graph, CompositorCont addLink(graph, scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(1)); addLink(graph, scaleAttribute->getOutputSocket(), scaleOperation->getInputSocket(2)); + scaleOperation->setSampler((PixelSampler)this->getbNode()->custom1); + addLink(graph, scaleOperation->getOutputSocket(), rotateOperation->getInputSocket(0)); addLink(graph, angleAttribute->getOutputSocket(), rotateOperation->getInputSocket(1)); rotateOperation->setDoDegree2RadConversion(false); diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index 7106b015fe6..29d8bbea2db 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -49,7 +49,6 @@ MovieDistortionOperation::MovieDistortionOperation(bool distortion) : NodeOperat this->m_movieClip = NULL; this->m_cache = NULL; this->m_distortion = distortion; - setComplex(true); } void MovieDistortionOperation::initExecution() diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp index a4015c6283f..f4160a5fbcb 100644 --- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp @@ -69,6 +69,46 @@ void RenderLayersBaseProg::initExecution() } } +void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, PixelSampler sampler) +{ + unsigned int offset; + int ix, iy; + int width = this->getWidth(), height = this->getHeight(); + + switch (sampler) { + case COM_PS_NEAREST: + ix = x; + iy = y; + offset = (iy * width + ix) * this->m_elementsize; + + if (this->m_elementsize == 1) + output[0] = this->m_inputBuffer[offset]; + else if (this->m_elementsize == 3) + copy_v3_v3(output, &this->m_inputBuffer[offset]); + else + copy_v4_v4(output, &this->m_inputBuffer[offset]); + + break; + + case COM_PS_BILINEAR: + BLI_bilinear_interpolation(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + break; + + case COM_PS_BICUBIC: + BLI_bicubic_interpolation(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + break; + } + + if (this->m_elementsize == 1) { + output[1] = 0.0f; + output[2] = 0.0f; + output[3] = 0.0f; + } + else if (this->m_elementsize == 3) { + output[3] = 1.0f; + } +} + void RenderLayersBaseProg::executePixel(float output[4], float x, float y, PixelSampler sampler) { int ix = x; @@ -78,20 +118,7 @@ void RenderLayersBaseProg::executePixel(float output[4], float x, float y, Pixel zero_v4(output); } else { - unsigned int offset = (iy * this->getWidth() + ix) * this->m_elementsize; - if (this->m_elementsize == 1) { - output[0] = this->m_inputBuffer[offset]; - output[1] = 0.0f; - output[2] = 0.0f; - output[3] = 0.0f; - } - else if (this->m_elementsize == 3) { - copy_v3_v3(output, &this->m_inputBuffer[offset]); - output[3] = 1.0f; - } - else { - copy_v4_v4(output, &this->m_inputBuffer[offset]); - } + doInterpolation(output, x, y, sampler); } } diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h b/source/blender/compositor/operations/COM_RenderLayersBaseProg.h index ea57d4bc421..3916862a0b3 100644 --- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.h +++ b/source/blender/compositor/operations/COM_RenderLayersBaseProg.h @@ -80,6 +80,7 @@ protected: */ inline float *getInputBuffer() { return this->m_inputBuffer; } + void doInterpolation(float output[4], float x, float y, PixelSampler sampler); public: /** * setter for the scene field. Will be called from diff --git a/source/blender/compositor/operations/COM_ScaleOperation.cpp b/source/blender/compositor/operations/COM_ScaleOperation.cpp index 276b2f54b6e..9e8f5af0ef0 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.cpp +++ b/source/blender/compositor/operations/COM_ScaleOperation.cpp @@ -29,7 +29,16 @@ * note: use bilinear because bicubic makes fuzzy even when not scaling at all (1:1) */ -ScaleOperation::ScaleOperation() : NodeOperation() +BaseScaleOperation::BaseScaleOperation() +{ +#ifdef USE_FORCE_BILINEAR + m_sampler = (int) COM_PS_BILINEAR; +#else + m_sampler = -1; +#endif +} + +ScaleOperation::ScaleOperation() : BaseScaleOperation() { this->addInputSocket(COM_DT_COLOR); this->addInputSocket(COM_DT_VALUE); @@ -59,22 +68,20 @@ void ScaleOperation::deinitExecution() void ScaleOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { -#ifdef USE_FORCE_BILINEAR - sampler = COM_PS_BILINEAR; -#endif + PixelSampler effective_sampler = getEffectiveSampler(sampler); float scaleX[4]; float scaleY[4]; - this->m_inputXOperation->read(scaleX, x, y, sampler); - this->m_inputYOperation->read(scaleY, x, y, sampler); + this->m_inputXOperation->read(scaleX, x, y, effective_sampler); + this->m_inputYOperation->read(scaleY, x, y, effective_sampler); const float scx = scaleX[0]; const float scy = scaleY[0]; float nx = this->m_centerX + (x - this->m_centerX) / scx; float ny = this->m_centerY + (y - this->m_centerY) / scy; - this->m_inputOperation->read(output, nx, ny, sampler); + this->m_inputOperation->read(output, nx, ny, effective_sampler); } bool ScaleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) @@ -94,12 +101,12 @@ bool ScaleOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOpe newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / scy; newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / scy; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } // SCALE ABSOLUTE -ScaleAbsoluteOperation::ScaleAbsoluteOperation() : NodeOperation() +ScaleAbsoluteOperation::ScaleAbsoluteOperation() : BaseScaleOperation() { this->addInputSocket(COM_DT_COLOR); this->addInputSocket(COM_DT_VALUE); @@ -129,15 +136,13 @@ void ScaleAbsoluteOperation::deinitExecution() void ScaleAbsoluteOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { -#ifdef USE_FORCE_BILINEAR - sampler = COM_PS_BILINEAR; -#endif + PixelSampler effective_sampler = getEffectiveSampler(sampler); float scaleX[4]; float scaleY[4]; - this->m_inputXOperation->read(scaleX, x, y, sampler); - this->m_inputYOperation->read(scaleY, x, y, sampler); + this->m_inputXOperation->read(scaleX, x, y, effective_sampler); + this->m_inputYOperation->read(scaleY, x, y, effective_sampler); const float scx = scaleX[0]; // target absolute scale const float scy = scaleY[0]; // target absolute scale @@ -151,7 +156,7 @@ void ScaleAbsoluteOperation::executePixel(float output[4], float x, float y, Pix float nx = this->m_centerX + (x - this->m_centerX) / relativeXScale; float ny = this->m_centerY + (y - this->m_centerY) / relativeYScale; - this->m_inputOperation->read(output, nx, ny, sampler); + this->m_inputOperation->read(output, nx, ny, effective_sampler); } bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) @@ -176,12 +181,12 @@ bool ScaleAbsoluteOperation::determineDependingAreaOfInterest(rcti *input, ReadB newInput.ymax = this->m_centerY + (input->ymax - this->m_centerY) / relateveYScale; newInput.ymin = this->m_centerY + (input->ymin - this->m_centerY) / relateveYScale; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } // Absolute fixed siez -ScaleFixedSizeOperation::ScaleFixedSizeOperation() : NodeOperation() +ScaleFixedSizeOperation::ScaleFixedSizeOperation() : BaseScaleOperation() { this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE); this->addOutputSocket(COM_DT_COLOR); @@ -250,17 +255,15 @@ void ScaleFixedSizeOperation::deinitExecution() void ScaleFixedSizeOperation::executePixel(float output[4], float x, float y, PixelSampler sampler) { -#ifdef USE_FORCE_BILINEAR - sampler = COM_PS_BILINEAR; -#endif + PixelSampler effective_sampler = getEffectiveSampler(sampler); if (this->m_is_offset) { float nx = ((x - this->m_offsetX) * this->m_relX); float ny = ((y - this->m_offsetY) * this->m_relY); - this->m_inputOperation->read(output, nx, ny, sampler); + this->m_inputOperation->read(output, nx, ny, effective_sampler); } else { - this->m_inputOperation->read(output, x * this->m_relX, y * this->m_relY, sampler); + this->m_inputOperation->read(output, x * this->m_relX, y * this->m_relY, effective_sampler); } } @@ -273,7 +276,7 @@ bool ScaleFixedSizeOperation::determineDependingAreaOfInterest(rcti *input, Read newInput.ymax = input->ymax * this->m_relY; newInput.ymin = input->ymin * this->m_relY; - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); + return BaseScaleOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); } void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], unsigned int preferredResolution[2]) @@ -281,7 +284,7 @@ void ScaleFixedSizeOperation::determineResolution(unsigned int resolution[2], un unsigned int nr[2]; nr[0] = this->m_newWidth; nr[1] = this->m_newHeight; - NodeOperation::determineResolution(resolution, nr); + BaseScaleOperation::determineResolution(resolution, nr); resolution[0] = this->m_newWidth; resolution[1] = this->m_newHeight; } diff --git a/source/blender/compositor/operations/COM_ScaleOperation.h b/source/blender/compositor/operations/COM_ScaleOperation.h index 4239ff063fb..f42cdbd78ed 100644 --- a/source/blender/compositor/operations/COM_ScaleOperation.h +++ b/source/blender/compositor/operations/COM_ScaleOperation.h @@ -25,7 +25,19 @@ #include "COM_NodeOperation.h" -class ScaleOperation : public NodeOperation { +class BaseScaleOperation : public NodeOperation { +public: + void setSampler(PixelSampler sampler) { this->m_sampler = (int) sampler; } + +protected: + BaseScaleOperation(); + + PixelSampler getEffectiveSampler(PixelSampler sampler) { return (m_sampler == -1) ? sampler : (PixelSampler) m_sampler; } + + int m_sampler; +}; + +class ScaleOperation : public BaseScaleOperation { private: SocketReader *m_inputOperation; SocketReader *m_inputXOperation; @@ -41,7 +53,7 @@ public: void deinitExecution(); }; -class ScaleAbsoluteOperation : public NodeOperation { +class ScaleAbsoluteOperation : public BaseScaleOperation { SocketReader *m_inputOperation; SocketReader *m_inputXOperation; SocketReader *m_inputYOperation; @@ -57,7 +69,7 @@ public: void deinitExecution(); }; -class ScaleFixedSizeOperation : public NodeOperation { +class ScaleFixedSizeOperation : public BaseScaleOperation { SocketReader *m_inputOperation; int m_newWidth; int m_newHeight; From 18300e8eab87c9133b88620bb8887b2441f4db46 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 10 Nov 2012 19:11:34 +0000 Subject: [PATCH 088/118] Movie clip: display stabilization border even if current frame failed to load --- source/blender/editors/space_clip/clip_draw.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index a2e4da719e9..02716c20588 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -252,7 +252,6 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy) { int x, y; - MovieClip *clip = ED_space_clip_get_clip(sc); /* find window pixel coordinates of origin */ UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); @@ -306,6 +305,15 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, IMB_display_buffer_release(cache_handle); } +} + +static void draw_stabilization_border(SpaceClip *sc, ARegion *ar, int width, int height, float zoomx, float zoomy) +{ + int x, y; + MovieClip *clip = ED_space_clip_get_clip(sc); + + /* find window pixel coordinates of origin */ + UI_view2d_to_region_no_clip(&ar->v2d, 0.0f, 0.0f, &x, &y); /* draw boundary border for frame if stabilization is enabled */ if (sc->flag & SC_SHOW_STABLE && clip->tracking.stabilization.flag & TRACKING_2D_STABILIZATION) { @@ -1469,6 +1477,7 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar) } if (width && height) { + draw_stabilization_border(sc, ar, width, height, zoomx, zoomy); draw_tracking_tracks(sc, ar, clip, width, height, zoomx, zoomy); draw_distortion(sc, ar, clip, width, height, zoomx, zoomy); } From 446f70f286154ca248dbdd25ecd68cdb9c6114d5 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sat, 10 Nov 2012 19:15:09 +0000 Subject: [PATCH 089/118] Removed determineDependingAreaOfInterest from movie distortion node It wasn't used and it was incorrect anyway (distortion could be more than 100px). --- .../operations/COM_MovieDistortionOperation.cpp | 12 ------------ .../operations/COM_MovieDistortionOperation.h | 1 - 2 files changed, 13 deletions(-) diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp index 29d8bbea2db..68a61dff801 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.cpp @@ -112,15 +112,3 @@ void MovieDistortionOperation::executePixel(float output[4], float x, float y, P this->m_inputOperation->read(output, x, y, COM_PS_BILINEAR); } } - -bool MovieDistortionOperation::determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output) -{ - rcti newInput; - - newInput.xmax = input->xmax + 100; - newInput.xmin = input->xmin - 100; - newInput.ymax = input->ymax + 100; - newInput.ymin = input->ymin - 100; - - return NodeOperation::determineDependingAreaOfInterest(&newInput, readOperation, output); -} diff --git a/source/blender/compositor/operations/COM_MovieDistortionOperation.h b/source/blender/compositor/operations/COM_MovieDistortionOperation.h index 93cc555fdbc..9f8aa065e3e 100644 --- a/source/blender/compositor/operations/COM_MovieDistortionOperation.h +++ b/source/blender/compositor/operations/COM_MovieDistortionOperation.h @@ -155,7 +155,6 @@ protected: public: MovieDistortionOperation(bool distortion); - bool determineDependingAreaOfInterest(rcti *input, ReadBufferOperation *readOperation, rcti *output); void executePixel(float output[4], float x, float y, PixelSampler sampler); void initExecution(); From 1ca4670267c3709d1c233264012882b4c0902748 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sat, 10 Nov 2012 22:31:29 +0000 Subject: [PATCH 090/118] Cycles: panorama camera in viewport camera view now shows the render mapped to the camera border rather than the entire viewport. --- intern/cycles/blender/blender_camera.cpp | 190 +++++++++++------------ intern/cycles/render/camera.cpp | 30 ++-- intern/cycles/render/camera.h | 5 +- intern/cycles/util/util_boundbox.h | 71 +++++++++ 4 files changed, 177 insertions(+), 119 deletions(-) diff --git a/intern/cycles/blender/blender_camera.cpp b/intern/cycles/blender/blender_camera.cpp index af16e210301..61fe7cf254d 100644 --- a/intern/cycles/blender/blender_camera.cpp +++ b/intern/cycles/blender/blender_camera.cpp @@ -56,10 +56,8 @@ struct BlenderCamera { float sensor_width; float sensor_height; - float border_left; - float border_right; - float border_bottom; - float border_top; + BoundBox2D border; + BoundBox2D pano_viewplane; Transform matrix; }; @@ -75,8 +73,10 @@ static void blender_camera_init(BlenderCamera *bcam) bcam->sensor_height = 18.0f; bcam->sensor_fit = BlenderCamera::AUTO; bcam->shuttertime = 1.0f; - bcam->border_right = 1.0f; - bcam->border_top = 1.0f; + bcam->border.right = 1.0f; + bcam->border.top = 1.0f; + bcam->pano_viewplane.right = 1.0f; + bcam->pano_viewplane.top = 1.0f; } static float blender_camera_focal_distance(BL::Object b_ob, BL::Camera b_camera) @@ -199,7 +199,7 @@ static Transform blender_camera_matrix(const Transform& tfm, CameraType type) } static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, - float *left, float *right, float *bottom, float *top, float *aspectratio, float *sensor_size) + BoundBox2D *viewplane, float *aspectratio, float *sensor_size) { /* dimensions */ float xratio = width*bcam->pixelaspect.x; @@ -244,32 +244,26 @@ static void blender_camera_viewplane(BlenderCamera *bcam, int width, int height, if(bcam->type == CAMERA_PANORAMA) { /* set viewplane */ - *left = 0.0f; - *right = 1.0f; - *bottom = 0.0f; - *top = 1.0f; + *viewplane = bcam->pano_viewplane; } else { /* set viewplane */ - *left = -xaspect; - *right = xaspect; - *bottom = -yaspect; - *top = yaspect; + viewplane->left = -xaspect; + viewplane->right = xaspect; + viewplane->bottom = -yaspect; + viewplane->top = yaspect; /* zoom for 3d camera view */ - *left *= bcam->zoom; - *right *= bcam->zoom; - *bottom *= bcam->zoom; - *top *= bcam->zoom; + *viewplane = (*viewplane) * bcam->zoom; /* modify viewplane with camera shift and 3d camera view offset */ float dx = 2.0f*(*aspectratio*bcam->shift.x + bcam->offset.x*xaspect*2.0f); float dy = 2.0f*(*aspectratio*bcam->shift.y + bcam->offset.y*yaspect*2.0f); - *left += dx; - *right += dx; - *bottom += dy; - *top += dy; + viewplane->left += dx; + viewplane->right += dx; + viewplane->bottom += dy; + viewplane->top += dy; } } @@ -281,7 +275,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int /* viewplane */ blender_camera_viewplane(bcam, width, height, - &cam->left, &cam->right, &cam->bottom, &cam->top, &aspectratio, &sensor_size); + &cam->viewplane, &aspectratio, &sensor_size); /* sensor */ cam->sensorwidth = bcam->sensor_width; @@ -314,10 +308,7 @@ static void blender_camera_sync(Camera *cam, BlenderCamera *bcam, int width, int cam->shuttertime = bcam->shuttertime; /* border */ - cam->border_left = bcam->border_left; - cam->border_right = bcam->border_right; - cam->border_bottom = bcam->border_bottom; - cam->border_top = bcam->border_top; + cam->border = bcam->border; /* set update flag */ if(cam->modified(prevcam)) @@ -340,10 +331,10 @@ void BlenderSync::sync_camera(BL::Object b_override, int width, int height) /* border */ if(r.use_border()) { - bcam.border_left = r.border_min_x(); - bcam.border_right = r.border_max_x(); - bcam.border_bottom = r.border_min_y(); - bcam.border_top = r.border_max_y(); + bcam.border.left = r.border_min_x(); + bcam.border.right = r.border_max_x(); + bcam.border.bottom = r.border_min_y(); + bcam.border.top = r.border_max_y(); } /* camera object */ @@ -381,6 +372,9 @@ void BlenderSync::sync_camera_motion(BL::Object b_ob, int motion) /* Sync 3D View Camera */ +static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, + BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box); + static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height, bool skip_panorama = false) { /* 3d view parameters */ @@ -396,14 +390,25 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: if(b_ob) { blender_camera_from_object(bcam, b_ob, skip_panorama); - /* magic zoom formula */ - bcam->zoom = (float)b_rv3d.view_camera_zoom(); - bcam->zoom = (1.41421f + bcam->zoom/50.0f); - bcam->zoom *= bcam->zoom; - bcam->zoom = 2.0f/bcam->zoom; + if(!skip_panorama && bcam->type == CAMERA_PANORAMA) { + /* in panorama camera view, we map viewplane to camera border */ + BoundBox2D view_box, cam_box; - /* offset */ - bcam->offset = get_float2(b_rv3d.view_camera_offset()); + blender_camera_view_subset(b_scene, b_ob, b_v3d, b_rv3d, width, height, + &view_box, &cam_box); + + bcam->pano_viewplane = view_box.make_relative_to(cam_box); + } + else { + /* magic zoom formula */ + bcam->zoom = (float)b_rv3d.view_camera_zoom(); + bcam->zoom = (1.41421f + bcam->zoom/50.0f); + bcam->zoom *= bcam->zoom; + bcam->zoom = 2.0f/bcam->zoom; + + /* offset */ + bcam->offset = get_float2(b_rv3d.view_camera_offset()); + } } } else if(b_rv3d.view_perspective() == BL::RegionView3D::view_perspective_ORTHO) { @@ -427,6 +432,37 @@ static void blender_camera_from_view(BlenderCamera *bcam, BL::Scene b_scene, BL: bcam->matrix = transform_inverse(get_transform(b_rv3d.view_matrix())); } +static void blender_camera_view_subset(BL::Scene b_scene, BL::Object b_ob, BL::SpaceView3D b_v3d, + BL::RegionView3D b_rv3d, int width, int height, BoundBox2D *view_box, BoundBox2D *cam_box) +{ + BL::RenderSettings r = b_scene.render(); + BoundBox2D cam, view; + float view_aspect, cam_aspect, sensor_size; + + /* get viewport viewplane */ + BlenderCamera view_bcam; + blender_camera_init(&view_bcam); + blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true); + + blender_camera_viewplane(&view_bcam, width, height, + &view, &view_aspect, &sensor_size); + + /* get camera viewplane */ + BlenderCamera cam_bcam; + blender_camera_init(&cam_bcam); + blender_camera_from_object(&cam_bcam, b_ob, true); + + width = (int)(r.resolution_x()*r.resolution_percentage()/100); + height = (int)(r.resolution_y()*r.resolution_percentage()/100); + + blender_camera_viewplane(&cam_bcam, width, height, + &cam, &cam_aspect, &sensor_size); + + /* return */ + *view_box = view * (1.0f/view_aspect); + *cam_box = cam * (1.0f/cam_aspect); +} + static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) { @@ -442,10 +478,10 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp * assume viewport has got correctly clamped border already */ if(b_v3d.use_render_border()) { - bcam->border_left = b_v3d.render_border_min_x(); - bcam->border_right = b_v3d.render_border_max_x(); - bcam->border_bottom = b_v3d.render_border_min_y(); - bcam->border_top = b_v3d.render_border_max_y(); + bcam->border.left = b_v3d.render_border_min_x(); + bcam->border.right = b_v3d.render_border_max_x(); + bcam->border.bottom = b_v3d.render_border_min_y(); + bcam->border.top = b_v3d.render_border_max_y(); return; } @@ -458,60 +494,20 @@ static void blender_camera_border(BlenderCamera *bcam, BL::Scene b_scene, BL::Sp if(!b_ob) return; - bcam->border_left = r.border_min_x(); - bcam->border_right = r.border_max_x(); - bcam->border_bottom = r.border_min_y(); - bcam->border_top = r.border_max_y(); + bcam->border.left = r.border_min_x(); + bcam->border.right = r.border_max_x(); + bcam->border.bottom = r.border_min_y(); + bcam->border.top = r.border_max_y(); - float cam_left, cam_right, cam_bottom, cam_top; - float view_left, view_right, view_bottom, view_top; - float view_aspect, cam_aspect, sensor_size; + /* determine camera viewport subset */ + BoundBox2D view_box, cam_box; - /* get viewport viewplane */ - BlenderCamera view_bcam; - blender_camera_init(&view_bcam); - blender_camera_from_view(&view_bcam, b_scene, b_v3d, b_rv3d, width, height, true); - - blender_camera_viewplane(&view_bcam, width, height, - &view_left, &view_right, &view_bottom, &view_top, &view_aspect, &sensor_size); - - view_left /= view_aspect; - view_right /= view_aspect; - view_bottom /= view_aspect; - view_top /= view_aspect; - - /* get camera viewplane */ - BlenderCamera cam_bcam; - blender_camera_init(&cam_bcam); - blender_camera_from_object(&cam_bcam, b_ob, true); - - width = (int)(r.resolution_x()*r.resolution_percentage()/100); - height = (int)(r.resolution_y()*r.resolution_percentage()/100); - - blender_camera_viewplane(&cam_bcam, width, height, - &cam_left, &cam_right, &cam_bottom, &cam_top, &cam_aspect, &sensor_size); - - cam_left /= cam_aspect; - cam_right /= cam_aspect; - cam_bottom /= cam_aspect; - cam_top /= cam_aspect; + blender_camera_view_subset(b_scene, b_ob, b_v3d, b_rv3d, width, height, + &view_box, &cam_box); /* determine viewport subset matching camera border */ - float tmp_left = ((cam_left - view_left) / (view_right - view_left)); - float tmp_right = ((cam_right - view_left) / (view_right - view_left)); - float tmp_bottom = ((cam_bottom - view_bottom) / (view_top - view_bottom)); - float tmp_top = ((cam_top - view_bottom) / (view_top - view_bottom)); - - bcam->border_left = tmp_left + bcam->border_left*(tmp_right - tmp_left); - bcam->border_right = tmp_left + bcam->border_right*(tmp_right - tmp_left); - bcam->border_bottom = tmp_bottom + bcam->border_bottom*(tmp_top - tmp_bottom); - bcam->border_top = tmp_bottom + bcam->border_top*(tmp_top - tmp_bottom); - - /* clamp */ - bcam->border_left = clamp(bcam->border_left, 0.0f, 1.0f); - bcam->border_right = clamp(bcam->border_right, 0.0f, 1.0f); - bcam->border_bottom = clamp(bcam->border_bottom, 0.0f, 1.0f); - bcam->border_top = clamp(bcam->border_top, 0.0f, 1.0f); + cam_box = cam_box.make_relative_to(view_box); + bcam->border = cam_box.subset(bcam->border).clamp(); } void BlenderSync::sync_view(BL::SpaceView3D b_v3d, BL::RegionView3D b_rv3d, int width, int height) @@ -539,10 +535,10 @@ BufferParams BlenderSync::get_buffer_params(BL::Scene b_scene, BL::SpaceView3D b if(use_border) { /* border render */ - params.full_x = cam->border_left*width; - params.full_y = cam->border_bottom*height; - params.width = (int)(cam->border_right*width) - params.full_x; - params.height = (int)(cam->border_top*height) - params.full_y; + params.full_x = cam->border.left*width; + params.full_y = cam->border.bottom*height; + params.width = (int)(cam->border.right*width) - params.full_x; + params.height = (int)(cam->border.top*height) - params.full_y; /* survive in case border goes out of view or becomes too small */ params.width = max(params.width, 1); diff --git a/intern/cycles/render/camera.cpp b/intern/cycles/render/camera.cpp index 649936bec04..308ebd0794a 100644 --- a/intern/cycles/render/camera.cpp +++ b/intern/cycles/render/camera.cpp @@ -55,15 +55,10 @@ Camera::Camera() width = 1024; height = 512; - left = -((float)width/(float)height); - right = (float)width/(float)height; - bottom = -1.0f; - top = 1.0f; - - border_left = 0.0f; - border_right = 1.0f; - border_bottom = 0.0f; - border_top = 1.0f; + viewplane.left = -((float)width/(float)height); + viewplane.right = (float)width/(float)height; + viewplane.bottom = -1.0f; + viewplane.top = 1.0f; screentoworld = transform_identity(); rastertoworld = transform_identity(); @@ -95,10 +90,11 @@ void Camera::update() /* raster to screen */ Transform screentoraster = ndctoraster; - + screentoraster = ndctoraster * - transform_scale(1.0f/(right - left), 1.0f/(top - bottom), 1.0f) * - transform_translate(-left, -bottom, 0.0f); + transform_scale(1.0f/(viewplane.right - viewplane.left), + 1.0f/(viewplane.top - viewplane.bottom), 1.0f) * + transform_translate(-viewplane.left, -viewplane.bottom, 0.0f); Transform rastertoscreen = transform_inverse(screentoraster); @@ -265,14 +261,8 @@ bool Camera::modified(const Camera& cam) // modified for progressive render // (width == cam.width) && // (height == cam.height) && - (left == cam.left) && - (right == cam.right) && - (bottom == cam.bottom) && - (top == cam.top) && - (border_left == cam.border_left) && - (border_right == cam.border_right) && - (border_bottom == cam.border_bottom) && - (border_top == cam.border_top) && + (viewplane == cam.viewplane) && + (border == cam.border) && (matrix == cam.matrix) && (panorama_type == cam.panorama_type) && (fisheye_fov == cam.fisheye_fov) && diff --git a/intern/cycles/render/camera.h b/intern/cycles/render/camera.h index 1407c86e7c2..4c2de7b50b8 100644 --- a/intern/cycles/render/camera.h +++ b/intern/cycles/render/camera.h @@ -21,6 +21,7 @@ #include "kernel_types.h" +#include "util_boundbox.h" #include "util_transform.h" #include "util_types.h" @@ -65,10 +66,10 @@ public: /* screen */ int width, height; - float left, right, bottom, top; + BoundBox2D viewplane; /* border */ - float border_left, border_right, border_bottom, border_top; + BoundBox2D border; /* transformation */ Transform matrix; diff --git a/intern/cycles/util/util_boundbox.h b/intern/cycles/util/util_boundbox.h index b35c4c12bb8..a0cdf1761ad 100644 --- a/intern/cycles/util/util_boundbox.h +++ b/intern/cycles/util/util_boundbox.h @@ -31,6 +31,8 @@ using namespace std; CCL_NAMESPACE_BEGIN +/* 3D BoundBox */ + class BoundBox { public: @@ -160,6 +162,75 @@ __forceinline BoundBox intersect(const BoundBox& a, const BoundBox& b, const Bou return intersect(a, intersect(b, c)); } +/* 2D BoundBox */ + +class BoundBox2D { +public: + float left; + float right; + float bottom; + float top; + + BoundBox2D() + : left(0.0f), right(1.0f), bottom(0.0f), top(1.0f) + { + } + + bool operator==(const BoundBox2D& other) const + { + return (left == other.left && right == other.right && + bottom == other.bottom && top == other.top); + } + + BoundBox2D operator*(float f) const + { + BoundBox2D result; + + result.left = left*f; + result.right = right*f; + result.bottom = bottom*f; + result.top = top*f; + + return result; + } + + BoundBox2D subset(const BoundBox2D& other) const + { + BoundBox2D subset; + + subset.left = left + other.left*(right - left); + subset.right = left + other.right*(right - left); + subset.bottom = bottom + other.bottom*(top - bottom); + subset.top = bottom + other.top*(top - bottom); + + return subset; + } + + BoundBox2D make_relative_to(const BoundBox2D& other) const + { + BoundBox2D result; + + result.left = ((left - other.left) / (other.right - other.left)); + result.right = ((right - other.left) / (other.right - other.left)); + result.bottom = ((bottom - other.bottom) / (other.top - other.bottom)); + result.top = ((top - other.bottom) / (other.top - other.bottom)); + + return result; + } + + BoundBox2D clamp(float mn = 0.0f, float mx = 1.0f) + { + BoundBox2D result; + + result.left = ccl::clamp(left, mn, mx); + result.right = ccl::clamp(right, mn, mx); + result.bottom = ccl::clamp(bottom, mn, mx); + result.top = ccl::clamp(top, mn, mx); + + return result; + } +}; + CCL_NAMESPACE_END #endif /* __UTIL_BOUNDBOX_H__ */ From 67b74f96daa98809d5f9a348adfcd561f5f54f07 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 10 Nov 2012 22:32:15 +0000 Subject: [PATCH 091/118] - property sensor was converting floating point values to text then back to float - for floating point properties. - IntValue's GetNumber() was convert int -> float -> double. - BL_Shader was using STR_String rather then char*, where most callers had a char*, use a char* to avoid STR_String conversion-and-alloc on shader access. --- source/gameengine/Expressions/IntValue.cpp | 2 +- .../GameLogic/SCA_PropertySensor.cpp | 16 ++++-- source/gameengine/Ketsji/BL_Shader.cpp | 56 +++++++++---------- source/gameengine/Ketsji/BL_Shader.h | 6 +- 4 files changed, 43 insertions(+), 37 deletions(-) diff --git a/source/gameengine/Expressions/IntValue.cpp b/source/gameengine/Expressions/IntValue.cpp index cb6bc556bab..0261a4a2d02 100644 --- a/source/gameengine/Expressions/IntValue.cpp +++ b/source/gameengine/Expressions/IntValue.cpp @@ -286,7 +286,7 @@ cInt CIntValue::GetInt() double CIntValue::GetNumber() { - return (float) m_int; + return (double) m_int; } diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index 5dd4cc501ca..ced3b8418fe 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -126,7 +126,6 @@ bool SCA_PropertySensor::Evaluate() bool SCA_PropertySensor::CheckPropertyCondition() { - m_recentresult=false; bool result=false; bool reverse = false; @@ -174,7 +173,7 @@ bool SCA_PropertySensor::CheckPropertyCondition() case KX_PROPSENSOR_EXPRESSION: { - /* +#if 0 if (m_rightexpr) { CValue* resultval = m_rightexpr->Calculate(); @@ -189,7 +188,7 @@ bool SCA_PropertySensor::CheckPropertyCondition() result = resultval->GetNumber() != 0; } } - */ +#endif break; } case KX_PROPSENSOR_INTERVAL: @@ -197,7 +196,16 @@ bool SCA_PropertySensor::CheckPropertyCondition() CValue* orgprop = GetParent()->FindIdentifier(m_checkpropname); if (!orgprop->IsError()) { - float val = orgprop->GetText().ToFloat(), min = m_checkpropval.ToFloat(), max = m_checkpropmaxval.ToFloat(); + const float min = m_checkpropval.ToFloat(); + const float max = m_checkpropmaxval.ToFloat(); + float val; + + if (dynamic_cast(orgprop) == NULL) { + val = orgprop->GetNumber(); + } + else { + val = orgprop->GetText().ToFloat(); + } result = (min <= val) && (val <= max); } diff --git a/source/gameengine/Ketsji/BL_Shader.cpp b/source/gameengine/Ketsji/BL_Shader.cpp index fb8e7beb157..b047588df5a 100644 --- a/source/gameengine/Ketsji/BL_Shader.cpp +++ b/source/gameengine/Ketsji/BL_Shader.cpp @@ -571,41 +571,39 @@ void BL_Shader::Update( const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) } -int BL_Shader::GetAttribLocation(const STR_String& name) +int BL_Shader::GetAttribLocation(const char *name) { - if ( GLEW_ARB_fragment_shader && - GLEW_ARB_vertex_shader && - GLEW_ARB_shader_objects - ) + if (GLEW_ARB_fragment_shader && + GLEW_ARB_vertex_shader && + GLEW_ARB_shader_objects) { - return glGetAttribLocationARB(mShader, name.ReadPtr()); + return glGetAttribLocationARB(mShader, name); } return -1; } -void BL_Shader::BindAttribute(const STR_String& attr, int loc) +void BL_Shader::BindAttribute(const char *attr, int loc) { - if ( GLEW_ARB_fragment_shader && - GLEW_ARB_vertex_shader && - GLEW_ARB_shader_objects - ) + if (GLEW_ARB_fragment_shader && + GLEW_ARB_vertex_shader && + GLEW_ARB_shader_objects ) { - glBindAttribLocationARB(mShader, loc, attr.ReadPtr()); + glBindAttribLocationARB(mShader, loc, attr); } } -int BL_Shader::GetUniformLocation(const STR_String& name) +int BL_Shader::GetUniformLocation(const char *name) { if ( GLEW_ARB_fragment_shader && GLEW_ARB_vertex_shader && - GLEW_ARB_shader_objects + GLEW_ARB_shader_objects ) { MT_assert(mShader!=0); - int location = glGetUniformLocationARB(mShader, name.ReadPtr()); + int location = glGetUniformLocationARB(mShader, name); if (location == -1) - spit("Invalid uniform value: " << name.ReadPtr() << "."); + spit("Invalid uniform value: " << name << "."); return location; } @@ -900,7 +898,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setSampler, "setSampler(name, index)" ) Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int index=-1; if (PyArg_ParseTuple(args, "si:setSampler", &uniform, &index)) { @@ -941,7 +939,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1f, "setUniform1f(name, fx)" ) Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; float value=0; if (PyArg_ParseTuple(args, "sf:setUniform1f", &uniform, &value )) { @@ -965,7 +963,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2f, "setUniform2f(name, fx, fy)") if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; float array[2] = {0, 0}; if (PyArg_ParseTuple(args, "sff:setUniform2f", &uniform, &array[0],&array[1] )) { @@ -989,7 +987,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3f, "setUniform3f(name, fx,fy,fz) ") if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; float array[3] = {0, 0, 0}; if (PyArg_ParseTuple(args, "sfff:setUniform3f", &uniform, &array[0],&array[1],&array[2])) { @@ -1014,7 +1012,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4f, "setUniform4f(name, fx,fy,fz, fw) " if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; float array[4] = {0, 0, 0, 0}; if (PyArg_ParseTuple(args, "sffff:setUniform4f", &uniform, &array[0],&array[1],&array[2], &array[3])) { @@ -1038,7 +1036,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform1i, "setUniform1i(name, ix)" ) if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int value=0; if (PyArg_ParseTuple(args, "si:setUniform1i", &uniform, &value )) { @@ -1062,7 +1060,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform2i, "setUniform2i(name, ix, iy)") if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int array[2] = {0, 0}; if (PyArg_ParseTuple(args, "sii:setUniform2i", &uniform, &array[0],&array[1] )) { @@ -1087,7 +1085,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform3i, "setUniform3i(name, ix,iy,iz) ") Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int array[3] = {0, 0, 0}; if (PyArg_ParseTuple(args, "siii:setUniform3i", &uniform, &array[0],&array[1],&array[2])) { @@ -1110,7 +1108,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniform4i, "setUniform4i(name, ix,iy,iz, iw) " if (mError) { Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int array[4] = {0, 0, 0, 0}; if (PyArg_ParseTuple(args, "siiii:setUniform4i", &uniform, &array[0],&array[1],&array[2], &array[3] )) { @@ -1296,7 +1294,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix4, 0,0,0,1 }; - const char *uniform=""; + const char *uniform; PyObject *matrix=0; int transp=0; // python use column major by default, so no transpose.... @@ -1342,7 +1340,7 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformMatrix3, 0,0,1, }; - const char *uniform=""; + const char *uniform; PyObject *matrix=0; int transp=0; // python use column major by default, so no transpose.... if (!PyArg_ParseTuple(args, "sO|i:setUniformMatrix3",&uniform, &matrix,&transp)) @@ -1404,9 +1402,9 @@ KX_PYMETHODDEF_DOC( BL_Shader, setUniformDef, "setUniformDef(name, enum)" ) Py_RETURN_NONE; } - const char *uniform=""; + const char *uniform; int nloc=0; - if (PyArg_ParseTuple(args, "si:setUniformDef",&uniform, &nloc)) + if (PyArg_ParseTuple(args, "si:setUniformDef", &uniform, &nloc)) { int loc = GetUniformLocation(uniform); if (loc != -1) diff --git a/source/gameengine/Ketsji/BL_Shader.h b/source/gameengine/Ketsji/BL_Shader.h index 82476873b85..243445d95c5 100644 --- a/source/gameengine/Ketsji/BL_Shader.h +++ b/source/gameengine/Ketsji/BL_Shader.h @@ -205,9 +205,9 @@ public: void SetUniformfv(int location,int type, float *param, int size,bool transpose=false); void SetUniformiv(int location,int type, int *param, int size,bool transpose=false); - int GetAttribLocation(const STR_String& name); - void BindAttribute(const STR_String& attr, int loc); - int GetUniformLocation(const STR_String& name); + int GetAttribLocation(const char *name); + void BindAttribute(const char *attr, int loc); + int GetUniformLocation(const char *name); void SetUniform(int uniform, const MT_Tuple2& vec); void SetUniform(int uniform, const MT_Tuple3& vec); From f8af8100d28910202f0b34f5aafea30321d59842 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sat, 10 Nov 2012 23:57:13 +0000 Subject: [PATCH 092/118] code cleanup: bge - rename 'type' to 'use_mcol' in material conversion. --- .../Converter/BL_BlenderDataConversion.cpp | 110 ++++++++---------- 1 file changed, 47 insertions(+), 63 deletions(-) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index 58ae415e9d3..d127f1fba78 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -423,64 +423,55 @@ static void SetDefaultLightMode(Scene* scene) // -- -static void GetRGB(short type, - MFace* mface, - MCol* mmcol, - Material *mat, - unsigned int &c0, - unsigned int &c1, - unsigned int &c2, - unsigned int &c3) +static void GetRGB( + const bool use_mcol, + MFace *mface, + MCol *mmcol, + Material *mat, + unsigned int &c0, + unsigned int &c1, + unsigned int &c2, + unsigned int &c3) { unsigned int color = 0xFFFFFFFFL; - switch (type) { - case 0: // vertex colors - { - if (mmcol) { - c0 = KX_Mcol2uint_new(mmcol[0]); - c1 = KX_Mcol2uint_new(mmcol[1]); - c2 = KX_Mcol2uint_new(mmcol[2]); - if (mface->v4) - c3 = KX_Mcol2uint_new(mmcol[3]); - } - else { // backup white - c0 = KX_rgbaint2uint_new(color); - c1 = KX_rgbaint2uint_new(color); - c2 = KX_rgbaint2uint_new(color); - if (mface->v4) - c3 = KX_rgbaint2uint_new( color ); - } - } break; - - - case 1: // material rgba - { - if (mat) { - union { - unsigned char cp[4]; - unsigned int integer; - } col_converter; - col_converter.cp[3] = (unsigned char) (mat->r * 255.0f); - col_converter.cp[2] = (unsigned char) (mat->g * 255.0f); - col_converter.cp[1] = (unsigned char) (mat->b * 255.0f); - col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f); - color = col_converter.integer; - } + if (use_mcol) { + // vertex colors + + if (mmcol) { + c0 = KX_Mcol2uint_new(mmcol[0]); + c1 = KX_Mcol2uint_new(mmcol[1]); + c2 = KX_Mcol2uint_new(mmcol[2]); + if (mface->v4) + c3 = KX_Mcol2uint_new(mmcol[3]); + } + else { // backup white c0 = KX_rgbaint2uint_new(color); c1 = KX_rgbaint2uint_new(color); c2 = KX_rgbaint2uint_new(color); if (mface->v4) - c3 = KX_rgbaint2uint_new(color); - } break; - - default: // white - { - c0 = KX_rgbaint2uint_new(color); - c1 = KX_rgbaint2uint_new(color); - c2 = KX_rgbaint2uint_new(color); - if (mface->v4) - c3 = KX_rgbaint2uint_new(color); - } break; + c3 = KX_rgbaint2uint_new( color ); + } + } + else { + // material rgba + if (mat) { + union { + unsigned char cp[4]; + unsigned int integer; + } col_converter; + col_converter.cp[3] = (unsigned char) (mat->r * 255.0f); + col_converter.cp[2] = (unsigned char) (mat->g * 255.0f); + col_converter.cp[1] = (unsigned char) (mat->b * 255.0f); + col_converter.cp[0] = (unsigned char) (mat->alpha * 255.0f); + color = col_converter.integer; + } + // backup white is fallback + + c0 = KX_rgbaint2uint_new(color); + c1 = KX_rgbaint2uint_new(color); + c2 = KX_rgbaint2uint_new(color); + if (mface->v4) + c3 = KX_rgbaint2uint_new(color); } } @@ -504,10 +495,7 @@ static bool ConvertMaterial( int numchan = -1, texalpha = 0; bool validmat = (mat!=0); bool validface = (tface!=0); - - short type = 0; - if ( validmat ) - type = 1; // material color + bool use_mcol = true; material->IdMode = DEFAULT_BLENDER; material->glslmat = (validmat)? glslmat: false; @@ -515,11 +503,7 @@ static bool ConvertMaterial( // -------------------------------- if (validmat) { - - // use vertex colors by explicitly setting - if (mat->mode &MA_VERTEXCOLP || glslmat) - type = 0; - + use_mcol = (mat->mode & MA_VERTEXCOLP || glslmat) ? true: false; // use lighting? material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT; material->ras_mode |= ( mat->game.flag & GEMAT_BACKCULL )?0:TWOSIDED; @@ -869,10 +853,10 @@ static bool ConvertMaterial( } unsigned int rgb[4]; - GetRGB(type,mface,mmcol,mat,rgb[0],rgb[1],rgb[2], rgb[3]); + GetRGB(use_mcol, mface, mmcol, mat, rgb[0], rgb[1], rgb[2], rgb[3]); // swap the material color, so MCol on bitmap font works - if (validmat && type==1 && (mat->game.flag & GEMAT_TEXT)) + if (validmat && use_mcol == false && (mat->game.flag & GEMAT_TEXT)) { rgb[0] = KX_rgbaint2uint_new(rgb[0]); rgb[1] = KX_rgbaint2uint_new(rgb[1]); From dfc55421dfed71b3b9cc074d1d3919bd02168ad7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 11 Nov 2012 00:39:08 +0000 Subject: [PATCH 093/118] game engine material conversion: don't use the material to convert vertex colors, then extract back out (pre face). --- .../Converter/BL_BlenderDataConversion.cpp | 29 +++++-------------- source/gameengine/Ketsji/BL_Material.cpp | 21 +------------- source/gameengine/Ketsji/BL_Material.h | 5 +--- .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 7 ++++- source/gameengine/Ketsji/KX_BlenderMaterial.h | 2 ++ .../gameengine/Ketsji/KX_PolygonMaterial.cpp | 2 +- source/gameengine/Ketsji/KX_PolygonMaterial.h | 2 +- 7 files changed, 20 insertions(+), 48 deletions(-) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index d127f1fba78..b5ff11007de 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -487,15 +487,14 @@ static bool ConvertMaterial( MTFace* tface, const char *tfaceName, MFace* mface, - MCol* mmcol, + MCol* mmcol, /* only for text, use first mcol, weak */ MTF_localLayer *layers, - bool glslmat) + const bool glslmat) { material->Initialize(); int numchan = -1, texalpha = 0; bool validmat = (mat!=0); bool validface = (tface!=0); - bool use_mcol = true; material->IdMode = DEFAULT_BLENDER; material->glslmat = (validmat)? glslmat: false; @@ -503,7 +502,6 @@ static bool ConvertMaterial( // -------------------------------- if (validmat) { - use_mcol = (mat->mode & MA_VERTEXCOLP || glslmat) ? true: false; // use lighting? material->ras_mode |= ( mat->mode & MA_SHLESS )?0:USE_LIGHT; material->ras_mode |= ( mat->game.flag & GEMAT_BACKCULL )?0:TWOSIDED; @@ -852,19 +850,9 @@ static bool ConvertMaterial( } } - unsigned int rgb[4]; - GetRGB(use_mcol, mface, mmcol, mat, rgb[0], rgb[1], rgb[2], rgb[3]); - - // swap the material color, so MCol on bitmap font works - if (validmat && use_mcol == false && (mat->game.flag & GEMAT_TEXT)) - { - rgb[0] = KX_rgbaint2uint_new(rgb[0]); - rgb[1] = KX_rgbaint2uint_new(rgb[1]); - rgb[2] = KX_rgbaint2uint_new(rgb[2]); - rgb[3] = KX_rgbaint2uint_new(rgb[3]); + if (validmat && mmcol) { /* color is only for text */ + material->m_mcol = *(unsigned int *)mmcol; } - - material->SetConversionRGB(rgb); material->SetConversionUV(uvName, uv); material->SetConversionUV2(uv2Name, uv2); @@ -1009,20 +997,19 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, bool twoside = false; if (converter->GetMaterials()) { + const bool glslmat = converter->GetGLSLMaterials(); + const bool use_mcol = ma ? (ma->mode & MA_VERTEXCOLP || glslmat) : true; /* do Blender Multitexture and Blender GLSL materials */ - unsigned int rgb[4]; MT_Point2 uv[4]; /* first is the BL_Material */ if (!bl_mat) bl_mat = new BL_Material(); ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol, - layers, converter->GetGLSLMaterials()); + layers, glslmat); /* vertex colors and uv's were stored in bl_mat temporarily */ - bl_mat->GetConversionRGB(rgb); - rgb0 = rgb[0]; rgb1 = rgb[1]; - rgb2 = rgb[2]; rgb3 = rgb[3]; + GetRGB(use_mcol, mface, mcol, ma, rgb0, rgb1, rgb2, rgb3); bl_mat->GetConversionUV(uv); uv0 = uv[0]; uv1 = uv[1]; diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp index 4c7518769e1..a7d89517a08 100644 --- a/source/gameengine/Ketsji/BL_Material.cpp +++ b/source/gameengine/Ketsji/BL_Material.cpp @@ -36,10 +36,7 @@ BL_Material::BL_Material() void BL_Material::Initialize() { - rgb[0] = 0; - rgb[1] = 0; - rgb[2] = 0; - rgb[3] = 0; + m_mcol = 0xFFFFFFFFL; IdMode = 0; ras_mode = 0; glslmat = 0; @@ -98,22 +95,6 @@ void BL_Material::Initialize() } } -void BL_Material::SetConversionRGB(unsigned int *nrgb) -{ - rgb[0]=*nrgb++; - rgb[1]=*nrgb++; - rgb[2]=*nrgb++; - rgb[3]=*nrgb; -} - -void BL_Material::GetConversionRGB(unsigned int *nrgb) -{ - *nrgb++ = rgb[0]; - *nrgb++ = rgb[1]; - *nrgb++ = rgb[2]; - *nrgb = rgb[3]; -} - void BL_Material::SetConversionUV(const STR_String& name, MT_Point2 *nuv) { uvName = name; diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index b67bd95f878..082e265f387 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -87,17 +87,14 @@ public: MTFace tface; /* copy of the derived meshes tface */ Image* img[MAXTEX]; EnvMap* cubemap[MAXTEX]; + unsigned int m_mcol; /* for text color (only) */ - unsigned int rgb[4]; MT_Point2 uv[4]; MT_Point2 uv2[4]; STR_String uvName; STR_String uv2Name; - void SetConversionRGB(unsigned int *rgb); - void GetConversionRGB(unsigned int *rgb); - void SetConversionUV(const STR_String& name, MT_Point2 *uv); void GetConversionUV(MT_Point2 *uv); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 2154beeb205..cb995c3f738 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -124,7 +124,7 @@ MTFace* KX_BlenderMaterial::GetMTFace(void) const unsigned int* KX_BlenderMaterial::GetMCol(void) const { // fonts on polys - return mMaterial->rgb; + return &mMaterial->m_mcol; } void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const @@ -138,6 +138,11 @@ void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const RAS_IPolyMaterial::GetMaterialRGBAColor(rgba); } +bool KX_BlenderMaterial::IsMaterial(BL_Material *bl_mat) const +{ + return (mMaterial == bl_mat); +} + Material *KX_BlenderMaterial::GetBlenderMaterial() const { return mMaterial->material; diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index 1653669ebcc..c38eb2a6fd0 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -76,6 +76,8 @@ public: TCachingInfo& cachingInfo )const; + /* mMaterial is private, but need this for conversion */ + bool IsMaterial(BL_Material *bl_mat) const; Material* GetBlenderMaterial() const; MTFace* GetMTFace(void) const; unsigned int* GetMCol(void) const; diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp index 36c94dc997b..f89b918f31b 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.cpp +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.cpp @@ -109,7 +109,7 @@ void KX_PolygonMaterial::Initialize( m_mcol = *mcol; } else { - memset(&m_mcol, 0, sizeof(m_mcol)); + m_mcol = 0; } m_material = ma; diff --git a/source/gameengine/Ketsji/KX_PolygonMaterial.h b/source/gameengine/Ketsji/KX_PolygonMaterial.h index 89bfb4ff9fb..2ce8f480c1c 100644 --- a/source/gameengine/Ketsji/KX_PolygonMaterial.h +++ b/source/gameengine/Ketsji/KX_PolygonMaterial.h @@ -60,7 +60,7 @@ class KX_PolygonMaterial : public PyObjectPlus, public RAS_IPolyMaterial private: /** Blender texture face structure. */ mutable MTFace m_tface; - mutable unsigned int m_mcol; + mutable unsigned int m_mcol; /* for text color (only) */ Material* m_material; #ifdef WITH_PYTHON From 83de5cb30831328548502126dff84ffdb72544f2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 11 Nov 2012 01:54:30 +0000 Subject: [PATCH 094/118] bge mesh conversion speedup, avoid calling ConvertMaterial() on every face. now do per material bucket. --- .../Converter/BL_BlenderDataConversion.cpp | 139 ++++++++++-------- source/gameengine/Ketsji/BL_Material.cpp | 34 +---- source/gameengine/Ketsji/BL_Material.h | 10 +- .../gameengine/Ketsji/KX_BlenderMaterial.cpp | 2 +- source/gameengine/Ketsji/KX_BlenderMaterial.h | 2 +- 5 files changed, 86 insertions(+), 101 deletions(-) diff --git a/source/gameengine/Converter/BL_BlenderDataConversion.cpp b/source/gameengine/Converter/BL_BlenderDataConversion.cpp index b5ff11007de..eb695e624e4 100644 --- a/source/gameengine/Converter/BL_BlenderDataConversion.cpp +++ b/source/gameengine/Converter/BL_BlenderDataConversion.cpp @@ -480,6 +480,45 @@ typedef struct MTF_localLayer { const char *name; } MTF_localLayer; +static void tface_to_uv_bge(const MFace *mface, const MTFace *tface, MT_Point2 uv[4]) +{ + uv[0].setValue(tface->uv[0]); + uv[1].setValue(tface->uv[1]); + uv[2].setValue(tface->uv[2]); + if (mface->v4) { + uv[3].setValue(tface->uv[3]); + } +} + +static void GetUV( + MFace *mface, + MTFace *tface, + MTF_localLayer *layers, + const int layer_uv[2], + MT_Point2 uv[4], + MT_Point2 uv2[4]) +{ + bool validface = (tface != NULL); + + uv2[0] = uv2[1] = uv2[2] = uv2[3] = MT_Point2(0.0f, 0.0f); + + /* No material, what to do? let's see what is in the UV and set the material accordingly + * light and visible is always on */ + if (layer_uv[0] != -1) { + tface_to_uv_bge(mface, layers[layer_uv[0]].face, uv); + if (layer_uv[1] != -1) { + tface_to_uv_bge(mface, layers[layer_uv[1]].face, uv2); + } + } + else if (validface) { + tface_to_uv_bge(mface, tface, uv); + } + else { + // nothing at all + uv[0] = uv[1] = uv[2] = uv[3] = MT_Point2(0.0f, 0.0f); + } +} + // ------------------------------------ static bool ConvertMaterial( BL_Material *material, @@ -489,6 +528,7 @@ static bool ConvertMaterial( MFace* mface, MCol* mmcol, /* only for text, use first mcol, weak */ MTF_localLayer *layers, + int layer_uv[2], const bool glslmat) { material->Initialize(); @@ -500,6 +540,9 @@ static bool ConvertMaterial( material->glslmat = (validmat)? glslmat: false; material->materialindex = mface->mat_nr; + /* default value for being unset */ + layer_uv[0] = layer_uv[1] = -1; + // -------------------------------- if (validmat) { // use lighting? @@ -754,33 +797,19 @@ static bool ConvertMaterial( // No material - old default TexFace properties material->ras_mode |= USE_LIGHT; } - MT_Point2 uv[4]; - MT_Point2 uv2[4]; - const char *uvName = "", *uv2Name = ""; - - uv2[0] = uv2[1] = uv2[2] = uv2[3] = MT_Point2(0.0f, 0.0f); + const char *uvName = "", *uv2Name = ""; /* No material, what to do? let's see what is in the UV and set the material accordingly * light and visible is always on */ if ( validface ) { material->tile = tface->tile; - - uv[0].setValue(tface->uv[0]); - uv[1].setValue(tface->uv[1]); - uv[2].setValue(tface->uv[2]); - - if (mface->v4) - uv[3].setValue(tface->uv[3]); - uvName = tfaceName; } else { // nothing at all material->alphablend = GEMAT_SOLID; material->tile = 0; - - uv[0] = uv[1] = uv[2] = uv[3] = MT_Point2(0.0f, 0.0f); } if (validmat && validface) { @@ -798,49 +827,30 @@ static bool ConvertMaterial( } // get uv sets - if (validmat) - { + if (validmat) { bool isFirstSet = true; // only two sets implemented, but any of the eight // sets can make up the two layers - for (int vind = 0; vindnum_enabled; vind++) - { + for (int vind = 0; vindnum_enabled; vind++) { BL_Mapping &map = material->mapping[vind]; - if (map.uvCoName.IsEmpty()) + if (map.uvCoName.IsEmpty()) { isFirstSet = false; - else - { - for (int lay=0; layuv[0]); - uvSet[1].setValue(layer.face->uv[1]); - uvSet[2].setValue(layer.face->uv[2]); - - if (mface->v4) - uvSet[3].setValue(layer.face->uv[3]); - else - uvSet[3].setValue(0.0f, 0.0f); - - if (isFirstSet) - { - uv[0] = uvSet[0]; uv[1] = uvSet[1]; - uv[2] = uvSet[2]; uv[3] = uvSet[3]; + if (strcmp(map.uvCoName.ReadPtr(), layer.name)==0) { + if (isFirstSet) { + layer_uv[0] = lay; isFirstSet = false; uvName = layer.name; } - else if (strcmp(layer.name, uvName) != 0) - { - uv2[0] = uvSet[0]; uv2[1] = uvSet[1]; - uv2[2] = uvSet[2]; uv2[3] = uvSet[3]; + else if (strcmp(layer.name, uvName) != 0) { + layer_uv[1] = lay; map.mapping |= USECUSTOMUV; uv2Name = layer.name; } @@ -853,8 +863,8 @@ static bool ConvertMaterial( if (validmat && mmcol) { /* color is only for text */ material->m_mcol = *(unsigned int *)mmcol; } - material->SetConversionUV(uvName, uv); - material->SetConversionUV2(uv2Name, uv2); + material->SetUVLayerName(uvName); + material->SetUVLayerName2(uv2Name); if (validmat) material->matname =(mat->id.name); @@ -900,6 +910,7 @@ RAS_MeshObject* BL_ConvertMesh(Mesh* mesh, Object* blenderobj, KX_Scene* scene, // Extract avaiable layers MTF_localLayer *layers = new MTF_localLayer[MAX_MTFACE]; + int layer_uv[2]; /* store uv1, uv2 layers */ for (int lay=0; layGetMaterials()) { + const bool is_bl_mat_new = (bl_mat == NULL); + //const bool is_kx_blmat_new = (kx_blmat == NULL); const bool glslmat = converter->GetGLSLMaterials(); const bool use_mcol = ma ? (ma->mode & MA_VERTEXCOLP || glslmat) : true; /* do Blender Multitexture and Blender GLSL materials */ - MT_Point2 uv[4]; + MT_Point2 uv_1[4]; + MT_Point2 uv_2[4]; /* first is the BL_Material */ - if (!bl_mat) + if (!bl_mat) { bl_mat = new BL_Material(); - ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol, - layers, glslmat); + } - /* vertex colors and uv's were stored in bl_mat temporarily */ + /* only */ + if (is_bl_mat_new || (bl_mat->material != ma)) { + ConvertMaterial(bl_mat, ma, tface, tfaceName, mface, mcol, + layers, layer_uv, glslmat); + } + + /* vertex colors and uv's from the faces */ GetRGB(use_mcol, mface, mcol, ma, rgb0, rgb1, rgb2, rgb3); + GetUV(mface, tface, layers, layer_uv, uv_1, uv_2); - bl_mat->GetConversionUV(uv); - uv0 = uv[0]; uv1 = uv[1]; - uv2 = uv[2]; uv3 = uv[3]; + uv0 = uv_1[0]; uv1 = uv_1[1]; + uv2 = uv_1[2]; uv3 = uv_1[3]; - bl_mat->GetConversionUV2(uv); - uv20 = uv[0]; uv21 = uv[1]; - uv22 = uv[2]; uv23 = uv[3]; + uv20 = uv_2[0]; uv21 = uv_2[1]; + uv22 = uv_2[2]; uv23 = uv_2[3]; /* then the KX_BlenderMaterial */ if (kx_blmat == NULL) kx_blmat = new KX_BlenderMaterial(); - kx_blmat->Initialize(scene, bl_mat, (ma?&ma->game:NULL)); + //if (is_kx_blmat_new || !kx_blmat->IsMaterial(bl_mat)) { + kx_blmat->Initialize(scene, bl_mat, (ma ? &ma->game : NULL)); + //} + polymat = static_cast(kx_blmat); } else { diff --git a/source/gameengine/Ketsji/BL_Material.cpp b/source/gameengine/Ketsji/BL_Material.cpp index a7d89517a08..0954aa0f7ab 100644 --- a/source/gameengine/Ketsji/BL_Material.cpp +++ b/source/gameengine/Ketsji/BL_Material.cpp @@ -63,11 +63,6 @@ void BL_Material::Initialize() share = false; int i; - for (i=0; i<4; i++) - { - uv[i] = MT_Point2(0.f,1.f); - uv2[i] = MT_Point2(0.f, 1.f); - } for (i=0; i 1 ) diff --git a/source/gameengine/Ketsji/BL_Material.h b/source/gameengine/Ketsji/BL_Material.h index 082e265f387..ef180ed2126 100644 --- a/source/gameengine/Ketsji/BL_Material.h +++ b/source/gameengine/Ketsji/BL_Material.h @@ -89,17 +89,11 @@ public: EnvMap* cubemap[MAXTEX]; unsigned int m_mcol; /* for text color (only) */ - MT_Point2 uv[4]; - MT_Point2 uv2[4]; - STR_String uvName; STR_String uv2Name; - void SetConversionUV(const STR_String& name, MT_Point2 *uv); - void GetConversionUV(MT_Point2 *uv); - - void SetConversionUV2(const STR_String& name, MT_Point2 *uv); - void GetConversionUV2(MT_Point2 *uv); + void SetUVLayerName(const STR_String &name); + void SetUVLayerName2(const STR_String &name); void SetSharedMaterial(bool v); bool IsShared(); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index cb995c3f738..88e26fd9a55 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -138,7 +138,7 @@ void KX_BlenderMaterial::GetMaterialRGBAColor(unsigned char *rgba) const RAS_IPolyMaterial::GetMaterialRGBAColor(rgba); } -bool KX_BlenderMaterial::IsMaterial(BL_Material *bl_mat) const +bool KX_BlenderMaterial::IsMaterial(const BL_Material *bl_mat) const { return (mMaterial == bl_mat); } diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.h b/source/gameengine/Ketsji/KX_BlenderMaterial.h index c38eb2a6fd0..7bc9c7c3863 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.h +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.h @@ -77,7 +77,7 @@ public: )const; /* mMaterial is private, but need this for conversion */ - bool IsMaterial(BL_Material *bl_mat) const; + bool IsMaterial(const BL_Material *bl_mat) const; Material* GetBlenderMaterial() const; MTFace* GetMTFace(void) const; unsigned int* GetMCol(void) const; From a9eb61047361534c5c6454716729c96b7c323d93 Mon Sep 17 00:00:00 2001 From: Ben Batt Date: Sun, 11 Nov 2012 04:53:20 +0000 Subject: [PATCH 095/118] Fix #32398: Mirror modifier with "Merge" enabled producing pairs of faces sharing the same set of vertices. Modified the CDDM_merge_verts function (currently only used by the Mirror modifier) to skip faces using all merged vertices. --- .../blender/blenkernel/intern/cdderivedmesh.c | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index a6b303f3556..c0e6bd54f53 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2254,6 +2254,11 @@ void CDDM_calc_normals_tessface(DerivedMesh *dm) * this is a really horribly written function. ger. - joeedh * * note, CDDM_recalc_tessellation has to run on the returned DM if you want to access tessfaces. + * + * Note: This function is currently only used by the Mirror modifier, so it + * skips any faces that have all vertices merged (to avoid creating pairs + * of faces sharing the same set of vertices). If used elsewhere, it may + * be necessary to make this functionality optional. */ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) { @@ -2297,14 +2302,11 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) newv[i] = newv[vtargetmap[i]]; } } - - /* find-replace merged vertices with target vertices */ - ml = cddm->mloop; - for (i = 0; i < totloop; i++, ml++) { - if (vtargetmap[ml->v] != -1) { - ml->v = vtargetmap[ml->v]; - } - } + + /* Don't remap vertices in cddm->mloop, because we need to know the original + indices in order to skip faces with all vertices merged. + The "update loop indices..." section further down remaps vertices in mloop. + */ /* now go through and fix edges and faces */ med = cddm->medge; @@ -2338,6 +2340,25 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) ml = cddm->mloop + mp->loopstart; + /* skip faces with all vertices merged */ + { + int all_vertices_merged = TRUE; + + for (j = 0; j < mp->totloop; j++, ml++) { + if (vtargetmap[ml->v] == -1) { + all_vertices_merged = FALSE; + break; + } + } + + if (UNLIKELY(all_vertices_merged)) + { + continue; + } + } + + ml = cddm->mloop + mp->loopstart; + c = 0; for (j = 0; j < mp->totloop; j++, ml++) { med = cddm->medge + ml->e; From 92c8c2ed69fa36eb9d68ebb7033bdf892e58996f Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Sun, 11 Nov 2012 08:48:35 +0000 Subject: [PATCH 096/118] Code de-duplication in imageprocess.c -- made it use interpolation functions from blenlib --- source/blender/blenlib/BLI_math_interp.h | 13 +- source/blender/blenlib/intern/math_interp.c | 232 +++++++++++++----- .../operations/COM_RenderLayersBaseProg.cpp | 4 +- source/blender/imbuf/intern/imageprocess.c | 197 +-------------- 4 files changed, 196 insertions(+), 250 deletions(-) diff --git a/source/blender/blenlib/BLI_math_interp.h b/source/blender/blenlib/BLI_math_interp.h index 3a107be32bd..21975763779 100644 --- a/source/blender/blenlib/BLI_math_interp.h +++ b/source/blender/blenlib/BLI_math_interp.h @@ -29,7 +29,16 @@ #ifndef BLI_MATH_INTERP #define BLI_MATH_INTERP -void BLI_bicubic_interpolation(const float *buffer, float *output, int width, int height, int components, float u, float v); -void BLI_bilinear_interpolation(const float *buffer, float *output, int width, int height, int components, float u, float v); +void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v); + +void BLI_bicubic_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v); + +void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v); + +void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v); #endif diff --git a/source/blender/blenlib/intern/math_interp.c b/source/blender/blenlib/intern/math_interp.c index 742669354a9..59a1c1f649c 100644 --- a/source/blender/blenlib/intern/math_interp.c +++ b/source/blender/blenlib/intern/math_interp.c @@ -60,12 +60,44 @@ static float P(float k) } #endif +static void vector_from_float(const float *data, float vector[4], int components) +{ + if (components == 1) { + vector[0] = data[0]; + } + else if (components == 3) { + copy_v3_v3(vector, data); + } + else { + copy_v4_v4(vector, data); + } +} + +static void vector_from_byte(const unsigned char *data, float vector[4], int components) +{ + if (components == 1) { + vector[0] = data[0]; + } + else if (components == 3) { + vector[0] = data[0]; + vector[1] = data[1]; + vector[2] = data[2]; + } + else { + vector[0] = data[0]; + vector[1] = data[1]; + vector[2] = data[2]; + vector[3] = data[3]; + } +} + /* BICUBIC INTERPOLATION */ -void BLI_bicubic_interpolation(const float *buffer, float *output, int width, int height, int components, float u, float v) +BLI_INLINE void bicubic_interpolation(const unsigned char *byte_buffer, const float *float_buffer, + unsigned char *byte_output, float *float_output, int width, int height, + int components, float u, float v) { int i, j, n, m, x1, y1; float a, b, w, wx, wy[4], out[4]; - const float *data; /* sample area entirely outside image? */ if (ceil(u) < 0 || floor(u) > width - 1 || ceil(v) < 0 || floor(v) > height - 1) { @@ -92,6 +124,8 @@ void BLI_bicubic_interpolation(const float *buffer, float *output, int width, in CLAMP(x1, 0, width - 1); wx = P(n - a); for (m = -1; m <= 2; m++) { + float data[4]; + y1 = j + m; CLAMP(y1, 0, height - 1); /* normally we could do this */ @@ -99,15 +133,20 @@ void BLI_bicubic_interpolation(const float *buffer, float *output, int width, in /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */ w = wx * wy[m + 1]; - data = buffer + width * y1 * 4 + 4 * x1; + if (float_output) { + const float *float_data = float_buffer + width * y1 * 4 + 4 * x1; + + vector_from_float(float_data, data, components); + } + else { + const unsigned char *byte_data = byte_buffer + width * y1 * 4 + 4 * x1; + + vector_from_byte(byte_data, data, components); + } if (components == 1) { out[0] += data[0] * w; } - else if (components == 2) { - out[0] += data[0] * w; - out[1] += data[1] * w; - } else if (components == 3) { out[0] += data[0] * w; out[1] += data[1] * w; @@ -131,15 +170,22 @@ void BLI_bicubic_interpolation(const float *buffer, float *output, int width, in x1 = i + n; y1 = j + m; if (x1 > 0 && x1 < width && y1 > 0 && y1 < height) { - data = in->rect_float + width * y1 * 4 + 4 * x1; + float data[4]; + + if (float_output) { + const float *float_data = float_buffer + width * y1 * 4 + 4 * x1; + + vector_from_float(float_data, data, components); + } + else { + const unsigned char *byte_data = byte_buffer + width * y1 * 4 + 4 * x1; + + vector_from_byte(byte_data, data, components); + } if (components == 1) { out[0] += data[0] * P(n - a) * P(b - m); } - else if (components == 2) { - out[0] += data[0] * P(n - a) * P(b - m); - out[1] += data[1] * P(n - a) * P(b - m); - } else if (components == 3) { out[0] += data[0] * P(n - a) * P(b - m); out[1] += data[1] * P(n - a) * P(b - m); @@ -156,33 +202,54 @@ void BLI_bicubic_interpolation(const float *buffer, float *output, int width, in } #endif - if (components == 1) { - output[0] = out[0]; - } - else if (components == 2) { - output[0] = out[0]; - output[1] = out[1]; - } - else if (components == 3) { - output[0] = out[0]; - output[1] = out[1]; - output[2] = out[2]; + if (float_output) { + if (components == 1) { + float_output[0] = out[0]; + } + else if (components == 3) { + copy_v3_v3(float_output, out); + } + else { + copy_v4_v4(float_output, out); + } } else { - output[0] = out[0]; - output[1] = out[1]; - output[2] = out[2]; - output[3] = out[3]; + if (components == 1) { + byte_output[0] = out[0]; + } + else if (components == 3) { + byte_output[0] = out[0]; + byte_output[1] = out[1]; + byte_output[2] = out[2]; + } + else { + byte_output[0] = out[0]; + byte_output[1] = out[1]; + byte_output[2] = out[2]; + byte_output[3] = out[3]; + } } } -/* BILINEAR INTERPOLATION */ -void BLI_bilinear_interpolation(const float *buffer, float *output, int width, int height, int components, float u, float v) +void BLI_bicubic_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v) +{ + bicubic_interpolation(NULL, buffer, NULL, output, width, height, components, u, v); +} + +void BLI_bicubic_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v) +{ + bicubic_interpolation(buffer, NULL, output, NULL, width, height, components, u, v); +} + +/* BILINEAR INTERPOLATION */ +BLI_INLINE void bilinear_interpolation(const unsigned char *byte_buffer, const float *float_buffer, + unsigned char *byte_output, float *float_output, int width, int height, + int components, float u, float v) { - const float *row1, *row2, *row3, *row4; float a, b; float a_b, ma_b, a_mb, ma_mb; - float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; int y1, y2, x1, x2; /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ @@ -197,39 +264,88 @@ void BLI_bilinear_interpolation(const float *buffer, float *output, int width, i return; } - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) row1 = empty; - else row1 = buffer + width * y1 * 4 + 4 * x1; + if (float_output) { + const float *row1, *row2, *row3, *row4; + float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - if (x1 < 0 || y2 > height - 1) row2 = empty; - else row2 = buffer + width * y2 * 4 + 4 * x1; + /* sample including outside of edges of image */ + if (x1 < 0 || y1 < 0) row1 = empty; + else row1 = float_buffer + width * y1 * 4 + 4 * x1; - if (x2 > width - 1 || y1 < 0) row3 = empty; - else row3 = buffer + width * y1 * 4 + 4 * x2; + if (x1 < 0 || y2 > height - 1) row2 = empty; + else row2 = float_buffer + width * y2 * 4 + 4 * x1; - if (x2 > width - 1 || y2 > height - 1) row4 = empty; - else row4 = buffer + width * y2 * 4 + 4 * x2; + if (x2 > width - 1 || y1 < 0) row3 = empty; + else row3 = float_buffer + width * y1 * 4 + 4 * x2; - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); + if (x2 > width - 1 || y2 > height - 1) row4 = empty; + else row4 = float_buffer + width * y2 * 4 + 4 * x2; - if (components == 1) { - output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - } - else if (components == 2) { - output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - } - else if (components == 3) { - output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + a = u - floorf(u); + b = v - floorf(v); + a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); + + if (components == 1) { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + } + else if (components == 3) { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + } + else { + float_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + float_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + float_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + float_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + } } else { - output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; - output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + const unsigned char *row1, *row2, *row3, *row4; + unsigned char empty[4] = {0, 0, 0, 0}; + + /* sample including outside of edges of image */ + if (x1 < 0 || y1 < 0) row1 = empty; + else row1 = byte_buffer + width * y1 * 4 + 4 * x1; + + if (x1 < 0 || y2 > height - 1) row2 = empty; + else row2 = byte_buffer + width * y2 * 4 + 4 * x1; + + if (x2 > width - 1 || y1 < 0) row3 = empty; + else row3 = byte_buffer + width * y1 * 4 + 4 * x2; + + if (x2 > width - 1 || y2 > height - 1) row4 = empty; + else row4 = byte_buffer + width * y2 * 4 + 4 * x2; + + a = u - floorf(u); + b = v - floorf(v); + a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); + + if (components == 1) { + byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + } + else if (components == 3) { + byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + byte_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + byte_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + } + else { + byte_output[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; + byte_output[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; + byte_output[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; + byte_output[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + } } } + +void BLI_bilinear_interpolation_fl(const float *buffer, float *output, int width, int height, + int components, float u, float v) +{ + bilinear_interpolation(NULL, buffer, NULL, output, width, height, components, u, v); +} + +void BLI_bilinear_interpolation_char(const unsigned char *buffer, unsigned char *output, int width, int height, + int components, float u, float v) +{ + bilinear_interpolation(buffer, NULL, output, NULL, width, height, components, u, v); +} diff --git a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp index f4160a5fbcb..2ca499683d3 100644 --- a/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp +++ b/source/blender/compositor/operations/COM_RenderLayersBaseProg.cpp @@ -91,11 +91,11 @@ void RenderLayersBaseProg::doInterpolation(float output[4], float x, float y, Pi break; case COM_PS_BILINEAR: - BLI_bilinear_interpolation(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + BLI_bilinear_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); break; case COM_PS_BICUBIC: - BLI_bicubic_interpolation(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); + BLI_bicubic_interpolation_fl(this->m_inputBuffer, output, width, height, this->m_elementsize, x, y); break; } diff --git a/source/blender/imbuf/intern/imageprocess.c b/source/blender/imbuf/intern/imageprocess.c index 57fbce710a1..a185c4ee3e0 100644 --- a/source/blender/imbuf/intern/imageprocess.c +++ b/source/blender/imbuf/intern/imageprocess.c @@ -43,6 +43,7 @@ #include "BLI_utildefines.h" #include "BLI_threads.h" #include "BLI_listbase.h" +#include "BLI_math.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" @@ -95,132 +96,15 @@ static void pixel_from_buffer(struct ImBuf *ibuf, unsigned char **outI, float ** *outF = ibuf->rect_float + offset; } -/************************************************************************** - * INTERPOLATIONS - * - * Reference and docs: - * http://wiki.blender.org/index.php/User:Damiles#Interpolations_Algorithms - ***************************************************************************/ - -/* BICUBIC Interpolation functions - * More info: http://wiki.blender.org/index.php/User:Damiles#Bicubic_pixel_interpolation - * function assumes out to be zero'ed, only does RGBA */ - -static float P(float k) -{ - float p1, p2, p3, p4; - p1 = MAX2(k + 2.0f, 0); - p2 = MAX2(k + 1.0f, 0); - p3 = MAX2(k, 0); - p4 = MAX2(k - 1.0f, 0); - return (float)(1.0f / 6.0f) * (p1 * p1 * p1 - 4.0f * p2 * p2 * p2 + 6.0f * p3 * p3 * p3 - 4.0f * p4 * p4 * p4); -} - - -#if 0 -/* older, slower function, works the same as above */ -static float P(float k) -{ - return (float)(1.0f / 6.0f) * (pow(MAX2(k + 2.0f, 0), 3.0f) - 4.0f * pow(MAX2(k + 1.0f, 0), 3.0f) + 6.0f * pow(MAX2(k, 0), 3.0f) - 4.0f * pow(MAX2(k - 1.0f, 0), 3.0f)); -} -#endif +/* BICUBIC Interpolation */ void bicubic_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - int i, j, n, m, x1, y1; - unsigned char *dataI; - float a, b, w, wx, wy[4], outR, outG, outB, outA, *dataF; - - /* sample area entirely outside image? */ - if (ceil(u) < 0 || floor(u) > in->x - 1 || ceil(v) < 0 || floor(v) > in->y - 1) { - return; - } - - /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ - - i = (int)floor(u); - j = (int)floor(v); - a = u - i; - b = v - j; - - outR = outG = outB = outA = 0.0f; - -/* Optimized and not so easy to read */ - - /* avoid calling multiple times */ - wy[0] = P(b - (-1)); - wy[1] = P(b - 0); - wy[2] = P(b - 1); - wy[3] = P(b - 2); - - for (n = -1; n <= 2; n++) { - x1 = i + n; - CLAMP(x1, 0, in->x - 1); - wx = P(n - a); - for (m = -1; m <= 2; m++) { - y1 = j + m; - CLAMP(y1, 0, in->y - 1); - /* normally we could do this */ - /* w = P(n-a) * P(b-m); */ - /* except that would call P() 16 times per pixel therefor pow() 64 times, better precalc these */ - w = wx * wy[m + 1]; - - if (outF) { - dataF = in->rect_float + in->x * y1 * 4 + 4 * x1; - outR += dataF[0] * w; - outG += dataF[1] * w; - outB += dataF[2] * w; - outA += dataF[3] * w; - } - if (outI) { - dataI = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1; - outR += dataI[0] * w; - outG += dataI[1] * w; - outB += dataI[2] * w; - outA += dataI[3] * w; - } - } - } - -/* Done with optimized part */ - -#if 0 - /* older, slower function, works the same as above */ - for (n = -1; n <= 2; n++) { - for (m = -1; m <= 2; m++) { - x1 = i + n; - y1 = j + m; - if (x1 > 0 && x1 < in->x && y1 > 0 && y1 < in->y) { - if (do_float) { - dataF = in->rect_float + in->x * y1 * 4 + 4 * x1; - outR += dataF[0] * P(n - a) * P(b - m); - outG += dataF[1] * P(n - a) * P(b - m); - outB += dataF[2] * P(n - a) * P(b - m); - outA += dataF[3] * P(n - a) * P(b - m); - } - if (do_rect) { - dataI = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1; - outR += dataI[0] * P(n - a) * P(b - m); - outG += dataI[1] * P(n - a) * P(b - m); - outB += dataI[2] * P(n - a) * P(b - m); - outA += dataI[3] * P(n - a) * P(b - m); - } - } - } - } -#endif - - if (outI) { - outI[0] = (int)outR; - outI[1] = (int)outG; - outI[2] = (int)outB; - outI[3] = (int)outA; - } if (outF) { - outF[0] = outR; - outF[1] = outG; - outF[2] = outB; - outF[3] = outA; + BLI_bicubic_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); + } + else { + BLI_bicubic_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v); } } @@ -239,77 +123,14 @@ void bicubic_interpolation(ImBuf *in, ImBuf *out, float u, float v, int xout, in bicubic_interpolation_color(in, outI, outF, u, v); } -/* function assumes out to be zero'ed, only does RGBA */ /* BILINEAR INTERPOLATION */ void bilinear_interpolation_color(struct ImBuf *in, unsigned char outI[4], float outF[4], float u, float v) { - float *row1, *row2, *row3, *row4, a, b; - unsigned char *row1I, *row2I, *row3I, *row4I; - float a_b, ma_b, a_mb, ma_mb; - float empty[4] = {0.0f, 0.0f, 0.0f, 0.0f}; - unsigned char emptyI[4] = {0, 0, 0, 0}; - int y1, y2, x1, x2; - - - /* ImBuf in must have a valid rect or rect_float, assume this is already checked */ - - x1 = (int)floor(u); - x2 = (int)ceil(u); - y1 = (int)floor(v); - y2 = (int)ceil(v); - - /* sample area entirely outside image? */ - if (x2 < 0 || x1 > in->x - 1 || y2 < 0 || y1 > in->y - 1) { - return; - } - if (outF) { - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) row1 = empty; - else row1 = in->rect_float + in->x * y1 * 4 + 4 * x1; - - if (x1 < 0 || y2 > in->y - 1) row2 = empty; - else row2 = in->rect_float + in->x * y2 * 4 + 4 * x1; - - if (x2 > in->x - 1 || y1 < 0) row3 = empty; - else row3 = in->rect_float + in->x * y1 * 4 + 4 * x2; - - if (x2 > in->x - 1 || y2 > in->y - 1) row4 = empty; - else row4 = in->rect_float + in->x * y2 * 4 + 4 * x2; - - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); - - outF[0] = ma_mb * row1[0] + a_mb * row3[0] + ma_b * row2[0] + a_b * row4[0]; - outF[1] = ma_mb * row1[1] + a_mb * row3[1] + ma_b * row2[1] + a_b * row4[1]; - outF[2] = ma_mb * row1[2] + a_mb * row3[2] + ma_b * row2[2] + a_b * row4[2]; - outF[3] = ma_mb * row1[3] + a_mb * row3[3] + ma_b * row2[3] + a_b * row4[3]; + BLI_bilinear_interpolation_fl(in->rect_float, outF, in->x, in->y, 4, u, v); } - if (outI) { - /* sample including outside of edges of image */ - if (x1 < 0 || y1 < 0) row1I = emptyI; - else row1I = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x1; - - if (x1 < 0 || y2 > in->y - 1) row2I = emptyI; - else row2I = (unsigned char *)in->rect + in->x * y2 * 4 + 4 * x1; - - if (x2 > in->x - 1 || y1 < 0) row3I = emptyI; - else row3I = (unsigned char *)in->rect + in->x * y1 * 4 + 4 * x2; - - if (x2 > in->x - 1 || y2 > in->y - 1) row4I = emptyI; - else row4I = (unsigned char *)in->rect + in->x * y2 * 4 + 4 * x2; - - a = u - floorf(u); - b = v - floorf(v); - a_b = a * b; ma_b = (1.0f - a) * b; a_mb = a * (1.0f - b); ma_mb = (1.0f - a) * (1.0f - b); - - /* need to add 0.5 to avoid rounding down (causes darken with the smear brush) - * tested with white images and this should not wrap back to zero */ - outI[0] = (ma_mb * row1I[0] + a_mb * row3I[0] + ma_b * row2I[0] + a_b * row4I[0]) + 0.5f; - outI[1] = (ma_mb * row1I[1] + a_mb * row3I[1] + ma_b * row2I[1] + a_b * row4I[1]) + 0.5f; - outI[2] = (ma_mb * row1I[2] + a_mb * row3I[2] + ma_b * row2I[2] + a_b * row4I[2]) + 0.5f; - outI[3] = (ma_mb * row1I[3] + a_mb * row3I[3] + ma_b * row2I[3] + a_b * row4I[3]) + 0.5f; + else { + BLI_bilinear_interpolation_char((unsigned char*) in->rect, outI, in->x, in->y, 4, u, v); } } From f5df1601d6c6d03377f30f3787b964cab71ec3e0 Mon Sep 17 00:00:00 2001 From: Jason Wilkins Date: Sun, 11 Nov 2012 09:07:29 +0000 Subject: [PATCH 097/118] replace 0 and 1 with FALSE and TRUE in BLF_global_font_init in blf.c --- source/blender/blenfont/intern/blf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index f3cc92e7a27..f56c0e7503c 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -149,10 +149,10 @@ static int blf_global_font_init(void) if (global_font_default == -1) { printf("Warning: Can't find default font!\n"); - return 0; + return FALSE; } else { - return 1; + return TRUE; } } From 47068e88fba5b8a79ae8a9a09dadac684869faa6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 11 Nov 2012 10:03:25 +0000 Subject: [PATCH 098/118] BGE: fix for 2 uses of uninitialized memory - property-sensor and object-color for materials. --- source/gameengine/GameLogic/SCA_PropertySensor.cpp | 8 +++----- source/gameengine/Ketsji/KX_GameObject.cpp | 1 + 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/source/gameengine/GameLogic/SCA_PropertySensor.cpp b/source/gameengine/GameLogic/SCA_PropertySensor.cpp index ced3b8418fe..f02ac495233 100644 --- a/source/gameengine/GameLogic/SCA_PropertySensor.cpp +++ b/source/gameengine/GameLogic/SCA_PropertySensor.cpp @@ -152,13 +152,11 @@ bool SCA_PropertySensor::CheckPropertyCondition() */ if (result==false && dynamic_cast(orgprop) != NULL) { float f; - - if (EOF == sscanf(m_checkpropval.ReadPtr(), "%f", &f)) - { - //error + if (sscanf(m_checkpropval.ReadPtr(), "%f", &f) == 1) { + result = (f == ((CFloatValue *)orgprop)->GetFloat()); } else { - result = (f == ((CFloatValue *)orgprop)->GetFloat()); + /* error */ } } /* end patch */ diff --git a/source/gameengine/Ketsji/KX_GameObject.cpp b/source/gameengine/Ketsji/KX_GameObject.cpp index a669f4346ea..4f3d020a3d9 100644 --- a/source/gameengine/Ketsji/KX_GameObject.cpp +++ b/source/gameengine/Ketsji/KX_GameObject.cpp @@ -99,6 +99,7 @@ KX_GameObject::KX_GameObject( m_bSuspendDynamics(false), m_bUseObjectColor(false), m_bIsNegativeScaling(false), + m_objectColor(1.0, 1.0, 1.0, 1.0), m_bVisible(true), m_bCulled(true), m_bOccluder(false), From c4f332084f202123b73b9623c892997c005ba948 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 11 Nov 2012 10:55:32 +0000 Subject: [PATCH 099/118] code cleanup: - blf doesnt have includes for TRUE/FALSE, use 1/0. - rename ogl_multisamples -> multi_sample, also shorten enum strings. --- release/scripts/startup/bl_ui/space_userpref.py | 2 +- source/blender/blenfont/intern/blf.c | 5 ++--- source/blender/makesrna/intern/rna_userdef.c | 12 ++++++------ source/blender/windowmanager/intern/wm_window.c | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py index de55eaba775..1a66d67bce5 100644 --- a/release/scripts/startup/bl_ui/space_userpref.py +++ b/release/scripts/startup/bl_ui/space_userpref.py @@ -446,7 +446,7 @@ class USERPREF_PT_system(Panel): #~ col.prop(system, "use_antialiasing") col.label(text="Window Draw Method:") col.prop(system, "window_draw_method", text="") - col.prop(system, "ogl_multisamples", text="") + col.prop(system, "multi_sample", text="") col.label(text="Text Draw Options:") col.prop(system, "use_text_antialiasing") col.label(text="Textures:") diff --git a/source/blender/blenfont/intern/blf.c b/source/blender/blenfont/intern/blf.c index f56c0e7503c..778b6c11e5a 100644 --- a/source/blender/blenfont/intern/blf.c +++ b/source/blender/blenfont/intern/blf.c @@ -28,7 +28,6 @@ * \ingroup blf */ - #include #include #include @@ -149,10 +148,10 @@ static int blf_global_font_init(void) if (global_font_default == -1) { printf("Warning: Can't find default font!\n"); - return FALSE; + return 0; } else { - return TRUE; + return 1; } } diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c index 3e9f5b44a3d..2081cf3df75 100644 --- a/source/blender/makesrna/intern/rna_userdef.c +++ b/source/blender/makesrna/intern/rna_userdef.c @@ -3019,11 +3019,11 @@ static void rna_def_userdef_system(BlenderRNA *brna) }; static EnumPropertyItem multi_sample_levels[] = { - {USER_MULTISAMPLE_NONE, "MULTISAMPLE_NONE", 0, "No MultiSample", "Do not use OpenGL MultiSample"}, - {USER_MULTISAMPLE_2, "MULTISAMPLE_2", 0, "MultiSample: 2", "Use 2x OpenGL MultiSample (requires restart)"}, - {USER_MULTISAMPLE_4, "MULTISAMPLE_4", 0, "MultiSample: 4", "Use 4x OpenGL MultiSample (requires restart)"}, - {USER_MULTISAMPLE_8, "MULTISAMPLE_8", 0, "MultiSample: 8", "Use 8x OpenGL MultiSample (requires restart)"}, - {USER_MULTISAMPLE_16, "MULTISAMPLE_16", 0, "MultiSample: 16", "Use 16x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_NONE, "NONE", 0, "No MultiSample", "Do not use OpenGL MultiSample"}, + {USER_MULTISAMPLE_2, "2", 0, "MultiSample: 2", "Use 2x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_4, "4", 0, "MultiSample: 4", "Use 4x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_8, "8", 0, "MultiSample: 8", "Use 8x OpenGL MultiSample (requires restart)"}, + {USER_MULTISAMPLE_16, "16", 0, "MultiSample: 16", "Use 16x OpenGL MultiSample (requires restart)"}, {0, NULL, 0, NULL, NULL} }; @@ -3322,7 +3322,7 @@ static void rna_def_userdef_system(BlenderRNA *brna) RNA_def_property_update(prop, 0, "rna_userdef_text_update"); /* Full scene anti-aliasing */ - prop = RNA_def_property(srna, "ogl_multisamples", PROP_ENUM, PROP_NONE); + prop = RNA_def_property(srna, "multi_sample", PROP_ENUM, PROP_NONE); RNA_def_property_enum_bitflag_sdna(prop, NULL, "ogl_multisamples"); RNA_def_property_enum_items(prop, multi_sample_levels); RNA_def_property_ui_text(prop, "MultiSample", "Enable OpenGL multi-sampling, only for systems that support it, requires restart"); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 87d80402af6..631bd0c9002 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -345,7 +345,7 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win) (GHOST_TWindowState)win->windowstate, GHOST_kDrawingContextTypeOpenGL, 0 /* no stereo */, - U.ogl_multisamples /* AA */); + U.ogl_multisamples /* AA */); if (ghostwin) { /* needed so we can detect the graphics card below */ From 66b488acc3de8c2591fc92f16d445cdf131aaf14 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 11 Nov 2012 11:00:55 +0000 Subject: [PATCH 100/118] style cleanup --- source/blender/blenkernel/intern/cdderivedmesh.c | 9 ++++----- source/blender/blenkernel/intern/sequencer.c | 3 +-- source/blender/makesrna/intern/rna_nodetree.c | 2 +- source/blender/render/intern/source/external_engine.c | 4 ++-- 4 files changed, 8 insertions(+), 10 deletions(-) diff --git a/source/blender/blenkernel/intern/cdderivedmesh.c b/source/blender/blenkernel/intern/cdderivedmesh.c index c0e6bd54f53..3ade51d13eb 100644 --- a/source/blender/blenkernel/intern/cdderivedmesh.c +++ b/source/blender/blenkernel/intern/cdderivedmesh.c @@ -2304,9 +2304,9 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) } /* Don't remap vertices in cddm->mloop, because we need to know the original - indices in order to skip faces with all vertices merged. - The "update loop indices..." section further down remaps vertices in mloop. - */ + * indices in order to skip faces with all vertices merged. + * The "update loop indices..." section further down remaps vertices in mloop. + */ /* now go through and fix edges and faces */ med = cddm->medge; @@ -2351,8 +2351,7 @@ DerivedMesh *CDDM_merge_verts(DerivedMesh *dm, const int *vtargetmap) } } - if (UNLIKELY(all_vertices_merged)) - { + if (UNLIKELY(all_vertices_merged)) { continue; } } diff --git a/source/blender/blenkernel/intern/sequencer.c b/source/blender/blenkernel/intern/sequencer.c index a947a48938e..547ca96e10a 100644 --- a/source/blender/blenkernel/intern/sequencer.c +++ b/source/blender/blenkernel/intern/sequencer.c @@ -2384,8 +2384,7 @@ static ImBuf *seq_render_scene_strip(SeqRenderData context, Sequence *seq, float (void)oldmarkers; #endif - if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) - { + if ((sequencer_view3d_cb && do_seq_gl && camera) && is_thread_main) { char err_out[256] = "unknown"; /* for old scened this can be uninitialized, * should probably be added to do_versions at some point if the functionality stays */ diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 33a41ff6f6e..a68bcf62df8 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -1140,7 +1140,7 @@ static void rna_ShaderNodeScript_update(Main *bmain, Scene *scene, PointerRNA *p bNode *node = (bNode *)ptr->data; RenderEngineType *engine_type = RE_engines_find(scene->r.engine); - if(engine_type && engine_type->update_script_node) { + if (engine_type && engine_type->update_script_node) { /* auto update node */ RenderEngine *engine = RE_engine_create(engine_type); engine_type->update_script_node(engine, ntree, node); diff --git a/source/blender/render/intern/source/external_engine.c b/source/blender/render/intern/source/external_engine.c index d771cf2253d..8bdb805ada2 100644 --- a/source/blender/render/intern/source/external_engine.c +++ b/source/blender/render/intern/source/external_engine.c @@ -349,7 +349,7 @@ int RE_engine_render(Render *re, int do_all) re->i.totface = re->i.totvert = re->i.totstrand = re->i.totlamp = re->i.tothalo = 0; /* render */ - if(!re->engine) + if (!re->engine) re->engine = RE_engine_create(type); engine = re->engine; @@ -382,7 +382,7 @@ int RE_engine_render(Render *re, int do_all) if (type->render) type->render(engine, re->scene); - if(!(re->r.mode & R_PERSISTENT_DATA)) { + if (!(re->r.mode & R_PERSISTENT_DATA)) { RE_engine_free(re->engine); re->engine = NULL; } From 886dcf617e573862c45db8dc77316adcb6db0b05 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sun, 11 Nov 2012 12:02:39 +0000 Subject: [PATCH 101/118] MultiSample feature: added provision that requires a restart in order to get it work properly - you cannot set/disable it in a running program with windows open. In short: Multisample setting is static, set on first time running of Blender, after reading the user preferences. For as far as I can see - disabling/enableing (glEnable) doesn't harm to be used in drawing code. With multisample on at start, you can enable and disable it freely. But without it set at start, enabling doesn't do anything nor draws badly. --- source/blender/windowmanager/intern/wm_window.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 631bd0c9002..97052fd2fc6 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -333,8 +333,14 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win) static void wm_window_add_ghostwindow(const char *title, wmWindow *win) { GHOST_WindowHandle ghostwin; + static int multisamples = -1; int scr_w, scr_h, posy; + /* force setting multisamples only once, it requires restart - and you cannot + mix it, either all windows have it, or none (tested in OSX opengl) */ + if (multisamples == -1) + multisamples = U.ogl_multisamples; + wm_get_screensize(&scr_w, &scr_h); posy = (scr_h - win->posy - win->sizey); @@ -345,7 +351,7 @@ static void wm_window_add_ghostwindow(const char *title, wmWindow *win) (GHOST_TWindowState)win->windowstate, GHOST_kDrawingContextTypeOpenGL, 0 /* no stereo */, - U.ogl_multisamples /* AA */); + multisamples /* AA */); if (ghostwin) { /* needed so we can detect the graphics card below */ From 7d583e37bb8c9e96477f77f5981e55dbfad4b6aa Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sun, 11 Nov 2012 13:12:53 +0000 Subject: [PATCH 102/118] Bugfix, IRC report: NumPad emulation code wasn't working for double-clicks, preventing to fast type same values in buttons (Like, 111111 resulted in 111 only). Moved the emulation hack to where it belongs, in lowest level function that interprets the ghost events for Blender's WM events. --- .../windowmanager/intern/wm_event_system.c | 143 +++++++++--------- 1 file changed, 73 insertions(+), 70 deletions(-) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 14244de00f6..54e61df4f6a 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -1279,74 +1279,6 @@ int WM_userdef_event_map(int kmitype) return kmitype; } -static void wm_eventemulation(wmEvent *event) -{ - /* Store last mmb event value to make emulation work when modifier keys are released first. */ - static int mmb_emulated = 0; /* this should be in a data structure somwhere */ - - /* middlemouse emulation */ - if (U.flag & USER_TWOBUTTONMOUSE) { - if (event->type == LEFTMOUSE) { - - if (event->val == KM_PRESS && event->alt) { - event->type = MIDDLEMOUSE; - event->alt = 0; - mmb_emulated = 1; - } - else if (event->val == KM_RELEASE) { - /* only send middle-mouse release if emulated */ - if (mmb_emulated) { - event->type = MIDDLEMOUSE; - event->alt = 0; - } - mmb_emulated = 0; - } - } - - } - -#ifdef __APPLE__ - - /* rightmouse emulation */ - if (U.flag & USER_TWOBUTTONMOUSE) { - if (event->type == LEFTMOUSE) { - - if (event->val == KM_PRESS && event->oskey) { - event->type = RIGHTMOUSE; - event->oskey = 0; - mmb_emulated = 1; - } - else if (event->val == KM_RELEASE) { - if (mmb_emulated) { - event->oskey = RIGHTMOUSE; - event->alt = 0; - } - mmb_emulated = 0; - } - } - - } -#endif - - /* numpad emulation */ - if (U.flag & USER_NONUMPAD) { - switch (event->type) { - case ZEROKEY: event->type = PAD0; break; - case ONEKEY: event->type = PAD1; break; - case TWOKEY: event->type = PAD2; break; - case THREEKEY: event->type = PAD3; break; - case FOURKEY: event->type = PAD4; break; - case FIVEKEY: event->type = PAD5; break; - case SIXKEY: event->type = PAD6; break; - case SEVENKEY: event->type = PAD7; break; - case EIGHTKEY: event->type = PAD8; break; - case NINEKEY: event->type = PAD9; break; - case MINUSKEY: event->type = PADMINUS; break; - case EQUALKEY: event->type = PADPLUSKEY; break; - case BACKSLASHKEY: event->type = PADSLASHKEY; break; - } - } -} static int wm_eventmatch(wmEvent *winevent, wmKeyMapItem *kmi) { @@ -2113,8 +2045,6 @@ void wm_event_do_handlers(bContext *C) } #endif - wm_eventemulation(event); - CTX_wm_window_set(C, win); /* we let modal handlers get active area/region, also wm_paintcursor_test needs it */ @@ -2616,6 +2546,75 @@ static int convert_key(GHOST_TKey key) } } +static void wm_eventemulation(wmEvent *event) +{ + /* Store last mmb event value to make emulation work when modifier keys are released first. */ + static int mmb_emulated = 0; /* this should be in a data structure somwhere */ + + /* middlemouse emulation */ + if (U.flag & USER_TWOBUTTONMOUSE) { + if (event->type == LEFTMOUSE) { + + if (event->val == KM_PRESS && event->alt) { + event->type = MIDDLEMOUSE; + event->alt = 0; + mmb_emulated = 1; + } + else if (event->val == KM_RELEASE) { + /* only send middle-mouse release if emulated */ + if (mmb_emulated) { + event->type = MIDDLEMOUSE; + event->alt = 0; + } + mmb_emulated = 0; + } + } + + } + +#ifdef __APPLE__ + + /* rightmouse emulation */ + if (U.flag & USER_TWOBUTTONMOUSE) { + if (event->type == LEFTMOUSE) { + + if (event->val == KM_PRESS && event->oskey) { + event->type = RIGHTMOUSE; + event->oskey = 0; + mmb_emulated = 1; + } + else if (event->val == KM_RELEASE) { + if (mmb_emulated) { + event->oskey = RIGHTMOUSE; + event->alt = 0; + } + mmb_emulated = 0; + } + } + + } +#endif + + /* numpad emulation */ + if (U.flag & USER_NONUMPAD) { + switch (event->type) { + case ZEROKEY: event->type = PAD0; break; + case ONEKEY: event->type = PAD1; break; + case TWOKEY: event->type = PAD2; break; + case THREEKEY: event->type = PAD3; break; + case FOURKEY: event->type = PAD4; break; + case FIVEKEY: event->type = PAD5; break; + case SIXKEY: event->type = PAD6; break; + case SEVENKEY: event->type = PAD7; break; + case EIGHTKEY: event->type = PAD8; break; + case NINEKEY: event->type = PAD9; break; + case MINUSKEY: event->type = PADMINUS; break; + case EQUALKEY: event->type = PADPLUSKEY; break; + case BACKSLASHKEY: event->type = PADSLASHKEY; break; + } + } +} + /* adds customdata to event */ static void update_tablet_data(wmWindow *win, wmEvent *event) { @@ -2825,6 +2824,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U else event.type = MIDDLEMOUSE; + wm_eventemulation(&event); + /* copy previous state to prev event state (two old!) */ evt->prevval = evt->val; evt->prevtype = evt->type; @@ -2890,6 +2891,8 @@ void wm_event_add_ghostevent(wmWindowManager *wm, wmWindow *win, int type, int U memcpy(event.utf8_buf, kd->utf8_buf, sizeof(event.utf8_buf)); /* might be not null terminated*/ event.val = (type == GHOST_kEventKeyDown) ? KM_PRESS : KM_RELEASE; + wm_eventemulation(&event); + /* copy previous state to prev event state (two old!) */ evt->prevval = evt->val; evt->prevtype = evt->type; From 9b9636fdc356d6ef2782923e88a77b6dddf0dba0 Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sun, 11 Nov 2012 14:07:58 +0000 Subject: [PATCH 103/118] Bugfix [#33140] The alt+shift+RMB menu to select objects didn't handle 'extend' (now called toggle). Was due to code cleanup for selecting (and new CTRL+SHIFT+Select). Now the shift+alt menu behaves like shift+clicks. --- .../blender/editors/space_view3d/view3d_select.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/space_view3d/view3d_select.c b/source/blender/editors/space_view3d/view3d_select.c index 43626b058d6..53f983912ac 100644 --- a/source/blender/editors/space_view3d/view3d_select.c +++ b/source/blender/editors/space_view3d/view3d_select.c @@ -1064,11 +1064,11 @@ static EnumPropertyItem *object_select_menu_enum_itemf(bContext *C, PointerRNA * static int object_select_menu_exec(bContext *C, wmOperator *op) { int name_index = RNA_enum_get(op->ptr, "name"); - short extend = RNA_boolean_get(op->ptr, "extend"); + short toggle = RNA_boolean_get(op->ptr, "toggle"); short changed = 0; const char *name = object_mouse_select_menu_data[name_index].idname; - if (!extend) { + if (!toggle) { CTX_DATA_BEGIN (C, Base *, base, selectable_bases) { if (base->flag & SELECT) { @@ -1125,7 +1125,7 @@ void VIEW3D_OT_select_menu(wmOperatorType *ot) RNA_def_property_flag(prop, PROP_HIDDEN); ot->prop = prop; - RNA_def_boolean(ot->srna, "extend", 0, "Extend", "Extend selection instead of deselecting everything first"); + RNA_def_boolean(ot->srna, "toggle", 0, "Toggle", "Toggle selection instead of deselecting everything first"); } static void deselectall_except(Scene *scene, Base *b) /* deselect all except b */ @@ -1141,7 +1141,7 @@ static void deselectall_except(Scene *scene, Base *b) /* deselect all except b } } -static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], short extend) +static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int *buffer, int hits, const int mval[2], short toggle) { short baseCount = 0; short ok; @@ -1207,7 +1207,7 @@ static Base *object_mouse_select_menu(bContext *C, ViewContext *vc, unsigned int PointerRNA ptr; WM_operator_properties_create(&ptr, "VIEW3D_OT_select_menu"); - RNA_boolean_set(&ptr, "extend", extend); + RNA_boolean_set(&ptr, "toggle", toggle); WM_operator_name_call(C, "VIEW3D_OT_select_menu", WM_OP_INVOKE_DEFAULT, &ptr); WM_operator_properties_free(&ptr); } @@ -1440,7 +1440,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese /* note; shift+alt goes to group-flush-selecting */ if (enumerate) { - basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, extend); + basact = object_mouse_select_menu(C, &vc, NULL, 0, mval, toggle); } else { base = startbase; @@ -1480,7 +1480,7 @@ static int mouse_select(bContext *C, const int mval[2], short extend, short dese /* note; shift+alt goes to group-flush-selecting */ if (has_bones == 0 && enumerate) { - basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, extend); + basact = object_mouse_select_menu(C, &vc, buffer, hits, mval, toggle); } else { basact = mouse_select_eval_buffer(&vc, buffer, hits, mval, startbase, has_bones); From 56cee8165639356df0f87a5e31adafbec7a80ed5 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Sun, 11 Nov 2012 14:33:06 +0000 Subject: [PATCH 104/118] OSX/cmake: actualize message for xcode specifics --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb656614b00..593cd9871aa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -296,11 +296,11 @@ if(APPLE) if(${CMAKE_GENERATOR} MATCHES "Xcode") - ##### workaround for actual official cmake incompatibility with xcode 4.3 ##### + ##### cmake incompatibility with xcode 4.3 and higher ##### if(${XCODE_VERSION} MATCHES '') # cmake fails due looking for xcode in the wrong path, thus will be empty var - message("Official cmake does not yet support Xcode 4.3, get a patched version here: http://www.jensverwiebe.de/Blender/CMake%202.8-7patched.zip") + message(FATAL_ERROR "Xcode 4.3 and higher must be used with cmake 2.8-8 or higher") endif() - ### end workaround for actual official cmake incompatibility with xcode 4.3 ### + ### end cmake incompatibility with xcode 4.3 and higher ### if(${XCODE_VERSION} VERSION_EQUAL 4 OR ${XCODE_VERSION} VERSION_GREATER 4 AND ${XCODE_VERSION} VERSION_LESS 4.3) # Xcode 4 defaults to the Apple LLVM Compiler. From 35dff426e93f58fff59691f919b16836ab3340e1 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 11 Nov 2012 14:48:58 +0000 Subject: [PATCH 105/118] "Dynamic Sketch" patch, which adds timing data to GP strokes, by storing an inittime in each stroke (value returned by PIL_check_seconds_timer() func), and then a delta time for each of its points, relative to that inittime. These timing data can then be used during conversion to Curve objects, to create a path animation (i.e. an Evaluation Time F-Curve) exactly reproducing the drawing movements. Aside from this "main feature", the patch brings several fixes/enhancements: * Stroke smoothing/simplifying will no more move the start/end points of a stroke (this was rather annoying sometimes!). * Also optimized smoothing code (even though not really noticeable on a modern computer, it now uses less memory and runs faster). * When converting to curve, you now have the following new possibilities: ** Normalize the weight values (currently, they will get "stroke width * 0.1", i.e. would range by default from 0.0 to 0.3...). ** Scale the radius values to your liking (again, currently they are set from stroke width times 0.1)! ** Link all strokes into a single curve, using zero-radius sections (this is mandatory to use the dynamic feature!). Here is a small demo video: http://youtu.be/VwWEXrnQAFI Will update user manual later today. --- source/blender/editors/gpencil/gpencil_edit.c | 1049 ++++++++++++++++- .../blender/editors/gpencil/gpencil_paint.c | 240 ++-- source/blender/editors/include/ED_gpencil.h | 1 + source/blender/makesdna/DNA_gpencil_types.h | 2 + 4 files changed, 1150 insertions(+), 142 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index ed8a1ea8280..dda97abe5ec 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -40,8 +40,10 @@ #include "BLI_math.h" #include "BLI_blenlib.h" +#include "BLI_rand.h" #include "BLI_utildefines.h" +#include "DNA_anim_types.h" #include "DNA_curve_types.h" #include "DNA_object_types.h" #include "DNA_node_types.h" @@ -51,14 +53,20 @@ #include "DNA_view3d_types.h" #include "DNA_gpencil_types.h" +#include "BKE_animsys.h" #include "BKE_context.h" #include "BKE_curve.h" +#include "BKE_depsgraph.h" +#include "BKE_fcurve.h" +#include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_library.h" +#include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_tracking.h" +#include "UI_interface.h" #include "WM_api.h" #include "WM_types.h" @@ -71,6 +79,7 @@ #include "ED_gpencil.h" #include "ED_view3d.h" #include "ED_clip.h" +#include "ED_keyframing.h" #include "gpencil_intern.h" @@ -387,6 +396,14 @@ enum { GP_STROKECONVERT_CURVE, }; +/* Defines for possible timing modes */ +enum { + GP_STROKECONVERT_TIMING_NONE = 1, + GP_STROKECONVERT_TIMING_LINEAR = 2, + GP_STROKECONVERT_TIMING_FULL = 3, + GP_STROKECONVERT_TIMING_CUSTOMGAP = 4, +}; + /* RNA enum define */ static EnumPropertyItem prop_gpencil_convertmodes[] = { {GP_STROKECONVERT_PATH, "PATH", 0, "Path", ""}, @@ -394,6 +411,31 @@ static EnumPropertyItem prop_gpencil_convertmodes[] = { {0, NULL, 0, NULL, NULL} }; +static EnumPropertyItem prop_gpencil_convert_timingmodes_restricted[] = { + {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"}, + {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"}, + {0, NULL, 0, NULL, NULL}, +}; + +static EnumPropertyItem prop_gpencil_convert_timingmodes[] = { + {GP_STROKECONVERT_TIMING_NONE, "NONE", 0, "No Timing", "Ignore timing"}, + {GP_STROKECONVERT_TIMING_LINEAR, "LINEAR", 0, "Linear", "Simple linear timing"}, + {GP_STROKECONVERT_TIMING_FULL, "FULL", 0, "Original", "Use the original timing, gaps included"}, + {GP_STROKECONVERT_TIMING_CUSTOMGAP, "CUSTOMGAP", 0, "Custom Gaps", + "Use the original timing, but with custom gap lengths (in frames)"}, + {0, NULL, 0, NULL, NULL}, +}; + +static EnumPropertyItem *rna_GPConvert_mode_items(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), + int *free) +{ + *free = FALSE; + if (RNA_boolean_get(ptr, "use_timing_data")) { + return prop_gpencil_convert_timingmodes; + } + return prop_gpencil_convert_timingmodes_restricted; +} + /* --- */ /* convert the coordinates from the given stroke point into 3d-coordinates @@ -440,40 +482,485 @@ static void gp_strokepoint_convertcoords(bContext *C, bGPDstroke *gps, bGPDspoin /* --- */ -/* convert stroke to 3d path */ -static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect) +/* temp struct for gp_stroke_path_animation() */ +typedef struct tGpTimingData { + /* Data set from operator settings */ + int mode; + int frame_range; /* Number of frames evaluated for path animation */ + int start_frame, end_frame; + int realtime; /* A bool, actually, will overwrite end_frame in case of Original or CustomGap timing... */ + float gap_duration, gap_randomness; /* To be used with CustomGap mode*/ + int seed; + + /* Data set from points, used to compute final timing FCurve */ + int num_points, cur_point; + + /* Distances */ + float *dists; + float tot_dist; + + /* Times */ + float *times; /* Note: Gap times will be negative! */ + float tot_time, gap_tot_time; + double inittime; +} tGpTimingData; + +static void _gp_timing_data_set_nbr(tGpTimingData *gtd, int nbr) { - bGPDspoint *pt; - Nurb *nu; - BPoint *bp; + float *tmp; + + BLI_assert(nbr > gtd->num_points); + + tmp = gtd->dists; + gtd->dists = MEM_callocN(sizeof(float) * nbr, __func__); + if (tmp) { + memcpy(gtd->dists, tmp, sizeof(float) * gtd->num_points); + MEM_freeN(tmp); + } + + tmp = gtd->times; + gtd->times = MEM_callocN(sizeof(float) * nbr, __func__); + if (tmp) { + memcpy(gtd->times, tmp, sizeof(float) * gtd->num_points); + MEM_freeN(tmp); + } + + gtd->num_points = nbr; +} + +static void gp_timing_data_add_point(tGpTimingData *gtd, double stroke_inittime, float time, float delta_dist) +{ + if (time < 0.0f) { + /* This is a gap, negative value! */ + gtd->tot_time = -(gtd->times[gtd->cur_point] = -(((float)(stroke_inittime - gtd->inittime)) + time)); + gtd->gap_tot_time += gtd->times[gtd->cur_point] - gtd->times[gtd->cur_point - 1]; + } + else + gtd->tot_time = (gtd->times[gtd->cur_point] = (((float)(stroke_inittime - gtd->inittime)) + time)); + gtd->dists[gtd->cur_point] = (gtd->tot_dist += delta_dist); + gtd->cur_point++; +} + +/* In frames! Binary search for FCurve keys have a threshold of 0.01, so we can’t set + * arbitrarily close points - this is esp. important with NoGaps mode! + */ +#define MIN_TIME_DELTA 0.02f + +/* Loop over next points to find the end of the stroke, and compute */ +static int gp_find_end_of_stroke_idx(tGpTimingData *gtd, int idx, int nbr_gaps, int *nbr_done_gaps, + float tot_gaps_time, float delta_time, float *next_delta_time) +{ + int j; + + for (j = idx + 1; j < gtd->num_points; j++) { + if (gtd->times[j] < 0) { + gtd->times[j] = -gtd->times[j]; + if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + /* In this mode, gap time between this stroke and the next should be 0 currently... + * So we have to compute its final duration! + */ + if (gtd->gap_randomness > 0.0f) { + /* We want gaps that are in gtd->gap_duration +/- gtd->gap_randomness range, + * and which sum to exactly tot_gaps_time... + */ + int rem_gaps = nbr_gaps - *nbr_done_gaps; + if (rem_gaps < 2) { + /* Last gap, just give remaining time! */ + *next_delta_time = tot_gaps_time; + } + else { + float delta, min, max; + /* This code ensures that if the first gaps have been shorter than average gap_duration, + * next gaps will tend to be longer (i.e. try to recover the lateness), and vice-versa! + */ + delta = delta_time - (gtd->gap_duration * *nbr_done_gaps); + /* Clamp min between [-gap_randomness, 0.0], with lower delta giving higher min */ + min = -gtd->gap_randomness - delta; + CLAMP(min, -gtd->gap_randomness, 0.0f); + /* Clamp max between [0.0, gap_randomness], with lower delta giving higher max */ + max = gtd->gap_randomness - delta; + CLAMP(max, 0.0f, gtd->gap_randomness); + *next_delta_time += gtd->gap_duration + (BLI_frand() * (max - min)) + min; + } + } + else { + *next_delta_time += gtd->gap_duration; + } + } + (*nbr_done_gaps)++; + break; + } + } + + return j - 1; +} + +static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, int *nbr_gaps, float *tot_gaps_time) +{ + int i; + float delta_time = 0.0f; + + for (i = 0; i < gtd->num_points; i++) { + if (gtd->times[i] < 0 && i) { + (*nbr_gaps)++; + gtd->times[i] = -gtd->times[i] - delta_time; + delta_time += gtd->times[i] - gtd->times[i - 1]; + gtd->times[i] = -gtd->times[i - 1]; /* Temp marker, values *have* to be different! */ + } + else { + gtd->times[i] -= delta_time; + } + } + gtd->tot_time -= delta_time; + + *tot_gaps_time = (float)(*nbr_gaps) * gtd->gap_duration; + gtd->tot_time += *tot_gaps_time; + if (G.debug & G_DEBUG) { + printf("%f, %f, %f, %d\n", gtd->tot_time, delta_time, *tot_gaps_time, *nbr_gaps); + } + if (gtd->gap_randomness > 0.0f) { + BLI_srandom(gtd->seed); + } +} + +static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, + Curve *cu, tGpTimingData *gtd, float cfra, float time_range, + int nbr_gaps, float tot_gaps_time) +{ + /* Use actual recorded timing! */ + float time_start = (float)gtd->start_frame; + + float last_valid_time = 0.0f; + int end_stroke_idx = -1, start_stroke_idx = 0; + float end_stroke_time = 0.0f; + + /* CustomGaps specific */ + float delta_time = 0.0f, next_delta_time = 0.0f; + int nbr_done_gaps = 0; + int i; - /* create new 'nurb' within the curve */ - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); - - nu->pntsu = gps->totpoints; - nu->pntsv = 1; - nu->orderu = gps->totpoints; - nu->flagu = CU_NURB_ENDPOINT; - nu->resolu = 32; - - nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * gps->totpoints, "bpoints"); - - /* add points */ - for (i = 0, pt = gps->points, bp = nu->bp; i < gps->totpoints; i++, pt++, bp++) { - float p3d[3]; + /* This is a bit tricky, as: + * - We can't add arbitrarily close points on FCurve (in time). + * - We *must* have all "caps" points of all strokes in FCurve, as much as possible! + */ + for (i = 0; i < gtd->num_points; i++) { + /* If new stroke... */ + if (i > end_stroke_idx) { + start_stroke_idx = i; + delta_time = next_delta_time; + /* find end of that new stroke */ + end_stroke_idx = gp_find_end_of_stroke_idx(gtd, i, nbr_gaps, &nbr_done_gaps, + tot_gaps_time, delta_time, &next_delta_time); + /* This one should *never* be negative! */ + end_stroke_time = time_start + ((gtd->times[end_stroke_idx] + delta_time) / gtd->tot_time * time_range); + } + + /* Simple proportional stuff... */ + cu->ctime = gtd->dists[i] / gtd->tot_dist * cu->pathlen; + cfra = time_start + ((gtd->times[i] + delta_time) / gtd->tot_time * time_range); + + /* And now, the checks about timing... */ + if (i == start_stroke_idx) { + /* If first point of a stroke, be sure it's enough ahead of last valid keyframe, and + * that the end point of the stroke is far enough! + * In case it is not, we keep the end point... + * Note that with CustomGaps mode, this is here we set the actual gap timing! + */ + if ((end_stroke_time - last_valid_time) > MIN_TIME_DELTA * 2) { + if ((cfra - last_valid_time) < MIN_TIME_DELTA) { + cfra = last_valid_time + MIN_TIME_DELTA; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else if (G.debug & G_DEBUG) { + printf("\t Skipping start point %d, too close from end point %d\n", i, end_stroke_idx); + } + } + else if (i == end_stroke_idx) { + /* Always try to insert end point of a curve (should be safe enough, anyway...) */ + if ((cfra - last_valid_time) < MIN_TIME_DELTA) { + cfra = last_valid_time + MIN_TIME_DELTA; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else { + /* Else ("middle" point), we only insert it if it's far enough from last keyframe, + * and also far enough from (not yet added!) end_stroke keyframe! + */ + if ((cfra - last_valid_time) > MIN_TIME_DELTA && (end_stroke_time - cfra) > MIN_TIME_DELTA) { + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + last_valid_time = cfra; + } + else if (G.debug & G_DEBUG) { + printf("\t Skipping \"middle\" point %d, too close from last added point or end point %d\n", + i, end_stroke_idx); + } + } + } +} + +static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu, tGpTimingData *gtd) +{ + Scene *scene = CTX_data_scene(C); + bAction *act; + FCurve *fcu; + PointerRNA ptr; + PropertyRNA *prop = NULL; + + float cfra; + int nbr_gaps = 0, i; + + if (gtd->mode == GP_STROKECONVERT_TIMING_NONE) + return; + + /* gap_duration and gap_randomness are in frames, but we need seconds!!! */ + gtd->gap_duration = FRA2TIME(gtd->gap_duration); + gtd->gap_randomness = FRA2TIME(gtd->gap_randomness); + + /* Enable path! */ + cu->flag |= CU_PATH; + cu->pathlen = gtd->frame_range; + + /* Get or create default action to add F-Curve+keyframe to */ + act = verify_adt_action((ID*)cu, TRUE); + /* Create RNA stuff */ + RNA_id_pointer_create((ID*)cu, &ptr); + prop = RNA_struct_find_property(&ptr, "eval_time"); + /* Get or create fcurve */ + fcu = verify_fcurve(act, NULL, &ptr, "eval_time", 0, TRUE); + + if (G.debug & G_DEBUG) { + printf("%s: tot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); + for (i = 0; i < gtd->num_points; i++) { + printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); + } + } + + if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) { + /* Linear extrapolation! */ + fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; + + cu->ctime = 0.0f; + cfra = (float)gtd->start_frame; + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + + cu->ctime = cu->pathlen; + if (gtd->realtime) { + cfra += (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ + } + else { + cfra = (float)gtd->end_frame; + } + insert_keyframe_direct(reports, ptr, prop, fcu, cfra, INSERTKEY_FAST); + } + else { + /* Use actual recorded timing! */ + float time_range; + + /* CustomGaps specific */ + float tot_gaps_time = 0.0f; + + /* Pre-process gaps, in case we don't want to keep their org timing */ + if (gtd->mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + gp_stroke_path_animation_preprocess_gaps(gtd, &nbr_gaps, &tot_gaps_time); + } + + if (gtd->realtime) { + time_range = (float)TIME2FRA(gtd->tot_time); /* Seconds to frames */ + } + else { + time_range = (float)(gtd->end_frame - gtd->start_frame); + } + + if (G.debug & G_DEBUG) { + printf("Starting keying!\n"); + } + + gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, cfra, time_range, + nbr_gaps, tot_gaps_time); + + } + + /* As we used INSERTKEY_FAST mode, we need to recompute all curve's handles now */ + calchandles_fcurve(fcu); + + if (G.debug & G_DEBUG) { + printf("%s: \ntot len: %f\t\ttot time: %f\n", __func__, gtd->tot_dist, gtd->tot_time); + for (i = 0; i < gtd->num_points; i++) { + printf("\tpoint %d:\t\tlen: %f\t\ttime: %f\n", i, gtd->dists[i], gtd->times[i]); + } + printf("\n\n"); + } + + WM_event_add_notifier(C, NC_ANIMATION | ND_KEYFRAME | NA_EDITED, NULL); + + /* send updates */ + DAG_id_tag_update((ID*)cu, 0); +} + +#undef MIN_TIME_DELTA + +#define GAP_DFAC 0.05f +#define WIDTH_CORR_FAC 0.1f +#define BEZT_HANDLE_FAC 0.3f + +/* convert stroke to 3d path */ +static void gp_stroke_to_path(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, + float minmax_weights[2], float rad_fac, int stitch, tGpTimingData *gtd) +{ + bGPDspoint *pt; + Nurb *nu = curnu ? *curnu : NULL; + BPoint *bp, *prev_bp = NULL; + int i, old_nbp = 0; + const int do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); + + /* create new 'nurb' or extend current one within the curve */ + if (nu) { + old_nbp = nu->pntsu; + /* If stitch, the first point of this stroke is already present in current nu. + * Else, we have to add to additional points to make the zero-radius link between strokes. + */ + BKE_nurb_points_add(nu, gps->totpoints + (stitch ? -1 : 2)); + } + else { + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_path(nurb)"); + nu->pntsu = gps->totpoints; + nu->pntsv = 1; + nu->orderu = 2; /* point-to-point! */ + nu->type = CU_NURBS; + nu->flagu = CU_NURB_ENDPOINT; + nu->resolu = cu->resolu; + nu->resolv = cu->resolv; + nu->knotsu = NULL; + + nu->bp = (BPoint *)MEM_callocN(sizeof(BPoint) * nu->pntsu, "bpoints"); + + stitch = FALSE; /* Security! */ + } + + if (do_gtd) { + _gp_timing_data_set_nbr(gtd, nu->pntsu); + } + + /* If needed, make the link between both strokes with two zero-radius additional points */ + /* About "zero-radius" point interpolations: + * - If we have at least two points in current curve (most common case), we linearly extrapolate + * the last segment to get the first point (p1) position and timing. + * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point + * with the first point of the current stroke. + * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated + * if it exists, else (if the stroke is a single point), linear interpolation with last curve point... + */ + if (curnu && !stitch && old_nbp) { + float p1[3], p2[3], p[3], next_p[3]; + float delta_time; + + prev_bp = NULL; + if (old_nbp > 1 && gps->prev && gps->prev->totpoints > 1) { + /* Only use last curve segment if previous stroke was not a single-point one! */ + prev_bp = nu->bp + old_nbp - 2; + } + bp = nu->bp + old_nbp - 1; + /* XXX We do this twice... Not sure it's worth to bother about this! */ + gp_strokepoint_convertcoords(C, gps, gps->points, p, subrect); + if (prev_bp) { + interp_v3_v3v3(p1, prev_bp->vec, bp->vec, 1.0f + GAP_DFAC); + } + else { + interp_v3_v3v3(p1, bp->vec, p, GAP_DFAC); + } + if (gps->totpoints > 1) { + /* XXX We do this twice... Not sure it's worth to bother about this! */ + gp_strokepoint_convertcoords(C, gps, gps->points + 1, next_p, subrect); + interp_v3_v3v3(p2, p, next_p, -GAP_DFAC); + } + else { + interp_v3_v3v3(p2, p, bp->vec, GAP_DFAC); + } + + /* First point */ + bp++; + copy_v3_v3(bp->vec, p1); + bp->vec[3] = 1.0f; + bp->f1 = SELECT; + minmax_weights[0] = bp->radius = bp->weight = 0.0f; + if (do_gtd) { + if (prev_bp) { + delta_time = gtd->tot_time + (gtd->tot_time - gtd->times[gtd->cur_point - 1]) * GAP_DFAC; + } + else { + delta_time = gtd->tot_time + (((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gtd->inittime, delta_time, len_v3v3((bp - 1)->vec, p1)); + } + + /* Second point */ + bp++; + copy_v3_v3(bp->vec, p2); + bp->vec[3] = 1.0f; + bp->f1 = SELECT; + minmax_weights[0] = bp->radius = bp->weight = 0.0f; + if (do_gtd) { + /* This negative delta_time marks the gap! */ + if (gps->totpoints > 1) { + delta_time = ((gps->points + 1)->time - gps->points->time) * -GAP_DFAC; + } + else { + delta_time = -(((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gps->inittime, delta_time, len_v3v3(p1, p2)); + } + + old_nbp += 2; + } + if (old_nbp && do_gtd) { + prev_bp = nu->bp + old_nbp - 1; + } + /* add points */ + for (i = stitch ? 1 : 0, pt = gps->points + (stitch ? 1 : 0), bp = nu->bp + old_nbp; + i < gps->totpoints; + i++, pt++, bp++) + { + float p3d[3]; + float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC; + /* get coordinates to add at */ gp_strokepoint_convertcoords(C, gps, pt, p3d, subrect); copy_v3_v3(bp->vec, p3d); - + bp->vec[3] = 1.0f; + /* set settings */ bp->f1 = SELECT; - bp->radius = bp->weight = pt->pressure * gpl->thickness; + bp->radius = width * rad_fac; + bp->weight = width; + CLAMP(bp->weight, 0.0f, 1.0f); + if (bp->weight < minmax_weights[0]) { + minmax_weights[0] = bp->weight; + } + else if (bp->weight > minmax_weights[1]) { + minmax_weights[1] = bp->weight; + } + + /* Update timing data */ + if (do_gtd) { + gp_timing_data_add_point(gtd, gps->inittime, pt->time, prev_bp ? len_v3v3(prev_bp->vec, p3d) : 0.0f); + } + prev_bp = bp; } - + /* add nurb to curve */ - BLI_addtail(&cu->nurb, nu); + if (!curnu || !*curnu) { + BLI_addtail(&cu->nurb, nu); + } + if (curnu) { + *curnu = nu; + } + + BKE_nurb_knot_calc_u(nu); } static int gp_camera_view_subrect(bContext *C, rctf *subrect) @@ -496,77 +983,288 @@ static int gp_camera_view_subrect(bContext *C, rctf *subrect) } /* convert stroke to 3d bezier */ -static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect) +static void gp_stroke_to_bezier(bContext *C, bGPDlayer *gpl, bGPDstroke *gps, Curve *cu, rctf *subrect, Nurb **curnu, + float minmax_weights[2], float rad_fac, int stitch, tGpTimingData *gtd) { bGPDspoint *pt; - Nurb *nu; - BezTriple *bezt; - int i, tot; + Nurb *nu = curnu ? *curnu : NULL; + BezTriple *bezt, *prev_bezt = NULL; + int i, tot, old_nbezt = 0; float p3d_cur[3], p3d_prev[3], p3d_next[3]; + const int do_gtd = (gtd->mode != GP_STROKECONVERT_TIMING_NONE); - /* create new 'nurb' within the curve */ - nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); + /* create new 'nurb' or extend current one within the curve */ + if (nu) { + old_nbezt = nu->pntsu; + /* If we do stitch, first point of current stroke is assumed the same as last point of previous stroke, + * so no need to add it. + * If no stitch, we want to add two additional points to make a "zero-radius" link between both strokes. + */ + BKE_nurb_bezierPoints_add(nu, gps->totpoints + (stitch ? -1 : 2)); + } + else { + nu = (Nurb *)MEM_callocN(sizeof(Nurb), "gpstroke_to_bezier(nurb)"); - nu->pntsu = gps->totpoints; - nu->resolu = 12; - nu->resolv = 12; - nu->type = CU_BEZIER; - nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints * sizeof(BezTriple), "bezts"); + nu->pntsu = gps->totpoints; + nu->resolu = 12; + nu->resolv = 12; + nu->type = CU_BEZIER; + nu->bezt = (BezTriple *)MEM_callocN(gps->totpoints * sizeof(BezTriple), "bezts"); + + stitch = FALSE; /* Security! */ + } + + if (do_gtd) { + _gp_timing_data_set_nbr(gtd, nu->pntsu); + } tot = gps->totpoints; /* get initial coordinates */ pt = gps->points; if (tot) { - gp_strokepoint_convertcoords(C, gps, pt, p3d_cur, subrect); + gp_strokepoint_convertcoords(C, gps, pt, stitch ? p3d_prev : p3d_cur, subrect); if (tot > 1) { - gp_strokepoint_convertcoords(C, gps, pt + 1, p3d_next, subrect); + gp_strokepoint_convertcoords(C, gps, pt + 1, stitch ? p3d_cur : p3d_next, subrect); + } + if (stitch && tot > 2) { + gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect); } } + /* If needed, make the link between both strokes with two zero-radius additional points */ + if (curnu && old_nbezt) { + /* Update last point's second handle! */ + if (stitch) { + float h2[3]; + bezt = nu->bezt + old_nbezt - 1; + interp_v3_v3v3(h2, bezt->vec[1], p3d_cur, BEZT_HANDLE_FAC); + copy_v3_v3(bezt->vec[2], h2); + pt++; + } + /* Create "link points" */ + /* About "zero-radius" point interpolations: + * - If we have at least two points in current curve (most common case), we linearly extrapolate + * the last segment to get the first point (p1) position and timing. + * - If we do not have those (quite odd, but may happen), we linearly interpolate the last point + * with the first point of the current stroke. + * The same goes for the second point, first segment of the current stroke is "negatively" extrapolated + * if it exists, else (if the stroke is a single point), linear interpolation with last curve point... + */ + else { + float h1[3], h2[3], p1[3], p2[3]; + float delta_time; + + prev_bezt = NULL; + if (old_nbezt > 1 && gps->prev && gps->prev->totpoints > 1) { + /* Only use last curve segment if previous stroke was not a single-point one! */ + prev_bezt = nu->bezt + old_nbezt - 2; + } + bezt = nu->bezt + old_nbezt - 1; + if (prev_bezt) { + interp_v3_v3v3(p1, prev_bezt->vec[1], bezt->vec[1], 1.0f + GAP_DFAC); + } + else { + interp_v3_v3v3(p1, bezt->vec[1], p3d_cur, GAP_DFAC); + } + if (tot > 1) { + interp_v3_v3v3(p2, p3d_cur, p3d_next, -GAP_DFAC); + } + else { + interp_v3_v3v3(p2, p3d_cur, bezt->vec[1], GAP_DFAC); + } + + /* Second handle of last point */ + interp_v3_v3v3(h2, bezt->vec[1], p1, BEZT_HANDLE_FAC); + copy_v3_v3(bezt->vec[2], h2); + + /* First point */ + interp_v3_v3v3(h1, p1, bezt->vec[1], BEZT_HANDLE_FAC); + interp_v3_v3v3(h2, p1, p2, BEZT_HANDLE_FAC); + + bezt++; + copy_v3_v3(bezt->vec[0], h1); + copy_v3_v3(bezt->vec[1], p1); + copy_v3_v3(bezt->vec[2], h2); + bezt->h1 = bezt->h2 = HD_FREE; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + minmax_weights[0] = bezt->radius = bezt->weight = 0.0f; + + if (do_gtd) { + if (prev_bezt) { + delta_time = gtd->tot_time + (gtd->tot_time - gtd->times[gtd->cur_point - 1]) * GAP_DFAC; + } + else { + delta_time = gtd->tot_time + (((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gtd->inittime, delta_time, len_v3v3((bezt - 1)->vec[1], p1)); + } + + /* Second point */ + interp_v3_v3v3(h1, p2, p1, BEZT_HANDLE_FAC); + interp_v3_v3v3(h2, p2, p3d_cur, BEZT_HANDLE_FAC); + + bezt++; + copy_v3_v3(bezt->vec[0], h1); + copy_v3_v3(bezt->vec[1], p2); + copy_v3_v3(bezt->vec[2], h2); + bezt->h1 = bezt->h2 = HD_FREE; + bezt->f1 = bezt->f2 = bezt->f3 = SELECT; + minmax_weights[0] = bezt->radius = bezt->weight = 0.0f; + + if (do_gtd) { + /* This negative delta_time marks the gap! */ + if (tot > 1) { + delta_time = ((gps->points + 1)->time - gps->points->time) * -GAP_DFAC; + } + else { + delta_time = -(((float)(gps->inittime - gtd->inittime)) - gtd->tot_time) * GAP_DFAC; + } + gp_timing_data_add_point(gtd, gps->inittime, delta_time, len_v3v3(p1, p2)); + } + + old_nbezt += 2; + copy_v3_v3(p3d_prev, p2); + } + } + if (old_nbezt && do_gtd) { + prev_bezt = nu->bezt + old_nbezt - 1; + } /* add points */ - for (i = 0, bezt = nu->bezt; i < tot; i++, pt++, bezt++) { + for (i = stitch ? 1 : 0, bezt = nu->bezt + old_nbezt; i < tot; i++, pt++, bezt++) { float h1[3], h2[3]; - - if (i) interp_v3_v3v3(h1, p3d_cur, p3d_prev, 0.3); - else interp_v3_v3v3(h1, p3d_cur, p3d_next, -0.3); - - if (i < tot - 1) interp_v3_v3v3(h2, p3d_cur, p3d_next, 0.3); - else interp_v3_v3v3(h2, p3d_cur, p3d_prev, -0.3); - + float width = pt->pressure * gpl->thickness * WIDTH_CORR_FAC; + + if (i || old_nbezt) { + interp_v3_v3v3(h1, p3d_cur, p3d_prev, BEZT_HANDLE_FAC); + } + else { + interp_v3_v3v3(h1, p3d_cur, p3d_next, -BEZT_HANDLE_FAC); + } + + if (i < tot - 1) { + interp_v3_v3v3(h2, p3d_cur, p3d_next, BEZT_HANDLE_FAC); + } + else { + interp_v3_v3v3(h2, p3d_cur, p3d_prev, -BEZT_HANDLE_FAC); + } + copy_v3_v3(bezt->vec[0], h1); copy_v3_v3(bezt->vec[1], p3d_cur); copy_v3_v3(bezt->vec[2], h2); - + /* set settings */ bezt->h1 = bezt->h2 = HD_FREE; bezt->f1 = bezt->f2 = bezt->f3 = SELECT; - bezt->radius = bezt->weight = pt->pressure * gpl->thickness * 0.1f; - + bezt->radius = width * rad_fac; + bezt->weight = width; + CLAMP(bezt->weight, 0.0f, 1.0f); + if (bezt->weight < minmax_weights[0]) { + minmax_weights[0] = bezt->weight; + } + else if (bezt->weight > minmax_weights[1]) { + minmax_weights[1] = bezt->weight; + } + + /* Update timing data */ + if (do_gtd) { + gp_timing_data_add_point(gtd, gps->inittime, pt->time, prev_bezt ? len_v3v3(prev_bezt->vec[1], p3d_cur) : 0.0f); + } + /* shift coord vects */ copy_v3_v3(p3d_prev, p3d_cur); copy_v3_v3(p3d_cur, p3d_next); - + if (i + 2 < tot) { gp_strokepoint_convertcoords(C, gps, pt + 2, p3d_next, subrect); } + + prev_bezt = bezt; } /* must calculate handles or else we crash */ BKE_nurb_handles_calc(nu); - /* add nurb to curve */ - BLI_addtail(&cu->nurb, nu); + if (!curnu || !*curnu) { + BLI_addtail(&cu->nurb, nu); + } + if (curnu) { + *curnu = nu; + } +} + +#undef GAP_DFAC +#undef WIDTH_CORR_FAC +#undef BEZT_HANDLE_FAC + +static void gp_stroke_finalize_curve_endpoints(Curve *cu) +{ + Nurb *nu = cu->nurb.first; + int i = 0; + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + if (bezt) { + bezt[i].weight = bezt[i].radius = 0.0f; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + if (bp) { + bp[i].weight = bp[i].radius = 0.0f; + } + } + + nu = cu->nurb.last; + i = nu->pntsu - 1; + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + if (bezt) { + bezt[i].weight = bezt[i].radius = 0.0f; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + if (bp) { + bp[i].weight = bp[i].radius = 0.0f; + } + } +} + +static void gp_stroke_norm_curve_weights(Curve *cu, float minmax_weights[2]) +{ + Nurb *nu; + const float delta = minmax_weights[0]; + const float fac = 1.0f / (minmax_weights[1] - delta); + int i; + + for (nu = cu->nurb.first; nu; nu = nu->next) { + if (nu->bezt) { + BezTriple *bezt = nu->bezt; + for (i = 0; i < nu->pntsu; i++, bezt++) { + bezt->weight = (bezt->weight - delta) * fac; + } + } + else if (nu->bp) { + BPoint *bp = nu->bp; + for (i = 0; i < nu->pntsu; i++, bp++) { + bp->weight = (bp->weight - delta) * fac; + } + } + } } /* convert a given grease-pencil layer to a 3d-curve representation (using current view if appropriate) */ -static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short mode) +static void gp_layer_to_curve(bContext *C, ReportList *reports, bGPdata *gpd, bGPDlayer *gpl, int mode, + int norm_weights, float rad_fac, int link_strokes, tGpTimingData *gtd) { Scene *scene = CTX_data_scene(C); bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); - bGPDstroke *gps; + bGPDstroke *gps, *prev_gps = NULL; Object *ob; Curve *cu; + Nurb *nu = NULL; + Base *base = BASACT, *newbase = NULL; + float minmax_weights[2] = {1.0f, 0.0f}; /* camera framing */ rctf subrect, *subrect_ptr = NULL; @@ -574,7 +1272,7 @@ static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short m /* error checking */ if (ELEM3(NULL, gpd, gpl, gpf)) return; - + /* only convert if there are any strokes on this layer's frame to convert */ if (gpf->strokes.first == NULL) return; @@ -592,29 +1290,116 @@ static void gp_layer_to_curve(bContext *C, bGPdata *gpd, bGPDlayer *gpl, short m zero_v3(ob->rot); cu = ob->data; cu->flag |= CU_3D; - + /* rename object and curve to layer name */ rename_id((ID *)ob, gpl->info); rename_id((ID *)cu, gpl->info); - + + gtd->inittime = ((bGPDstroke*)gpf->strokes.first)->inittime; + /* add points to curve */ for (gps = gpf->strokes.first; gps; gps = gps->next) { + /* Detect new strokes created because of GP_STROKE_BUFFER_MAX reached, + * and stitch them to previous one. + */ + int stitch = FALSE; + if (prev_gps) { + bGPDspoint *pt1 = prev_gps->points + prev_gps->totpoints - 1; + bGPDspoint *pt2 = gps->points; + if (pt1->x == pt2->x && pt1->y == pt2->y) + stitch = TRUE; + } + /* Decide whether we connect this stroke to previous one */ + if (!(stitch || link_strokes)) + nu = NULL; switch (mode) { case GP_STROKECONVERT_PATH: - gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr); + gp_stroke_to_path(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, gtd); break; case GP_STROKECONVERT_CURVE: - gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr); + gp_stroke_to_bezier(C, gpl, gps, cu, subrect_ptr, &nu, minmax_weights, rad_fac, stitch, gtd); break; default: BLI_assert(!"invalid mode"); break; } + prev_gps = gps; } + + /* If link_strokes, be sure first and last points have a zero weight/size! */ + if (link_strokes) + gp_stroke_finalize_curve_endpoints(cu); + + /* Update curve's weights, if needed */ + if (norm_weights && (minmax_weights[0] > 0.0f || minmax_weights[1] < 1.0f)) + gp_stroke_norm_curve_weights(cu, minmax_weights); + + /* Create the path animation, if needed */ + gp_stroke_path_animation(C, reports, cu, gtd); + + /* Reset org object as active, else we can't edit operator's settings!!! */ + /* set layers OK */ + newbase = BASACT; + newbase->lay = base->lay; + ob->lay = newbase->lay; + /* restore, BKE_object_add sets active */ + BASACT = base; + base->flag |= SELECT; } /* --- */ +/* Check a GP layer has valid timing data! Else, most timing options are hidden in the operator. + * op may be NULL. + */ +static int gp_convert_check_has_valid_timing(bContext *C, bGPDlayer *gpl, wmOperator *op) +{ + Scene *scene = CTX_data_scene(C); + bGPDframe *gpf = gpencil_layer_getframe(gpl, CFRA, 0); + bGPDstroke *gps = gpf->strokes.first; + bGPDspoint *pt; + double base_time, cur_time, prev_time = -1.0; + int i, valid = TRUE; + + do { + base_time = cur_time = gps->inittime; + if (cur_time <= prev_time) { + valid = FALSE; + break; + } + prev_time = cur_time; + for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) { + cur_time = base_time + (double)pt->time; + /* First point of a stroke should have the same time as stroke's inittime, + * so it's the only case where equality is allowed! + */ + if ((i && cur_time <= prev_time) || (cur_time < prev_time)) { + valid = FALSE; + break; + } + prev_time = cur_time; + } + if (!valid) { + break; + } + } while ((gps = gps->next)); + + if (op) { + RNA_boolean_set(op->ptr, "use_timing_data", valid); + } + return valid; +} + +/* Check end_frame is always > start frame! */ +static void gp_convert_set_end_frame(struct Main *UNUSED(main), struct Scene *UNUSED(scene), struct PointerRNA *ptr) +{ + int start_frame = RNA_int_get(ptr, "start_frame"); + int end_frame = RNA_int_get(ptr, "end_frame"); + if (end_frame <= start_frame) { + RNA_int_set(ptr, "end_frame", start_frame + 1); + } +} + static int gp_convert_poll(bContext *C) { bGPdata *gpd = gpencil_data_get_active(C); @@ -627,10 +1412,16 @@ static int gp_convert_poll(bContext *C) static int gp_convert_layer_exec(bContext *C, wmOperator *op) { + PropertyRNA *prop = RNA_struct_find_property(op->ptr, "use_timing_data"); bGPdata *gpd = gpencil_data_get_active(C); bGPDlayer *gpl = gpencil_layer_getactive(gpd); Scene *scene = CTX_data_scene(C); int mode = RNA_enum_get(op->ptr, "type"); + int norm_weights = RNA_boolean_get(op->ptr, "use_normalize_weights"); + float rad_fac = RNA_float_get(op->ptr, "radius_multiplier"); + int link_strokes = RNA_boolean_get(op->ptr, "use_link_strokes"); + int valid_timing; + tGpTimingData gtd; /* check if there's data to work with */ if (gpd == NULL) { @@ -638,7 +1429,36 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } - gp_layer_to_curve(C, gpd, gpl, mode); + if (!RNA_property_is_set(op->ptr, prop) && !gp_convert_check_has_valid_timing(C, gpl, op)) { + BKE_report(op->reports, RPT_WARNING, + "Current grease pencil strokes have no valid timing data, most timing options will be hidden!"); + } + valid_timing = RNA_property_boolean_get(op->ptr, prop); + + gtd.mode = RNA_enum_get(op->ptr, "timing_mode"); + /* Check for illegal timing mode! */ + if (!valid_timing && !ELEM(gtd.mode, GP_STROKECONVERT_TIMING_NONE, GP_STROKECONVERT_TIMING_LINEAR)) { + gtd.mode = GP_STROKECONVERT_TIMING_LINEAR; + RNA_enum_set(op->ptr, "timing_mode", gtd.mode); + } + if (!link_strokes) { + gtd.mode = GP_STROKECONVERT_TIMING_NONE; + } + + gtd.frame_range = RNA_int_get(op->ptr, "frame_range"); + gtd.start_frame = RNA_int_get(op->ptr, "start_frame"); + gtd.realtime = valid_timing ? RNA_boolean_get(op->ptr, "use_realtime") : FALSE; + gtd.end_frame = RNA_int_get(op->ptr, "end_frame"); + gtd.gap_duration = RNA_float_get(op->ptr, "gap_duration"); + gtd.gap_randomness = RNA_float_get(op->ptr, "gap_randomness"); + gtd.gap_randomness = min_ff(gtd.gap_randomness, gtd.gap_duration); + gtd.seed = RNA_int_get(op->ptr, "seed"); + gtd.num_points = gtd.cur_point = 0; + gtd.dists = gtd.times = NULL; + gtd.tot_dist = gtd.tot_time = gtd.gap_tot_time = 0.0f; + gtd.inittime = 0.0; + + gp_layer_to_curve(C, op->reports, gpd, gpl, mode, norm_weights, rad_fac, link_strokes, >d); /* notifiers */ WM_event_add_notifier(C, NC_OBJECT | NA_ADDED, NULL); @@ -648,24 +1468,131 @@ static int gp_convert_layer_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } +static int gp_convert_draw_check_prop(PointerRNA *ptr, PropertyRNA *prop) +{ + const char *prop_id = RNA_property_identifier(prop); + int link_strokes = RNA_boolean_get(ptr, "use_link_strokes"); + int timing_mode = RNA_enum_get(ptr, "timing_mode"); + int realtime = RNA_boolean_get(ptr, "use_realtime"); + float gap_duration = RNA_float_get(ptr, "gap_duration"); + float gap_randomness = RNA_float_get(ptr, "gap_randomness"); + int valid_timing = RNA_boolean_get(ptr, "use_timing_data"); + + /* Always show those props */ + if (strcmp(prop_id, "type") == 0 || + strcmp(prop_id, "use_normalize_weights") == 0 || + strcmp(prop_id, "radius_multiplier") == 0 || + strcmp(prop_id, "use_link_strokes") == 0) + { + return TRUE; + } + + /* Never show this prop */ + if (strcmp(prop_id, "use_timing_data") == 0) + return FALSE; + + if (link_strokes) { + /* Only show when link_stroke is TRUE */ + if (strcmp(prop_id, "timing_mode") == 0) + return TRUE; + + if (timing_mode != GP_STROKECONVERT_TIMING_NONE) { + /* Only show when link_stroke is TRUE and stroke timing is enabled */ + if (strcmp(prop_id, "frame_range") == 0 || + strcmp(prop_id, "start_frame") == 0) + { + return TRUE; + } + + /* Only show if we have valid timing data! */ + if (valid_timing && strcmp(prop_id, "use_realtime") == 0) + return TRUE; + + /* Only show if realtime or valid_timing is FALSE! */ + if ((!realtime || !valid_timing) && strcmp(prop_id, "end_frame") == 0) + return TRUE; + + if (valid_timing && timing_mode == GP_STROKECONVERT_TIMING_CUSTOMGAP) { + /* Only show for custom gaps! */ + if (strcmp(prop_id, "gap_duration") == 0) + return TRUE; + + /* Only show randomness for non-null custom gaps! */ + if (strcmp(prop_id, "gap_randomness") == 0 && gap_duration > 0.0f) + return TRUE; + + /* Only show seed for randomize action! */ + if (strcmp(prop_id, "seed") == 0 && gap_duration > 0.0f && gap_randomness > 0.0f) + return TRUE; + } + } + } + + /* Else, hidden! */ + return FALSE; +} + +static void gp_convert_ui(bContext *C, wmOperator *op) +{ + uiLayout *layout = op->layout; + wmWindowManager *wm = CTX_wm_manager(C); + PointerRNA ptr; + + RNA_pointer_create(&wm->id, op->type->srna, op->properties, &ptr); + + /* Main auto-draw call */ + uiDefAutoButsRNA(layout, &ptr, gp_convert_draw_check_prop, '\0'); +} + void GPENCIL_OT_convert(wmOperatorType *ot) { + PropertyRNA *prop; + /* identifiers */ ot->name = "Convert Grease Pencil"; ot->idname = "GPENCIL_OT_convert"; - ot->description = "Convert the active Grease Pencil layer to a new Object"; - ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + ot->description = "Convert the active Grease Pencil layer to a new Curve Object"; /* callbacks */ ot->invoke = WM_menu_invoke; ot->exec = gp_convert_layer_exec; ot->poll = gp_convert_poll; + ot->ui = gp_convert_ui; /* flags */ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; /* properties */ - ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", ""); + ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to"); + RNA_def_boolean(ot->srna, "use_normalize_weights", TRUE, "Normalize Weight", + "Normalize weight (set from stroke width)"); + RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 10.0f, "Radius Fac", + "Multiplier for the points' radii (set from stroke width)", 0.0f, 1000.0f); + RNA_def_boolean(ot->srna, "use_link_strokes", TRUE, "Link Strokes", + "Whether to link strokes with zero-radius sections of curves"); + prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL, + "Timing Mode", "How to use timing data stored in strokes"); + RNA_def_enum_funcs(prop, rna_GPConvert_mode_items); + RNA_def_int(ot->srna, "frame_range", 100, 1, 10000, "Frame Range", + "The duration of evaluation of the path control curve", 1, 1000); + RNA_def_int(ot->srna, "start_frame", 1, 1, 100000, "Start Frame", + "The start frame of the path control curve", 1, 100000); + RNA_def_boolean(ot->srna, "use_realtime", FALSE, "Realtime", + "Whether the path control curve reproduces the drawing in realtime, starting from Start Frame"); + prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame", + "The end frame of the path control curve (if Realtime is not set)", 1, 100000); + RNA_def_property_update_runtime(prop, gp_convert_set_end_frame); + RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 1000.0f, "Gap Duration", + "Custom Gap mode: (Average) length of gaps, in frames " + "(note: realtime value, will be scaled if Realtime is not set)", 0.0f, 10000.0f); + RNA_def_float(ot->srna, "gap_randomness", 0.0f, 0.0f, 100.0f, "Gap Randomness", + "Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f); + RNA_def_int(ot->srna, "seed", 0, 0, 100, "Random Seed", + "Custom Gap mode: Random generator seed", 0, 1000); + /* Note: Internal use, this one will always be hidden by UI code... */ + prop = RNA_def_boolean(ot->srna, "use_timing_data", FALSE, "Has Valid Timing", + "Whether the converted grease pencil layer has valid timing data (internal use)"); + RNA_def_property_flag(prop, PROP_SKIP_SAVE); } /* ************************************************ */ diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index 9bfd89075af..fa681ae2f70 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -39,6 +39,8 @@ #include "BLI_math.h" #include "BLI_utildefines.h" +#include "PIL_time.h" + #include "BKE_gpencil.h" #include "BKE_context.h" #include "BKE_global.h" @@ -99,6 +101,14 @@ typedef struct tGPsdata { short radius; /* radius of influence for eraser */ short flags; /* flags that can get set during runtime */ + /* Those needs to be doubles, as (at least under unix) they are in seconds since epoch, + * float (and its 7 digits precision) is definitively not enough here! + * double, with its 15 digits precision, ensures us millisecond precision for a few centuries at least. + */ + double inittime; /* Used when converting to path */ + double curtime; /* Used when converting to path */ + double ocurtime; /* Used when converting to path */ + float imat[4][4]; /* inverted transformation matrix applying when converting coords from screen-space * to region space */ @@ -201,7 +211,7 @@ static void gp_get_3d_reference(tGPsdata *p, float vec[3]) float *fp = give_cursor(p->scene, v3d); /* the reference point used depends on the owner... */ -#if 0 // XXX: disabled for now, since we can't draw relative to the owner yet +#if 0 /* XXX: disabled for now, since we can't draw relative to the owner yet */ if (p->ownerPtr.type == &RNA_Object) { Object *ob = (Object *)p->ownerPtr.data; @@ -249,7 +259,7 @@ static short gp_stroke_filtermval(tGPsdata *p, const int mval[2], int pmval[2]) } /* convert screen-coordinates to buffer-coordinates */ -// XXX this method needs a total overhaul! +/* XXX this method needs a total overhaul! */ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3], float *depth) { bGPdata *gpd = p->gpd; @@ -310,7 +320,7 @@ static void gp_stroke_convertcoords(tGPsdata *p, const int mval[2], float out[3] } /* add current stroke-point to buffer (returns whether point was successfully added) */ -static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) +static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure, double curtime) { bGPdata *gpd = p->gpd; tGPspoint *pt; @@ -325,6 +335,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* increment buffer size */ gpd->sbuffer_size++; @@ -338,6 +349,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* if this is just the second point we've added, increment the buffer size * so that it will be drawn properly... @@ -361,6 +373,7 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* increment counters */ gpd->sbuffer_size++; @@ -378,10 +391,11 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* store settings */ copy_v2_v2_int(&pt->x, mval); pt->pressure = pressure; + pt->time = (float)(curtime - p->inittime); /* if there's stroke for this poly line session add (or replace last) point * to stroke. This allows to draw lines more interactively (see new segment - * during mouse slide, i.e.) + * during mouse slide, e.g.) */ if (gp_stroke_added_check(p)) { bGPDstroke *gps = p->gpf->strokes.last; @@ -410,8 +424,9 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &pt->x, &pts->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pts->pressure = pt->pressure; + pts->time = pt->time; } /* increment counters */ @@ -425,18 +440,11 @@ static short gp_stroke_addpoint(tGPsdata *p, const int mval[2], float pressure) return GP_STROKEADD_INVALID; } - -/* temp struct for gp_stroke_smooth() */ -typedef struct tGpSmoothCo { - int x; - int y; -} tGpSmoothCo; - /* smooth a stroke (in buffer) before storing it */ static void gp_stroke_smooth(tGPsdata *p) { bGPdata *gpd = p->gpd; - tGpSmoothCo *smoothArray, *spc; + tGPspoint *spt, tmp_spt[3]; int i = 0, cmx = gpd->sbuffer_size; /* only smooth if smoothing is enabled, and we're not doing a straight line */ @@ -447,30 +455,26 @@ static void gp_stroke_smooth(tGPsdata *p) if ((cmx <= 2) || (gpd->sbuffer == NULL)) return; - /* create a temporary smoothing coordinates buffer, use to store calculated values to prevent sequential error */ - smoothArray = MEM_callocN(sizeof(tGpSmoothCo) * cmx, "gp_stroke_smooth smoothArray"); - - /* first pass: calculate smoothing coordinates using weighted-averages */ - for (i = 0, spc = smoothArray; i < gpd->sbuffer_size; i++, spc++) { - const tGPspoint *pc = (((tGPspoint *)gpd->sbuffer) + i); - const tGPspoint *pb = (i - 1 > 0) ? (pc - 1) : (pc); - const tGPspoint *pa = (i - 2 > 0) ? (pc - 2) : (pb); - const tGPspoint *pd = (i + 1 < cmx) ? (pc + 1) : (pc); + /* Calculate smoothing coordinates using weighted-averages */ + /* XXX DO NOT smooth first and last points! */ + spt = (tGPspoint *)gpd->sbuffer; + /* This small array stores the last two points' org coordinates, we don't want to use already averaged ones! + * Note it is used as a cyclic buffer... + */ + tmp_spt[0] = *spt; + for (i = 1, spt++; i < cmx - 1; i++, spt++) { + const tGPspoint *pc = spt; + const tGPspoint *pb = &tmp_spt[(i - 1) % 3]; + const tGPspoint *pa = (i - 1 > 0) ? (&tmp_spt[(i - 2) % 3]) : (pb); + const tGPspoint *pd = pc + 1; const tGPspoint *pe = (i + 2 < cmx) ? (pc + 2) : (pd); - spc->x = (int)(0.1 * pa->x + 0.2 * pb->x + 0.4 * pc->x + 0.2 * pd->x + 0.1 * pe->x); - spc->y = (int)(0.1 * pa->y + 0.2 * pb->y + 0.4 * pc->y + 0.2 * pd->y + 0.1 * pe->y); - } - - /* second pass: apply smoothed coordinates */ - for (i = 0, spc = smoothArray; i < gpd->sbuffer_size; i++, spc++) { - tGPspoint *pc = (((tGPspoint *)gpd->sbuffer) + i); + /* Store current point's org state for the two next points! */ + tmp_spt[i % 3] = *spt; - copy_v2_v2_int(&pc->x, &spc->x); + spt->x = (int)(0.1 * pa->x + 0.2 * pb->x + 0.4 * pc->x + 0.2 * pd->x + 0.1 * pe->x); + spt->y = (int)(0.1 * pa->y + 0.2 * pb->y + 0.4 * pc->y + 0.2 * pd->y + 0.1 * pe->y); } - - /* free temp array */ - MEM_freeN(smoothArray); } /* simplify a stroke (in buffer) before storing it @@ -492,7 +496,7 @@ static void gp_stroke_simplify(tGPsdata *p) /* don't simplify if less than 4 points in buffer */ if ((num_points <= 4) || (old_points == NULL)) return; - + /* clear buffer (but don't free mem yet) so that we can write to it * - firstly set sbuffer to NULL, so a new one is allocated * - secondly, reset flag after, as it gets cleared auto @@ -509,17 +513,21 @@ static void gp_stroke_simplify(tGPsdata *p) co[0] += (float)(old_points[offs].x * sfac); \ co[1] += (float)(old_points[offs].y * sfac); \ pressure += old_points[offs].pressure * sfac; \ + time += old_points[offs].time * sfac; \ } (void)0 + /* XXX Here too, do not lose start and end points! */ + gp_stroke_addpoint(p, &old_points->x, old_points->pressure, p->inittime + (double)old_points->time); for (i = 0, j = 0; i < num_points; i++) { if (i - j == 3) { - float co[2], pressure; + float co[2], pressure, time; int mco[2]; /* initialize values */ - co[0] = 0; - co[1] = 0; - pressure = 0; + co[0] = 0.0f; + co[1] = 0.0f; + pressure = 0.0f; + time = 0.0f; /* using macro, calculate new point */ GP_SIMPLIFY_AVPOINT(j, -0.25f); @@ -532,11 +540,13 @@ static void gp_stroke_simplify(tGPsdata *p) mco[1] = (int)co[1]; /* ignore return values on this... assume to be ok for now */ - gp_stroke_addpoint(p, mco, pressure); + gp_stroke_addpoint(p, mco, pressure, p->inittime + (double)time); j += 2; } } + gp_stroke_addpoint(p, &old_points[num_points - 1].x, old_points[num_points - 1].pressure, + p->inittime + (double)old_points[num_points - 1].time); /* free old buffer */ MEM_freeN(old_points); @@ -571,7 +581,8 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* special case for poly line -- for already added stroke during session * coordinates are getting added to stroke immediately to allow more - * interactive behavior */ + * interactive behavior + */ if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { if (gp_stroke_added_check(p)) { return; @@ -585,6 +596,7 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) gps->totpoints = totelem; gps->thickness = p->gpl->thickness; gps->flag = gpd->sbuffer_sflag; + gps->inittime = p->inittime; /* allocate enough memory for a continuous array for storage points */ gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); @@ -602,8 +614,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; pt++; } @@ -615,8 +628,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; } } else if (p->paintmode == GP_PAINTMODE_DRAW_POLY) { @@ -626,8 +640,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; } else { float *depth_arr = NULL; @@ -699,8 +714,9 @@ static void gp_stroke_newfrombuffer(tGPsdata *p) /* convert screen-coordinates to appropriate coordinates (and store them) */ gp_stroke_convertcoords(p, &ptc->x, &pt->x, depth_arr ? depth_arr + i : NULL); - /* copy pressure */ + /* copy pressure and time */ pt->pressure = ptc->pressure; + pt->time = ptc->time; } if (depth_arr) @@ -750,6 +766,25 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) gps->totpoints--; gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); memcpy(gps->points, pt_tmp + 1, sizeof(bGPDspoint) * gps->totpoints); + + /* We must adjust timings! + * Each point's timing data is a delta from stroke's inittime, so as we erase the first + * point of the stroke, we have to offset this inittime and all remaing points' delta values. + * This way we get a new stroke with exactly the same timing as if user had started drawing from + * the second point... + */ + { + bGPDspoint *pts; + float delta = pt_tmp[1].time; + int j; + + gps->inittime += delta; + + pts = gps->points; + for (j = 0; j < gps->totpoints; j++, pts++) { + pts->time -= delta; + } + } /* free temp buffer */ MEM_freeN(pt_tmp); @@ -769,6 +804,25 @@ static short gp_stroke_eraser_splitdel(bGPDframe *gpf, bGPDstroke *gps, int i) gsn->points = MEM_callocN(sizeof(bGPDspoint) * gsn->totpoints, "gp_stroke_points"); memcpy(gsn->points, pt_tmp + i, sizeof(bGPDspoint) * gsn->totpoints); + /* We must adjust timings of this new stroke! + * Each point's timing data is a delta from stroke's inittime, so as we erase the first + * point of the stroke, we have to offset this inittime and all remaing points' delta values. + * This way we get a new stroke with exactly the same timing as if user had started drawing from + * the second point... + */ + { + bGPDspoint *pts; + float delta = pt_tmp[i].time; + int j; + + gsn->inittime += delta; + + pts = gsn->points; + for (j = 0; j < gsn->totpoints; j++, pts++) { + pts->time -= delta; + } + } + /* adjust existing stroke */ gps->totpoints = i; gps->points = MEM_callocN(sizeof(bGPDspoint) * gps->totpoints, "gp_stroke_points"); @@ -831,7 +885,7 @@ static void gp_point_to_xy(ARegion *ar, View2D *v2d, rctf *subrect, bGPDstroke * /* eraser tool - evaluation per stroke */ -// TODO: this could really do with some optimization (KD-Tree/BVH?) +/* TODO: this could really do with some optimization (KD-Tree/BVH?) */ static void gp_stroke_eraser_dostroke(tGPsdata *p, const int mval[], const int mvalo[], short rad, const rcti *rect, bGPDframe *gpf, bGPDstroke *gps) @@ -919,11 +973,11 @@ static void gp_session_validatebuffer(tGPsdata *p) /* clear memory of buffer (or allocate it if starting a new session) */ if (gpd->sbuffer) { - //printf("\t\tGP - reset sbuffer\n"); + /* printf("\t\tGP - reset sbuffer\n"); */ memset(gpd->sbuffer, 0, sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX); } else { - //printf("\t\tGP - allocate sbuffer\n"); + /* printf("\t\tGP - allocate sbuffer\n"); */ gpd->sbuffer = MEM_callocN(sizeof(tGPspoint) * GP_STROKE_BUFFER_MAX, "gp_session_strokebuffer"); } @@ -932,6 +986,9 @@ static void gp_session_validatebuffer(tGPsdata *p) /* reset flags */ gpd->sbuffer_sflag = 0; + + /* reset inittime */ + p->inittime = 0.0; } /* (re)init new painting data */ @@ -959,8 +1016,8 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) /* supported views first */ case SPACE_VIEW3D: { - // View3D *v3d = curarea->spacedata.first; - // RegionView3D *rv3d = ar->regiondata; + /* View3D *v3d = curarea->spacedata.first; */ + /* RegionView3D *rv3d = ar->regiondata; */ /* set current area * - must verify that region data is 3D-view (and not something else) @@ -979,7 +1036,7 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) case SPACE_NODE: { - //SpaceNode *snode = curarea->spacedata.first; + /* SpaceNode *snode = curarea->spacedata.first; */ /* set current area */ p->sa = curarea; @@ -1007,7 +1064,7 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) break; case SPACE_IMAGE: { - //SpaceImage *sima = curarea->spacedata.first; + /* SpaceImage *sima = curarea->spacedata.first; */ /* set the current area */ p->sa = curarea; @@ -1072,7 +1129,8 @@ static int gp_session_initdata(bContext *C, tGPsdata *p) if (ED_gpencil_session_active() == 0) { /* initialize undo stack, - * also, existing undo stack would make buffer drawn */ + * also, existing undo stack would make buffer drawn + */ gpencil_undo_init(p->gpd); } @@ -1107,7 +1165,7 @@ static void gp_session_cleanup(tGPsdata *p) /* free stroke buffer */ if (gpd->sbuffer) { - //printf("\t\tGP - free sbuffer\n"); + /* printf("\t\tGP - free sbuffer\n"); */ MEM_freeN(gpd->sbuffer); gpd->sbuffer = NULL; } @@ -1115,6 +1173,7 @@ static void gp_session_cleanup(tGPsdata *p) /* clear flags */ gpd->sbuffer_size = 0; gpd->sbuffer_sflag = 0; + p->inittime = 0.0; } /* init new stroke */ @@ -1259,7 +1318,8 @@ static void gp_paint_strokeend(tGPsdata *p) static void gp_paint_cleanup(tGPsdata *p) { /* p->gpd==NULL happens when stroke failed to initialize, - * for example. when GP is hidden in current space (sergey) */ + * for example when GP is hidden in current space (sergey) + */ if (p->gpd) { /* finish off a stroke */ gp_paint_strokeend(p); @@ -1307,7 +1367,7 @@ static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short en else if (enable) { /* enable cursor */ p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C), - NULL, // XXX + NULL, /* XXX */ gpencil_draw_eraser, p); } } @@ -1448,16 +1508,26 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) /* only add current point to buffer if mouse moved (even though we got an event, it might be just noise) */ else if (gp_stroke_filtermval(p, p->mval, p->mvalo)) { /* try to add point */ - short ok = gp_stroke_addpoint(p, p->mval, p->pressure); + short ok = gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); /* handle errors while adding point */ if ((ok == GP_STROKEADD_FULL) || (ok == GP_STROKEADD_OVERFLOW)) { /* finish off old stroke */ gp_paint_strokeend(p); + /* And start a new one!!! Else, projection errors! */ + gp_paint_initstroke(p, p->paintmode); /* start a new stroke, starting from previous point */ - gp_stroke_addpoint(p, p->mvalo, p->opressure); - gp_stroke_addpoint(p, p->mval, p->pressure); + /* XXX Must manually reset inittime... */ + /* XXX We only need to reuse previous point if overflow! */ + if (ok == GP_STROKEADD_OVERFLOW) { + p->inittime = p->ocurtime; + gp_stroke_addpoint(p, p->mvalo, p->opressure, p->ocurtime); + } + else { + p->inittime = p->curtime; + } + gp_stroke_addpoint(p, p->mval, p->pressure, p->curtime); } else if (ok == GP_STROKEADD_INVALID) { /* the painting operation cannot continue... */ @@ -1473,6 +1543,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p) p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; + p->ocurtime = p->curtime; } } @@ -1485,10 +1556,11 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) int tablet = 0; /* convert from window-space to area-space mouse coordinates - * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding... + * NOTE: float to ints conversions, +1 factor is probably used to ensure a bit more accurate rounding... */ p->mval[0] = event->mval[0] + 1; p->mval[1] = event->mval[1] + 1; + p->curtime = PIL_check_seconds_timer(); /* handle pressure sensitivity (which is supplied by tablets) */ if (event->custom == EVT_DATA_TABLET) { @@ -1497,8 +1569,8 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) tablet = (wmtab->Active != EVT_TABLET_NONE); p->pressure = wmtab->Pressure; - //if (wmtab->Active == EVT_TABLET_ERASER) - // TODO... this should get caught by the keymaps which call drawing in the first place + /* if (wmtab->Active == EVT_TABLET_ERASER) */ + /* TODO... this should get caught by the keymaps which call drawing in the first place */ } else p->pressure = 1.0f; @@ -1519,14 +1591,17 @@ static void gpencil_draw_apply_event(wmOperator *op, wmEvent *event) p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; - + p->inittime = p->ocurtime = p->curtime; + /* special exception here for too high pressure values on first touch in - * windows for some tablets, then we just skip first touch .. + * windows for some tablets, then we just skip first touch... */ if (tablet && (p->pressure >= 0.99f)) return; } + RNA_float_set(&itemptr, "time", p->curtime - p->inittime); + /* apply the current latest drawing point */ gpencil_draw_apply(op, p); @@ -1541,18 +1616,18 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) { tGPsdata *p = NULL; - //printf("GPencil - Starting Re-Drawing\n"); + /* printf("GPencil - Starting Re-Drawing\n"); */ /* try to initialize context data needed while drawing */ if (!gpencil_draw_init(C, op)) { if (op->customdata) MEM_freeN(op->customdata); - //printf("\tGP - no valid data\n"); + /* printf("\tGP - no valid data\n"); */ return OPERATOR_CANCELLED; } else p = op->customdata; - //printf("\tGP - Start redrawing stroke\n"); + /* printf("\tGP - Start redrawing stroke\n"); */ /* loop over the stroke RNA elements recorded (i.e. progress of mouse movement), * setting the relevant values in context at each step, then applying @@ -1561,20 +1636,21 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) { float mousef[2]; - //printf("\t\tGP - stroke elem\n"); + /* printf("\t\tGP - stroke elem\n"); */ /* get relevant data for this point from stroke */ RNA_float_get_array(&itemptr, "mouse", mousef); p->mval[0] = (int)mousef[0]; p->mval[1] = (int)mousef[1]; p->pressure = RNA_float_get(&itemptr, "pressure"); + p->curtime = (double)RNA_float_get(&itemptr, "time") + p->inittime; if (RNA_boolean_get(&itemptr, "is_start")) { /* if first-run flag isn't set already (i.e. not true first stroke), * then we must terminate the previous one first before continuing */ if ((p->flags & GP_PAINTFLAG_FIRSTRUN) == 0) { - // TODO: both of these ops can set error-status, but we probably don't need to worry + /* TODO: both of these ops can set error-status, but we probably don't need to worry */ gp_paint_strokeend(p); gp_paint_initstroke(p, p->paintmode); } @@ -1587,6 +1663,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) p->mvalo[0] = p->mval[0]; p->mvalo[1] = p->mval[1]; p->opressure = p->pressure; + p->ocurtime = p->curtime; } /* apply this data as necessary now (as per usual) */ @@ -1594,7 +1671,7 @@ static int gpencil_draw_exec(bContext *C, wmOperator *op) } RNA_END; - //printf("\tGP - done\n"); + /* printf("\tGP - done\n"); */ /* cleanup */ gpencil_draw_exit(C, op); @@ -1640,7 +1717,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) /* set cursor */ if (p->paintmode == GP_PAINTMODE_ERASER) - WM_cursor_modal(win, BC_CROSSCURSOR); // XXX need a better cursor + WM_cursor_modal(win, BC_CROSSCURSOR); /* XXX need a better cursor */ else WM_cursor_modal(win, BC_PAINTBRUSHCURSOR); @@ -1650,7 +1727,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) */ if (event->val == KM_PRESS) { /* hotkey invoked - start drawing */ - //printf("\tGP - set first spot\n"); + /* printf("\tGP - set first spot\n"); */ p->status = GP_STATUS_PAINTING; /* handle the initial drawing - i.e. for just doing a simple dot */ @@ -1658,7 +1735,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, wmEvent *event) } else { /* toolbar invoked - don't start drawing yet... */ - //printf("\tGP - hotkey invoked... waiting for click-drag\n"); + /* printf("\tGP - hotkey invoked... waiting for click-drag\n"); */ } WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); @@ -1686,7 +1763,7 @@ static tGPsdata *gpencil_stroke_begin(bContext *C, wmOperator *op) p->status = GP_STATUS_ERROR; } - //printf("\t\tGP - start stroke\n"); + /* printf("\t\tGP - start stroke\n"); */ /* we may need to set up paint env again if we're resuming */ /* XXX: watch it with the paintmode! in future, @@ -1735,16 +1812,17 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) * the stroke is converted to 3D only after * it is finished. This approach should work * better in tools that immediately apply - * in 3D space. */ + * in 3D space. + */ - //printf("\tGP - handle modal event...\n"); + /* printf("\tGP - handle modal event...\n"); */ /* exit painting mode (and/or end current stroke) * NOTE: cannot do RIGHTMOUSE (as is standard for cancelling) as that would break polyline [#32647] */ if (ELEM4(event->type, RETKEY, PADENTER, ESCKEY, SPACEKEY)) { /* exit() ends the current stroke before cleaning up */ - //printf("\t\tGP - end of paint op + end of stroke\n"); + /* printf("\t\tGP - end of paint op + end of stroke\n"); */ p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } @@ -1768,7 +1846,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) if (sketch) { /* end stroke only, and then wait to resume painting soon */ - //printf("\t\tGP - end stroke only\n"); + /* printf("\t\tGP - end stroke only\n"); */ gpencil_stroke_end(op); /* we've just entered idling state, so this event was processed (but no others yet) */ @@ -1778,7 +1856,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) WM_event_add_notifier(C, NC_GPENCIL | NA_EDITED, NULL); } else { - //printf("\t\tGP - end of stroke + op\n"); + /* printf("\t\tGP - end of stroke + op\n"); */ p->status = GP_STATUS_DONE; estate = OPERATOR_FINISHED; } @@ -1801,7 +1879,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) /* handle painting mouse-movements? */ if (ELEM(event->type, MOUSEMOVE, INBETWEEN_MOUSEMOVE) || (p->flags & GP_PAINTFLAG_FIRSTRUN)) { /* handle drawing event */ - //printf("\t\tGP - add point\n"); + /* printf("\t\tGP - add point\n"); */ gpencil_draw_apply_event(op, event); /* finish painting operation if anything went wrong just now */ @@ -1811,7 +1889,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) } else { /* event handled, so just tag as running modal */ - //printf("\t\t\t\tGP - add point handled!\n"); + /* printf("\t\t\t\tGP - add point handled!\n"); */ estate = OPERATOR_RUNNING_MODAL; } } @@ -1822,7 +1900,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) /* just resize the brush (local version) * TODO: fix the hardcoded size jumps (set to make a visible difference) and hardcoded keys */ - //printf("\t\tGP - resize eraser\n"); + /* printf("\t\tGP - resize eraser\n"); */ switch (event->type) { case WHEELUPMOUSE: /* larger */ case PADPLUSKEY: diff --git a/source/blender/editors/include/ED_gpencil.h b/source/blender/editors/include/ED_gpencil.h index 1d461f797d6..39dd8822267 100644 --- a/source/blender/editors/include/ED_gpencil.h +++ b/source/blender/editors/include/ED_gpencil.h @@ -56,6 +56,7 @@ struct wmKeyConfig; typedef struct tGPspoint { int x, y; /* x and y coordinates of cursor (in relative to area) */ float pressure; /* pressure of tablet at this point */ + float time; /* Time relative to stroke start (used when converting to path) */ } tGPspoint; diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index 100968e7257..b7c1ee675b3 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -41,6 +41,7 @@ typedef struct bGPDspoint { float x, y, z; /* co-ordinates of point (usually 2d, but can be 3d as well) */ float pressure; /* pressure of input device (from 0 to 1) at this point */ + float time; /* seconds since start of stroke */ } bGPDspoint; /* Grease-Pencil Annotations - 'Stroke' @@ -55,6 +56,7 @@ typedef struct bGPDstroke { short thickness; /* thickness of stroke (currently not used) */ short flag; /* various settings about this stroke */ + double inittime; /* Init time of stroke */ } bGPDstroke; /* bGPDstroke->flag */ From 99d26ceefd32dd287d1043b774a9284029510341 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 11 Nov 2012 14:53:17 +0000 Subject: [PATCH 106/118] Actually, need no more BKE_main.h here... --- source/blender/editors/gpencil/gpencil_edit.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index dda97abe5ec..7ddbed85226 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -61,7 +61,6 @@ #include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_library.h" -#include "BKE_main.h" #include "BKE_object.h" #include "BKE_report.h" #include "BKE_tracking.h" From afd42031a95ac2b60c8640950f037d1ff0dfa474 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Sun, 11 Nov 2012 15:02:05 +0000 Subject: [PATCH 107/118] Fix #32974: cycles curved motion blur is not working well combined with rotation, problem is that the curved interpolation is not constant speed which leads to mismatches. Turns out this is really hard to solve and implement efficiently, so curved motion blur is disabled for now, until I can find a solution. --- intern/cycles/util/util_transform.cpp | 7 +++++ intern/cycles/util/util_transform.h | 37 +++++++++++++++++++-------- 2 files changed, 34 insertions(+), 10 deletions(-) diff --git a/intern/cycles/util/util_transform.cpp b/intern/cycles/util/util_transform.cpp index 70ee13d96d7..4eee024990f 100644 --- a/intern/cycles/util/util_transform.cpp +++ b/intern/cycles/util/util_transform.cpp @@ -251,6 +251,13 @@ void transform_motion_decompose(MotionTransform *decomp, const MotionTransform * transform_decompose(&decomp->pre, &motion->pre); transform_decompose(&decomp->mid, mid); transform_decompose(&decomp->post, &motion->post); + + /* ensure rotation around shortest angle, negated quaternions are the same + * but this means we don't have to do the check in quat_interpolate */ + if(dot(decomp->mid.x, decomp->post.x) < 0.0f) + decomp->mid.x = -decomp->mid.x; + if(dot(decomp->pre.x, decomp->mid.x) < 0.0f) + decomp->pre.x = -decomp->pre.x; } CCL_NAMESPACE_END diff --git a/intern/cycles/util/util_transform.h b/intern/cycles/util/util_transform.h index df525542207..65162ebf4e6 100644 --- a/intern/cycles/util/util_transform.h +++ b/intern/cycles/util/util_transform.h @@ -39,16 +39,16 @@ typedef struct Transform { #endif } Transform; +/* transform decomposed in rotation/translation/scale. we use the same data + * structure as Transform, and tightly pack decomposition into it. first the + * rotation (4), then translation (3), then 3x3 scale matrix (9) */ + typedef struct MotionTransform { Transform pre; Transform mid; Transform post; } MotionTransform; -/* transform decomposed in rotation/translation/scale. we use the same data - * structure as Transform, and tightly pack decomposition into it. first the - * rotation (4), then translation (3), then 3x3 scale matrix (9) */ - /* Functions */ __device_inline float3 transform_perspective(const Transform *t, const float3 a) @@ -303,13 +303,11 @@ __device_inline Transform transform_clear_scale(const Transform& tfm) __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t) { + /* note: this does not ensure rotation around shortest angle, q1 and q2 + * are assumed to be matched already in transform_motion_decompose */ float costheta = dot(q1, q2); - /* rotate around shortest angle */ - if(costheta < 0.0f) { - costheta = -costheta; - q1 = -q1; - } + /* possible optimization: it might be possible to precompute theta/qperp */ if(costheta > 0.9995f) { /* linear interpolation in degenerate case */ @@ -318,14 +316,17 @@ __device_inline float4 quat_interpolate(float4 q1, float4 q2, float t) else { /* slerp */ float theta = acosf(clamp(costheta, -1.0f, 1.0f)); - float thetap = theta * t; float4 qperp = normalize(q2 - q1 * costheta); + float thetap = theta * t; return q1 * cosf(thetap) + qperp * sinf(thetap); } } __device_inline Transform transform_quick_inverse(Transform M) { + /* possible optimization: can we avoid doing this altogether and construct + * the inverse matrix directly from negated translation, transposed rotation, + * scale can be inverted but what about shearing? */ Transform R; float det = M.x.x*(M.z.z*M.y.y - M.z.y*M.y.z) - M.y.x*(M.z.z*M.x.y - M.z.y*M.x.z) + M.z.x*(M.y.z*M.x.y - M.y.y*M.x.z); @@ -380,10 +381,17 @@ __device_inline void transform_compose(Transform *tfm, const Transform *decomp) tfm->w = make_float4(0.0f, 0.0f, 0.0f, 1.0f); } +/* Disabled for now, need arc-length parametrization for constant speed motion. + * #define CURVED_MOTION_INTERPOLATE */ + __device void transform_motion_interpolate(Transform *tfm, const MotionTransform *motion, float t) { + /* possible optimization: is it worth it adding a check to skip scaling? + * it's probably quite uncommon to have scaling objects. or can we skip + * just shearing perhaps? */ Transform decomp; +#ifdef CURVED_MOTION_INTERPOLATE /* 3 point bezier curve interpolation for position */ float3 Ppre = float4_to_float3(motion->pre.y); float3 Pmid = float4_to_float3(motion->mid.y); @@ -395,13 +403,18 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform decomp.y.x = P.x; decomp.y.y = P.y; decomp.y.z = P.z; +#endif /* linear interpolation for rotation and scale */ if(t < 0.5f) { t *= 2.0f; decomp.x = quat_interpolate(motion->pre.x, motion->mid.x, t); +#ifdef CURVED_MOTION_INTERPOLATE decomp.y.w = (1.0f - t)*motion->pre.y.w + t*motion->mid.y.w; +#else + decomp.y = (1.0f - t)*motion->pre.y + t*motion->mid.y; +#endif decomp.z = (1.0f - t)*motion->pre.z + t*motion->mid.z; decomp.w = (1.0f - t)*motion->pre.w + t*motion->mid.w; } @@ -409,7 +422,11 @@ __device void transform_motion_interpolate(Transform *tfm, const MotionTransform t = (t - 0.5f)*2.0f; decomp.x = quat_interpolate(motion->mid.x, motion->post.x, t); +#ifdef CURVED_MOTION_INTERPOLATE decomp.y.w = (1.0f - t)*motion->mid.y.w + t*motion->post.y.w; +#else + decomp.y = (1.0f - t)*motion->mid.y + t*motion->post.y; +#endif decomp.z = (1.0f - t)*motion->mid.z + t*motion->post.z; decomp.w = (1.0f - t)*motion->mid.w + t*motion->post.w; } From 5ff301790036d2e9a841a748c95c6f38901459a2 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 11 Nov 2012 16:54:26 +0000 Subject: [PATCH 108/118] Replacing gettext i18n backend by boost::locale one. This commit adds a small and simplistic C wrapper around boost's locale library as intern/locale, and heavily simplifies/reduces Blender's own i18n code (under blenfont/ dir). And it adds back UI translation on windows' official builds (with msvc)! Note to platform maintainers: iconv and gettext (libintl) can now be removed from precompiled libs (not gettext binaries, under windows, of course ;) ). Note to MinGW32/64 users: boost_locale lib has not yet been uploaded for those build env, please disable WITH_INTERNATIONAL for now (hopefully will be fixed very soon, have contacted psy-fy). --- CMakeLists.txt | 106 +++----- build_files/cmake/macros.cmake | 12 - build_files/scons/config/darwin-config.py | 2 + build_files/scons/config/linux-config.py | 2 + .../scons/config/win32-mingw-config.py | 2 + build_files/scons/config/win32-vc-config.py | 2 + .../scons/config/win64-mingw-config.py | 2 + build_files/scons/config/win64-vc-config.py | 2 + intern/CMakeLists.txt | 4 + intern/SConscript | 3 + intern/locale/CMakeLists.txt | 44 ++++ intern/locale/SConscript | 14 + intern/locale/boost_locale_wrapper.cpp | 87 ++++++ intern/locale/boost_locale_wrapper.h | 49 ++++ source/blender/blenfont/BLF_translation.h | 26 +- source/blender/blenfont/CMakeLists.txt | 4 +- source/blender/blenfont/SConscript | 2 +- source/blender/blenfont/intern/blf_lang.c | 248 ++++-------------- .../blender/blenfont/intern/blf_translation.c | 86 ++---- source/blender/makesrna/intern/rna_access.c | 4 +- source/blenderplayer/CMakeLists.txt | 4 + source/creator/CMakeLists.txt | 20 +- .../gameengine/GamePlayer/ghost/GPG_ghost.cpp | 1 - 23 files changed, 335 insertions(+), 391 deletions(-) create mode 100644 intern/locale/CMakeLists.txt create mode 100644 intern/locale/SConscript create mode 100644 intern/locale/boost_locale_wrapper.cpp create mode 100644 intern/locale/boost_locale_wrapper.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 593cd9871aa..cb3ddb405bf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -296,11 +296,11 @@ if(APPLE) if(${CMAKE_GENERATOR} MATCHES "Xcode") - ##### cmake incompatibility with xcode 4.3 and higher ##### + ##### workaround for actual official cmake incompatibility with xcode 4.3 ##### if(${XCODE_VERSION} MATCHES '') # cmake fails due looking for xcode in the wrong path, thus will be empty var - message(FATAL_ERROR "Xcode 4.3 and higher must be used with cmake 2.8-8 or higher") + message("Official cmake does not yet support Xcode 4.3, get a patched version here: http://www.jensverwiebe.de/Blender/CMake%202.8-7patched.zip") endif() - ### end cmake incompatibility with xcode 4.3 and higher ### + ### end workaround for actual official cmake incompatibility with xcode 4.3 ### if(${XCODE_VERSION} VERSION_EQUAL 4 OR ${XCODE_VERSION} VERSION_GREATER 4 AND ${XCODE_VERSION} VERSION_LESS 4.3) # Xcode 4 defaults to the Apple LLVM Compiler. @@ -376,8 +376,8 @@ if(WITH_CYCLES) set(WITH_OPENIMAGEIO ON) endif() -# auto enable boost for cycles, booleans or audaspace -if(WITH_CYCLES OR WITH_MOD_BOOLEAN OR WITH_AUDASPACE) +# auto enable boost for cycles, booleans, audaspace or i18n +if(WITH_CYCLES OR WITH_MOD_BOOLEAN OR WITH_AUDASPACE OR WITH_INTERNATIONAL) set(WITH_BOOST ON) endif() @@ -593,28 +593,6 @@ if(UNIX AND NOT APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D__STDC_CONSTANT_MACROS") endif() - if(WITH_INTERNATIONAL) - find_library(INTL_LIBRARY - NAMES intl - PATHS - /sw/lib - ) - - find_library(ICONV_LIBRARY - NAMES iconv - PATHS - /sw/lib - ) - mark_as_advanced( - ICONV_LIBRARY - INTL_LIBRARY - ) - - if(INTL_LIBRARY AND ICONV_LIBRARY) - set(GETTEXT_LIBRARIES ${INTL_LIBRARY} ${ICONV_LIBRARY}) - endif() - endif() - if(WITH_FFTW3) find_package(Fftw3) if(NOT FFTW3_FOUND) @@ -662,7 +640,11 @@ if(UNIX AND NOT APPLE) else() set(Boost_USE_MULTITHREADED ON) endif() - find_package(Boost 1.34 COMPONENTS filesystem regex system thread) + set(__boost_packages filesystem regex system thread) + if (WITH_INTERNATIONAL) + list(APPEND __boost_packages locale) + endif() + find_package(Boost 1.34 COMPONENTS ${__boost_packages}) mark_as_advanced(Boost_DIR) # why doesnt boost do this? endif() @@ -879,13 +861,6 @@ elseif(WIN32) add_definitions(-DWIN32) - if(WITH_INTERNATIONAL) - set(ICONV ${LIBDIR}/iconv) - set(ICONV_INCLUDE_DIRS ${ICONV}/include) - set(ICONV_LIBRARIES iconv) - set(ICONV_LIBPATH ${ICONV}/lib) - endif() - set(JPEG "${LIBDIR}/jpeg") set(JPEG_INCLUDE_DIR "${JPEG}/include") set(JPEG_LIBPATH ${JPEG}/lib) # not cmake defined @@ -978,13 +953,6 @@ elseif(WIN32) set(CXX_WARNINGS "${_WARNINGS}") unset(_WARNINGS) - if(WITH_INTERNATIONAL) - set(GETTEXT ${LIBDIR}/gettext) - set(GETTEXT_INCLUDE_DIRS ${GETTEXT}/include) - set(GETTEXT_LIBPATH ${GETTEXT}/lib) - set(GETTEXT_LIBRARIES gnu_gettext) - endif() - if(WITH_MOD_CLOTH_ELTOPO) set(LAPACK ${LIBDIR}/lapack) # set(LAPACK_INCLUDE_DIR ${LAPACK}/include) @@ -1137,6 +1105,11 @@ elseif(WIN32) debug libboost_date_time-${BOOST_DEBUG_POSTFIX} debug libboost_filesystem-${BOOST_DEBUG_POSTFIX} debug libboost_regex-${BOOST_DEBUG_POSTFIX} debug libboost_system-${BOOST_DEBUG_POSTFIX} debug libboost_thread-${BOOST_DEBUG_POSTFIX}) + if(WITH_INTERNATIONAL) + set(BOOST_LIBRARIES ${BOOST_LIBRARIES} + optimized libboost_locale-${BOOST_POSTFIX} + debug libboost_locale-${BOOST_DEBUG_POSTFIX}) + endif(WITH_INTERNATIONAL) set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB") endif() @@ -1190,16 +1163,8 @@ elseif(WIN32) add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE) - add_definitions(-DFREE_WINDOWS) - if(WITH_INTERNATIONAL) - set(GETTEXT ${LIBDIR}/gettext) - set(GETTEXT_INCLUDE_DIRS ${GETTEXT}/include) - set(GETTEXT_LIBPATH ${GETTEXT}/lib) - set(GETTEXT_LIBRARIES intl) - endif() - set(PNG "${LIBDIR}/png") set(PNG_INCLUDE_DIR "${PNG}/include") set(PNG_LIBPATH ${PNG}/lib) # not cmake defined @@ -1317,6 +1282,11 @@ elseif(WIN32) debug boost_date_time-${BOOST_DEBUG_POSTFIX} boost_filesystem-${BOOST_DEBUG_POSTFIX} boost_regex-${BOOST_DEBUG_POSTFIX} boost_system-${BOOST_DEBUG_POSTFIX} boost_thread-${BOOST_DEBUG_POSTFIX}) + if(WITH_INTERNATIONAL) + set(BOOST_LIBRARIES ${BOOST_LIBRARIES} + optimized libboost_locale-${BOOST_POSTFIX} + debug libboost_locale-${BOOST_DEBUG_POSTFIX}) + endif(WITH_CYCLES_OSL) set(BOOST_LIBPATH ${BOOST}/lib) set(BOOST_DEFINITIONS "-DBOOST_ALL_NO_LIB -DBOOST_THREAD_USE_LIB ") endif() @@ -1383,13 +1353,10 @@ elseif(APPLE) endif() if(WITH_JACK) - find_library(JACK_FRAMEWORK - NAMES jackmp - ) - set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers) - if(NOT JACK_FRAMEWORK) - set(WITH_JACK OFF) - endif() + set(JACK /usr/local) + set(JACK_INCLUDE_DIRS ${JACK}/include/jack) + set(JACK_LIBRARIES jack) + set(JACK_LIBPATH ${JACK}/lib) endif() if(WITH_CODEC_SNDFILE) @@ -1427,13 +1394,6 @@ elseif(APPLE) set(PYTHON_LIBRARIES "${PYTHON_LIBRARY}") endif() - if(WITH_INTERNATIONAL) - set(GETTEXT ${LIBDIR}/gettext) - set(GETTEXT_INCLUDE_DIRS "${GETTEXT}/include") - set(GETTEXT_LIBRARIES intl iconv) - set(GETTEXT_LIBPATH ${GETTEXT}/lib) - endif() - if(WITH_FFTW3) set(FFTW3 ${LIBDIR}/fftw3) set(FFTW3_INCLUDE_DIRS ${FFTW3}/include) @@ -1500,10 +1460,10 @@ elseif(APPLE) if(WITH_INPUT_NDOF) # This thread it *should* work and check the framework - campbell # http://www.cmake.org/pipermail/cmake/2005-December/007740.html - find_library(3DCONNEXION_CLIENT_FRAMEWORK + find_library(3D_CONNEXION_CLIENT_LIBRARY NAMES 3DconnexionClient ) - if(NOT 3DCONNEXION_CLIENT_FRAMEWORK) + if(NOT 3D_CONNEXION_CLIENT_LIBRARY) set(WITH_INPUT_NDOF OFF) endif() @@ -1511,11 +1471,7 @@ elseif(APPLE) set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework 3DconnexionClient") endif() endif() - - if(WITH_JACK) - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework jackmp") - endif() - + else() set(PLATFORM_CFLAGS "-pipe -funsigned-char") set(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime") @@ -1579,6 +1535,9 @@ elseif(APPLE) set(BOOST ${LIBDIR}/boost) set(BOOST_INCLUDE_DIR ${BOOST}/include) set(BOOST_LIBRARIES boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt) + if (WITH_INTERNATIONAL) + list(APPEND BOOST_LIBRARIES boost_locale-mt) + endif() set(BOOST_LIBPATH ${BOOST}/lib) set(BOOST_DEFINITIONS) endif() @@ -1704,6 +1663,11 @@ if(WITH_CYCLES) endif() endif() +if(WITH_INTERNATIONAL) + if(NOT WITH_BOOST) + message(FATAL_ERROR "Internationalization reqires WITH_BOOST, the library may not have been found. Configure BOOST or disable WITH_INTERNATIONAL") + endif() +endif() # See TEST_SSE_SUPPORT() for how this is defined. diff --git a/build_files/cmake/macros.cmake b/build_files/cmake/macros.cmake index 3c321cc60be..2d9de5a5792 100644 --- a/build_files/cmake/macros.cmake +++ b/build_files/cmake/macros.cmake @@ -196,10 +196,6 @@ macro(SETUP_LIBDIRS) if(WITH_PYTHON) # AND NOT WITH_PYTHON_MODULE # WIN32 needs link_directories(${PYTHON_LIBPATH}) endif() - if(WITH_INTERNATIONAL) - link_directories(${ICONV_LIBPATH}) - link_directories(${GETTEXT_LIBPATH}) - endif() if(WITH_SDL) link_directories(${SDL_LIBPATH}) endif() @@ -287,14 +283,6 @@ macro(setup_liblinks target_link_libraries(${target} ${GLEW_LIBRARY}) endif() - if(WITH_INTERNATIONAL) - target_link_libraries(${target} ${GETTEXT_LIBRARIES}) - - if(WIN32 AND NOT UNIX) - target_link_libraries(${target} ${ICONV_LIBRARIES}) - endif() - endif() - if(WITH_OPENAL) target_link_libraries(${target} ${OPENAL_LIBRARY}) endif() diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py index afab4131de8..8511e9658c9 100644 --- a/build_files/scons/config/darwin-config.py +++ b/build_files/scons/config/darwin-config.py @@ -297,6 +297,8 @@ WITH_BF_BOOST = True BF_BOOST = LIBDIR + '/boost' BF_BOOST_INC = BF_BOOST + '/include' BF_BOOST_LIB = 'boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt' +if WITH_BF_INTERNATIONAL: + BF_BOOST_LIB += ' boost_locale-mt' BF_BOOST_LIBPATH = BF_BOOST + '/lib' WITH_BF_CYCLES_CUDA_BINARIES = False diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py index 45f6602e4dd..6160389a9ab 100644 --- a/build_files/scons/config/linux-config.py +++ b/build_files/scons/config/linux-config.py @@ -233,6 +233,8 @@ if not os.path.exists(LCGDIR + '/boost'): BF_BOOST = '/usr' BF_BOOST_INC = BF_BOOST + '/include' BF_BOOST_LIB = 'boost_date_time boost_filesystem boost_regex boost_system boost_thread' +if WITH_BF_INTERNATIONAL: + BF_BOOST_LIB += ' boost_locale' BF_BOOST_LIBPATH = BF_BOOST + '/lib' WITH_BF_CYCLES = WITH_BF_OIIO and WITH_BF_BOOST diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py index 0a72d87bb2a..29e7d8c0b1b 100644 --- a/build_files/scons/config/win32-mingw-config.py +++ b/build_files/scons/config/win32-mingw-config.py @@ -169,6 +169,8 @@ WITH_BF_BOOST = True BF_BOOST = LIBDIR + '/boost' BF_BOOST_INC = BF_BOOST + '/include' BF_BOOST_LIB = 'boost_date_time-mgw46-mt-s-1_49 boost_filesystem-mgw46-mt-s-1_49 boost_regex-mgw46-mt-s-1_49 boost_system-mgw46-mt-s-1_49 boost_thread-mgw46-mt-s-1_49' +if WITH_BF_INTERNATIONAL: + BF_BOOST_LIB += ' boost_locale-mgw46-mt-s-1_49' BF_BOOST_LIBPATH = BF_BOOST + '/lib' #Ray trace optimization diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py index b77ff8e70e0..dbb18177487 100644 --- a/build_files/scons/config/win32-vc-config.py +++ b/build_files/scons/config/win32-vc-config.py @@ -171,6 +171,8 @@ WITH_BF_BOOST = True BF_BOOST = '${LIBDIR}/boost' BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49' +if WITH_BF_INTERNATIONAL: + BF_BOOST_LIB += ' libboost_locale-vc90-mt-s-1_49' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' #CUDA diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py index 838822bbbcb..91206aa2e02 100644 --- a/build_files/scons/config/win64-mingw-config.py +++ b/build_files/scons/config/win64-mingw-config.py @@ -169,6 +169,8 @@ WITH_BF_BOOST = True BF_BOOST = LIBDIR + '/boost' BF_BOOST_INC = BF_BOOST + '/include' BF_BOOST_LIB = 'boost_date_time-mgw47-mt-s-1_49 boost_date_time-mgw47-mt-sd-1_49 boost_filesystem-mgw47-mt-s-1_49 boost_filesystem-mgw47-mt-sd-1_49 boost_regex-mgw47-mt-s-1_49 boost_regex-mgw47-mt-sd-1_49 boost_system-mgw47-mt-s-1_49 boost_system-mgw47-mt-sd-1_49 boost_thread-mgw47-mt-s-1_49 boost_thread-mgw47-mt-sd-1_49' +if WITH_BF_INTERNATIONAL: + BF_BOOST_LIB += ' boost_locale-mgw47-mt-s-1_49 boost_locale-mgw47-mt-sd-1_49' BF_BOOST_LIBPATH = BF_BOOST + '/lib' #Ray trace optimization diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py index 4b719469c39..45fef533a58 100644 --- a/build_files/scons/config/win64-vc-config.py +++ b/build_files/scons/config/win64-vc-config.py @@ -169,6 +169,8 @@ WITH_BF_BOOST = True BF_BOOST = '${LIBDIR}/boost' BF_BOOST_INC = '${BF_BOOST}/include' BF_BOOST_LIB = 'libboost_date_time-vc90-mt-s-1_49 libboost_filesystem-vc90-mt-s-1_49 libboost_regex-vc90-mt-s-1_49 libboost_system-vc90-mt-s-1_49 libboost_thread-vc90-mt-s-1_49' +if WITH_BF_INTERNATIONAL: + BF_BOOST_LIB += ' libboost_locale-vc90-mt-s-1_49' BF_BOOST_LIBPATH = '${BF_BOOST}/lib' #CUDA diff --git a/intern/CMakeLists.txt b/intern/CMakeLists.txt index cb2fc239859..be797c45ba1 100644 --- a/intern/CMakeLists.txt +++ b/intern/CMakeLists.txt @@ -65,6 +65,10 @@ if(WITH_CYCLES) add_subdirectory(cycles) endif() +if(WITH_INTERNATIONAL) + add_subdirectory(locale) +endif() + # only windows needs utf16 converter if(WIN32) add_subdirectory(utfconv) diff --git a/intern/SConscript b/intern/SConscript index 59e412333b0..5360ce4ea88 100644 --- a/intern/SConscript +++ b/intern/SConscript @@ -30,6 +30,9 @@ if env['WITH_BF_CYCLES']: if env['WITH_BF_BOOLEAN']: SConscript(['bsp/SConscript']) +if env['WITH_BF_INTERNATIONAL']: + SConscript(['locale/SConscript']) + if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-mingw', 'linuxcross', 'win64-vc'): SConscript(['utfconv/SConscript']) diff --git a/intern/locale/CMakeLists.txt b/intern/locale/CMakeLists.txt new file mode 100644 index 00000000000..f3356bcda49 --- /dev/null +++ b/intern/locale/CMakeLists.txt @@ -0,0 +1,44 @@ +# ***** BEGIN GPL LICENSE BLOCK ***** +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# The Original Code is Copyright (C) 2012, Blender Foundation +# All rights reserved. +# +# The Original Code is: all of this file. +# +# Contributor(s): Bastien Montagne. +# +# ***** END GPL LICENSE BLOCK ***** + +set(INC + . +) + +set(INC_SYS +) + +set(SRC + boost_locale_wrapper.cpp +) + +if(WITH_INTERNATIONAL) + list(APPEND INC_SYS + ${BOOST_INCLUDE_DIR} + ) + add_definitions(-DWITH_INTERNATIONAL) +endif() + +blender_add_lib(bf_intern_locale "${SRC}" "${INC}" "${INC_SYS}") diff --git a/intern/locale/SConscript b/intern/locale/SConscript new file mode 100644 index 00000000000..4a1357b76e4 --- /dev/null +++ b/intern/locale/SConscript @@ -0,0 +1,14 @@ +#!/usr/bin/python + +Import('env') + +sources = env.Glob('*.cpp') + +incs = '.' +defs = [] + +if env['WITH_BF_INTERNATIONAL']: + defs.append('WITH_INTERNATIONAL') + incs += ' ' + env['BF_BOOST_INC'] + +env.BlenderLib( 'bf_intern_locale', sources, Split(incs), defs, libtype=['extern','player'], priority=[10, 185]) diff --git a/intern/locale/boost_locale_wrapper.cpp b/intern/locale/boost_locale_wrapper.cpp new file mode 100644 index 00000000000..ec2976f19b9 --- /dev/null +++ b/intern/locale/boost_locale_wrapper.cpp @@ -0,0 +1,87 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012, Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Bastien Montagne. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +#include + +#include "boost_locale_wrapper.h" + +static std::string messages_path; +static std::string default_domain; + +void bl_locale_init(const char *_messages_path, const char *_default_domain) +{ + // Avoid using ICU backend, we do not need its power and it's rather heavy! + boost::locale::localization_backend_manager lman = boost::locale::localization_backend_manager::global(); +#if defined (_WIN32) + lman.select("winapi"); +#else + lman.select("posix"); +#endif + boost::locale::localization_backend_manager::global(lman); + + messages_path = _messages_path; + default_domain = _default_domain; +} + +void bl_locale_set(const char *locale) +{ + boost::locale::generator gen; + // Specify location of dictionaries. + gen.add_messages_path(messages_path); + gen.add_messages_domain(default_domain); + //gen.set_default_messages_domain(default_domain); + + if (locale && locale[0]) { + std::locale::global(gen(locale)); + } + else { + std::locale::global(gen("")); + } + // Note: boost always uses "C" LC_NUMERIC by default! +} + +const char* bl_locale_pgettext(const char *msgctxt, const char *msgid) +{ + // Note: We cannot use short stuff like boost::locale::gettext, because those return + // std::basic_string objects, which c_ptr()-returned char* is no more valid + // once deleted (which happens as soons they are out of scope of this func). + typedef boost::locale::message_format char_message_facet; + try { + std::locale l; + char_message_facet const &facet = std::use_facet(l); + char const *r = facet.get(0, msgctxt, msgid); + if(r) + return r; + return msgid; + } + catch(std::exception const &e) { +// std::cout << "boost_locale_pgettext: " << e.what() << " \n"; + return msgid; + } +} + diff --git a/intern/locale/boost_locale_wrapper.h b/intern/locale/boost_locale_wrapper.h new file mode 100644 index 00000000000..e7956d216f1 --- /dev/null +++ b/intern/locale/boost_locale_wrapper.h @@ -0,0 +1,49 @@ +/* + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The Original Code is Copyright (C) 2012, Blender Foundation + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): Bastien Montagne. + * + * ***** END GPL LICENSE BLOCK ***** + * + */ + +/** \file locale/boost_locale_wrapper.h + * \ingroup locale + * A thin C wrapper around boost::locale... + */ + +#ifndef __BOOST_LOCALE_WRAPPER_H__ +#define __BOOST_LOCALE_WRAPPER_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +void bl_locale_init(const char *messages_path, const char *default_domain); +void bl_locale_set(const char *locale); +const char* bl_locale_pgettext(const char *msgctxt, const char *msgid); + +#ifdef __cplusplus +} +#endif + +#endif /* __BOOST_LOCALE_WRAPPER_H__ */ diff --git a/source/blender/blenfont/BLF_translation.h b/source/blender/blenfont/BLF_translation.h index b01ce93cb65..d0b5d824bb3 100644 --- a/source/blender/blenfont/BLF_translation.h +++ b/source/blender/blenfont/BLF_translation.h @@ -35,16 +35,6 @@ #define TEXT_DOMAIN_NAME "blender" -/* blf_translation.c */ - -#ifdef WITH_INTERNATIONAL -unsigned char *BLF_get_unifont(int *unifont_size); -void BLF_free_unifont(void); -#endif - -const char *BLF_gettext(const char *msgid); -const char *BLF_pgettext(const char *context, const char *message); - /* blf_lang.c */ /* Search the path directory to the locale files, this try all @@ -61,17 +51,23 @@ void BLF_lang_set(const char *); /* Get the current locale (short code, e.g. es_ES). */ const char *BLF_lang_get(void); -/* Set the current encoding name. */ -void BLF_lang_encoding(const char *str); - /* Get EnumPropertyItem's for translations menu. */ struct EnumPropertyItem *BLF_RNA_lang_enum_properties(void); +/* blf_translation.c */ + +#ifdef WITH_INTERNATIONAL +unsigned char *BLF_get_unifont(int *unifont_size); +void BLF_free_unifont(void); +#endif + +const char *BLF_pgettext(const char *msgctxt, const char *msgid); + /* translation */ int BLF_translate_iface(void); int BLF_translate_tooltips(void); -const char *BLF_translate_do_iface(const char *contex, const char *msgid); -const char *BLF_translate_do_tooltip(const char *contex, const char *msgid); +const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid); +const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid); /* The "translation-marker" macro. */ diff --git a/source/blender/blenfont/CMakeLists.txt b/source/blender/blenfont/CMakeLists.txt index 022dfd282b0..90baef14a74 100644 --- a/source/blender/blenfont/CMakeLists.txt +++ b/source/blender/blenfont/CMakeLists.txt @@ -31,6 +31,7 @@ set(INC ../makesrna ../imbuf ../../../intern/guardedalloc + ../../../intern/locale ) set(INC_SYS @@ -54,9 +55,6 @@ set(SRC ) if(WITH_INTERNATIONAL) - list(APPEND INC_SYS - ${GETTEXT_INCLUDE_DIRS} - ) add_definitions(-DWITH_INTERNATIONAL) endif() diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript index 075da58b116..91c9c6789cf 100644 --- a/source/blender/blenfont/SConscript +++ b/source/blender/blenfont/SConscript @@ -4,7 +4,7 @@ Import ('env') sources = env.Glob('intern/*.c') -incs = '. intern #/intern/guardedalloc ../blenkernel ../blenlib ../blenloader' +incs = '. intern #/intern/guardedalloc #/intern/locale ../blenkernel ../blenlib ../blenloader' incs += ' ../makesdna ../makesrna ../imbuf ../editors/include' incs += ' #/extern/glew/include' incs += ' ' + env['BF_FREETYPE_INC'] diff --git a/source/blender/blenfont/intern/blf_lang.c b/source/blender/blenfont/intern/blf_lang.c index f02d4a25554..0ed48623dd5 100644 --- a/source/blender/blenfont/intern/blf_lang.c +++ b/source/blender/blenfont/intern/blf_lang.c @@ -28,20 +28,17 @@ */ -#include -#include -#include - -#include "BKE_global.h" - -#include "BLF_api.h" #include "BLF_translation.h" /* own include */ #ifdef WITH_INTERNATIONAL -#include +#include +#include +#include -#include "libintl.h" +#include "boost_locale_wrapper.h" + +#include "BKE_global.h" #include "DNA_userdef_types.h" @@ -49,30 +46,20 @@ #include "MEM_guardedalloc.h" -#include "BLI_string.h" -#include "BLI_utildefines.h" -#include "BLI_path_util.h" #include "BLI_fileops.h" #include "BLI_linklist.h" +#include "BLI_path_util.h" #include "BLI_string.h" - -#define SYSTEM_ENCODING_DEFAULT "UTF-8" -#define FONT_SIZE_DEFAULT 12 +#include "BLI_utildefines.h" /* Locale options. */ -static char global_messagepath[1024]; -static char global_language[32]; -static char global_encoding_name[32]; - static const char **locales = NULL; -static char **long_locales = NULL; /* XXX Temp fix until we get a final solution with modern intl lib under windows! */ static int num_locales = 0; static EnumPropertyItem *locales_menu = NULL; static int num_locales_menu = 0; #define ULANGUAGE ((U.language >= 0 && U.language < num_locales) ? U.language : 0) #define LOCALE(_id) (locales ? locales[_id] : "") -#define LONG_LOCALE(_id) (long_locales ? long_locales[_id] : "") static void free_locales(void) { @@ -84,17 +71,8 @@ static void free_locales(void) MEM_freeN((void *)locales_menu[idx].description); /* Also frees locales's relevant value! */ } - idx = num_locales; - while (idx--) { - if (long_locales[idx]) { - MEM_freeN(long_locales[idx]); - } - } - MEM_freeN(locales); locales = NULL; - MEM_freeN(long_locales); - long_locales = NULL; } if (locales_menu) { MEM_freeN(locales_menu); @@ -140,7 +118,6 @@ static void fill_locales(void) /* Do not allocate locales with zero-sized mem, as LOCALE macro uses NULL locales as invalid marker! */ if (num_locales > 0) { locales = MEM_callocN(num_locales * sizeof(char*), __func__); - long_locales = MEM_callocN(num_locales * sizeof(char*), __func__); while (line) { int id; char *loc, *sep1, *sep2, *sep3; @@ -163,26 +140,28 @@ static void fill_locales(void) sep2++; sep3 = strchr(sep2, ':'); + if (sep3) { locales_menu[idx].identifier = loc = BLI_strdupn(sep2, sep3 - sep2); - - if (id == 0) { - /* The DEFAULT item... */ - if (BLI_strnlen(loc, 2)) { - locales[id] = locales_menu[idx].description = BLI_strdup(""); - long_locales[id] = BLI_strdup(""); - } - /* Menu "label", not to be stored in locales! */ - else { - locales_menu[idx].description = BLI_strdup(""); - } - } - else { - locales[id] = locales_menu[idx].description = BLI_strdup(loc); - long_locales[id] = BLI_strdup(sep3 + 1); - } - idx++; } + else { + locales_menu[idx].identifier = loc = BLI_strdup(sep2); + } + + if (id == 0) { + /* The DEFAULT item... */ + if (BLI_strnlen(loc, 2)) { + locales[id] = locales_menu[idx].description = BLI_strdup(""); + } + /* Menu "label", not to be stored in locales! */ + else { + locales_menu[idx].description = BLI_strdup(""); + } + } + else { + locales[id] = locales_menu[idx].description = BLI_strdup(loc); + } + idx++; } } @@ -207,15 +186,12 @@ void BLF_lang_init(void) { char *messagepath = BLI_get_folder(BLENDER_DATAFILES, "locale"); - BLI_strncpy(global_encoding_name, SYSTEM_ENCODING_DEFAULT, sizeof(global_encoding_name)); - if (messagepath) { - BLI_strncpy(global_messagepath, messagepath, sizeof(global_messagepath)); + bl_locale_init(messagepath, TEXT_DOMAIN_NAME); fill_locales(); } else { printf("%s: 'locale' data path for translations not found, continuing\n", __func__); - global_messagepath[0] = '\0'; } } @@ -224,159 +200,37 @@ void BLF_lang_free(void) free_locales(); } -/* Get LANG/LANGUAGE environment variable. */ -static void get_language_variable(const char *varname, char *var, const size_t maxlen) -{ - char *env = getenv(varname); - - if (env) { - char *s; - - /* Store defaul locale. */ - BLI_strncpy(var, env, maxlen); - - /* Use first language as default. */ - s = strchr(var, ':'); - if (s) - s[0] = 0; - } -} - -/* Get language to be used based on locale (which might be empty when using default language) and - * LANG environment variable. - */ -static void get_language(const char *locale, const char *lang, char *language, const size_t maxlen) -{ - if (locale[0]) { - BLI_strncpy(language, locale, maxlen); - } - else { - char *s; - - BLI_strncpy(language, lang, maxlen); - - s = strchr(language, '.'); - if (s) - s[0] = 0; - } -} - -/* XXX WARNING!!! In osx somehow the previous function call jumps in this one??? (ton, ppc) */ void BLF_lang_set(const char *str) { - char *locreturn; - int ok = TRUE; int ulang = ULANGUAGE; + const char *short_locale = str ? str : LOCALE(ulang); + const char *short_locale_utf8 = NULL; if ((U.transopts & USER_DOTRANSLATE) == 0) return; -#if defined(_WIN32) && !defined(FREE_WINDOWS) - { - const char *long_locale = str ? str : LONG_LOCALE(ulang); - if (long_locale) { - char *envStr; - - if (ulang) - envStr = BLI_sprintfN("LANG=%s", long_locale); - else /* Use system setting. */ - envStr = BLI_sprintfN("LANG=%s", getenv("LANG")); - - gettext_putenv(envStr); - MEM_freeN(envStr); - } - - locreturn = setlocale(LC_ALL, long_locale); - - if (locreturn == NULL) { - if (G.debug & G_DEBUG) - printf("Could not change locale to %s\n", long_locale); - - ok = FALSE; - } - } -#else - { - const char *short_locale = str ? str : LOCALE(ulang); - static char default_lang[64] = "\0"; - static char default_language[64] = "\0"; - - if (default_lang[0] == 0) - get_language_variable("LANG", default_lang, sizeof(default_lang)); - - if (default_language[0] == 0) - get_language_variable("LANGUAGE", default_language, sizeof(default_language)); - - if (short_locale[0]) { - char *short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale); - - if (G.debug & G_DEBUG) - printf("Setting LANG and LANGUAGE to %s\n", short_locale_utf8); - - locreturn = setlocale(LC_ALL, short_locale_utf8); - - if (locreturn != NULL) { - BLI_setenv("LANG", short_locale_utf8); - BLI_setenv("LANGUAGE", short_locale_utf8); - } - else { - if (G.debug & G_DEBUG) - printf("Setting LANG and LANGUAGE to %s\n", short_locale); - - locreturn = setlocale(LC_ALL, short_locale); - - if (locreturn != NULL) { - BLI_setenv("LANG", short_locale); - BLI_setenv("LANGUAGE", short_locale); - } - } - - if (G.debug & G_DEBUG && locreturn == NULL) - printf("Could not change locale to %s nor %s\n", short_locale, short_locale_utf8); - - MEM_freeN(short_locale_utf8); + /* We want to avoid locales like '.UTF-8'! */ + if (short_locale[0]) { + /* Hurrey! encoding needs to be placed *before* variant! */ + char *variant = strchr(short_locale, '@'); + if (variant) { + char *locale = BLI_strdupn(short_locale, variant - short_locale); + short_locale_utf8 = BLI_sprintfN("%s.UTF-8%s", locale, variant); + MEM_freeN(locale); } else { - if (G.debug & G_DEBUG) - printf("Setting LANG=%s and LANGUAGE=%s\n", default_lang, default_language); - - BLI_setenv("LANG", default_lang); - BLI_setenv("LANGUAGE", default_language); - locreturn = setlocale(LC_ALL, ""); - - if (G.debug & G_DEBUG && locreturn == NULL) - printf("Could not reset locale\n"); - } - - if (locreturn == NULL) { - char language[65]; - - get_language(short_locale, default_lang, language, sizeof(language)); - - if (G.debug & G_DEBUG) - printf("Fallback to LANG=%s and LANGUAGE=%s\n", default_lang, language); - - /* Fallback to default settings. */ - BLI_setenv("LANG", default_lang); - BLI_setenv("LANGUAGE", language); - - locreturn = setlocale(LC_ALL, ""); - - ok = FALSE; + short_locale_utf8 = BLI_sprintfN("%s.UTF-8", short_locale); } } -#endif - - if (ok) { - /*printf("Change locale to %s\n", locreturn ); */ - BLI_strncpy(global_language, locreturn, sizeof(global_language)); + else { + short_locale_utf8 = short_locale; } - setlocale(LC_NUMERIC, "C"); + bl_locale_set(short_locale_utf8); - textdomain(TEXT_DOMAIN_NAME); - bindtextdomain(TEXT_DOMAIN_NAME, global_messagepath); - bind_textdomain_codeset(TEXT_DOMAIN_NAME, global_encoding_name); + if (short_locale[0]) { + MEM_freeN((void*)short_locale_utf8); + } } const char *BLF_lang_get(void) @@ -385,12 +239,6 @@ const char *BLF_lang_get(void) return LOCALE(uilang); } -void BLF_lang_encoding(const char *str) -{ - BLI_strncpy(global_encoding_name, str, sizeof(global_encoding_name)); - /* bind_textdomain_codeset(TEXT_DOMAIN_NAME, encoding_name); */ -} - #undef LOCALE #undef ULANGUAGE @@ -406,12 +254,6 @@ void BLF_lang_free(void) return; } -void BLF_lang_encoding(const char *str) -{ - (void)str; - return; -} - void BLF_lang_set(const char *str) { (void)str; diff --git a/source/blender/blenfont/intern/blf_translation.c b/source/blender/blenfont/intern/blf_translation.c index 9c863da9eba..5d4b631688a 100644 --- a/source/blender/blenfont/intern/blf_translation.c +++ b/source/blender/blenfont/intern/blf_translation.c @@ -31,18 +31,11 @@ #include #include +#include "BLF_translation.h" + #ifdef WITH_INTERNATIONAL -#include -#include -#define GETTEXT_CONTEXT_GLUE "\004" - -/* needed for windows version of gettext */ -#ifndef LC_MESSAGES -# define LC_MESSAGES 1729 -#endif - -#endif +#include "boost_locale_wrapper.h" #include "MEM_guardedalloc.h" @@ -52,11 +45,8 @@ #include "BLI_path_util.h" #include "BLI_fileops.h" -#include "BLF_translation.h" - #include "DNA_userdef_types.h" /* For user settings. */ -#ifdef WITH_INTERNATIONAL static const char unifont_filename[] = "droidsans.ttf.gz"; static unsigned char *unifont_ttf = NULL; static int unifont_size = 0; @@ -90,55 +80,19 @@ void BLF_free_unifont(void) #endif -const char *BLF_gettext(const char *msgid) +const char *BLF_pgettext(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL - if (msgid && msgid[0]) - return gettext(msgid); + if (msgid && msgid[0]) { + return bl_locale_pgettext(msgctxt, msgid); + } return ""; #else + (void)msgctxt; return msgid; #endif } -const char *BLF_pgettext(const char *context, const char *message) -{ -#ifdef WITH_INTERNATIONAL - char static_msg_ctxt_id[1024]; - char *dynamic_msg_ctxt_id = NULL; - char *msg_ctxt_id; - const char *translation; - - size_t overall_length = strlen(context) + strlen(message) + sizeof(GETTEXT_CONTEXT_GLUE) + 1; - - if (!message || !context || !message[0]) - return ""; - - if (overall_length > sizeof(static_msg_ctxt_id)) { - dynamic_msg_ctxt_id = malloc(overall_length); - msg_ctxt_id = dynamic_msg_ctxt_id; - } - else { - msg_ctxt_id = static_msg_ctxt_id; - } - - sprintf(msg_ctxt_id, "%s%s%s", context, GETTEXT_CONTEXT_GLUE, message); - - translation = (char *)dcgettext(TEXT_DOMAIN_NAME, msg_ctxt_id, LC_MESSAGES); - - if (dynamic_msg_ctxt_id) - free(dynamic_msg_ctxt_id); - - if (translation == msg_ctxt_id) - translation = message; - - return translation; -#else - (void)context; - return message; -#endif -} - int BLF_translate_iface(void) { #ifdef WITH_INTERNATIONAL @@ -157,36 +111,32 @@ int BLF_translate_tooltips(void) #endif } -const char *BLF_translate_do_iface(const char *context, const char *msgid) +const char *BLF_translate_do_iface(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL if (BLF_translate_iface()) { - if (context) - return BLF_pgettext(context, msgid); - else - return BLF_gettext(msgid); + return BLF_pgettext(msgctxt, msgid); } - else + else { return msgid; + } #else - (void)context; + (void)msgctxt; return msgid; #endif } -const char *BLF_translate_do_tooltip(const char *context, const char *msgid) +const char *BLF_translate_do_tooltip(const char *msgctxt, const char *msgid) { #ifdef WITH_INTERNATIONAL if (BLF_translate_tooltips()) { - if (context) - return BLF_pgettext(context, msgid); - else - return BLF_gettext(msgid); + return BLF_pgettext(msgctxt, msgid); } - else + else { return msgid; + } #else - (void)context; + (void)msgctxt; return msgid; #endif } diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 69332dcd250..81e738ed82f 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -1224,10 +1224,10 @@ void RNA_property_enum_items_gettexted(bContext *C, PointerRNA *ptr, PropertyRNA if (prop->translation_context) nitem[i].name = BLF_pgettext(prop->translation_context, nitem[i].name); else - nitem[i].name = BLF_gettext(nitem[i].name); + nitem[i].name = BLF_pgettext(NULL, nitem[i].name); } if (nitem[i].description) - nitem[i].description = BLF_gettext(nitem[i].description); + nitem[i].description = BLF_pgettext(NULL, nitem[i].description); } *item = nitem; diff --git a/source/blenderplayer/CMakeLists.txt b/source/blenderplayer/CMakeLists.txt index 828b7f5066c..11e790451cd 100644 --- a/source/blenderplayer/CMakeLists.txt +++ b/source/blenderplayer/CMakeLists.txt @@ -191,6 +191,10 @@ endif() list(APPEND BLENDER_SORTED_LIBS bf_intern_guardedalloc_cpp) endif() + if(WITH_INTERNATIONAL) + list(APPEND BLENDER_SORTED_LIBS bf_intern_locale) + endif() + foreach(SORTLIB ${BLENDER_SORTED_LIBS}) set(REMLIB ${SORTLIB}) foreach(SEARCHLIB ${BLENDER_LINK_LIBS}) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index c06669c3ac2..9087d106f96 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -469,20 +469,6 @@ elseif(WIN32) DESTINATION ${TARGETDIR} ) - if(WITH_INTERNATIONAL AND (NOT WITH_MINGW64)) - install( - FILES ${LIBDIR}/gettext/lib/gnu_gettext.dll - DESTINATION ${TARGETDIR} - ) - - if(NOT CMAKE_CL_64) - install( - FILES ${LIBDIR}/iconv/lib/iconv.dll - DESTINATION ${TARGETDIR} - ) - endif() - endif() - if(WITH_PYTHON) set_lib_path(PYLIB "python") install( @@ -530,7 +516,7 @@ elseif(WIN32) endif() if(CMAKE_CL_64) - # gettext and png are statically linked on win64 + # png is statically linked on win64 install( FILES ${LIBDIR}/zlib/lib/zlib.dll DESTINATION ${TARGETDIR} @@ -987,6 +973,10 @@ endif() list_insert_after(BLENDER_SORTED_LIBS "cycles_kernel" "cycles_kernel_osl") endif() + if(WITH_INTERNATIONAL) + list(APPEND BLENDER_SORTED_LIBS bf_intern_locale) + endif() + foreach(SORTLIB ${BLENDER_SORTED_LIBS}) set(REMLIB ${SORTLIB}) foreach(SEARCHLIB ${BLENDER_LINK_LIBS}) diff --git a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp index 54457d0efdf..3e8755c41ce 100644 --- a/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp +++ b/source/gameengine/GamePlayer/ghost/GPG_ghost.cpp @@ -450,7 +450,6 @@ int main(int argc, char** argv) // Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c) BLF_init(11, U.dpi); BLF_lang_init(); - BLF_lang_encoding(""); BLF_lang_set(""); BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size); From 70080d005b4954278bd7d89cc3b03305e17eb616 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Sun, 11 Nov 2012 17:04:12 +0000 Subject: [PATCH 109/118] OSX/cmake-2.8-10: just reorder, now sdk must be set before deployment target --- CMakeLists.txt | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cb3ddb405bf..e621125464c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -289,10 +289,6 @@ if(APPLE) set(OSX_SYSTEM unsupported) endif() message(STATUS "Detected system-version: " ${OSX_SYSTEM}) - - if(NOT CMAKE_OSX_DEPLOYMENT_TARGET) - set(CMAKE_OSX_DEPLOYMENT_TARGET "10.6" CACHE STRING "" FORCE) # 10.6 is our min. target, if you use higher sdk, weak linking happens - with 10.5 we have still not solved problems, build those with 10.5.sdk for now !!! - endif() if(${CMAKE_GENERATOR} MATCHES "Xcode") @@ -319,6 +315,20 @@ if(APPLE) endif() message(STATUS "Detected Xcode-version: " ${XCODE_VERSION}) + + if(${XCODE_VERSION} VERSION_LESS 4.3) + set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk CACHE PATH "" FORCE) # use guaranteed existing sdk + else() + # note: i don't use xcode-select path on purpose, cause also /Applications/Xcode.app would be allowed + # absolute pathes are more foolproof here ! + set(OSX_SYSROOT_PREFIX /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform) + set(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk) # use guaranteed existing sdk + set(CMAKE_OSX_SYSROOT ${OSX_SYSROOT_PREFIX}/${OSX_DEVELOPER_PREFIX} CACHE PATH "" FORCE) + endif() + + if(NOT CMAKE_OSX_DEPLOYMENT_TARGET) + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.5" CACHE STRING "" FORCE) # 10.5 is our min. target, if you use higher sdk, weak linking happens + endif() option(WITH_COCOA "Use Cocoa framework instead of deprecated Carbon" ON) option(USE_QTKIT "Use QtKit instead of Carbon quicktime (needed for having partial quicktime for 64bit)" OFF) @@ -1321,16 +1331,6 @@ elseif(APPLE) set(WITH_LIBS10.5 ON CACHE BOOL "Use 10.5 libs" FORCE) # valid also for 10.6/10.7 endif() - if(${XCODE_VERSION} VERSION_LESS 4.3) - set(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk CACHE PATH "" FORCE) # use guaranteed existing sdk - else() - # note: i don't use xcode-select path on purpose, cause also /Applications/Xcode.app would be allowed - # absolute pathes are more foolproof here ! - set(OSX_SYSROOT_PREFIX /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform) - set(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk) # use guaranteed existing sdk - set(CMAKE_OSX_SYSROOT ${OSX_SYSROOT_PREFIX}/${OSX_DEVELOPER_PREFIX} CACHE PATH "" FORCE) - endif() - if(WITH_LIBS10.5) set(LIBDIR ${CMAKE_SOURCE_DIR}/../lib/darwin-9.x.universal) else() From 7165c352beb58d128949e84b215b3f864f6291c6 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Sun, 11 Nov 2012 18:06:10 +0000 Subject: [PATCH 110/118] Restore my work overwritten by 52106 and some further reordering for cmake 2.8.10, todo: take into account missing symlinks for Library and /usr/local in newest xcode, affects ndof and jack --- CMakeLists.txt | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e621125464c..e162b0b1508 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -292,11 +292,11 @@ if(APPLE) if(${CMAKE_GENERATOR} MATCHES "Xcode") - ##### workaround for actual official cmake incompatibility with xcode 4.3 ##### + ##### cmake incompatibility with xcode 4.3 and higher ##### if(${XCODE_VERSION} MATCHES '') # cmake fails due looking for xcode in the wrong path, thus will be empty var - message("Official cmake does not yet support Xcode 4.3, get a patched version here: http://www.jensverwiebe.de/Blender/CMake%202.8-7patched.zip") + message(FATAL_ERROR "Xcode 4.3 and higher must be used with cmake 2.8-8 or higher") endif() - ### end workaround for actual official cmake incompatibility with xcode 4.3 ### + ### end cmake incompatibility with xcode 4.3 and higher ### if(${XCODE_VERSION} VERSION_EQUAL 4 OR ${XCODE_VERSION} VERSION_GREATER 4 AND ${XCODE_VERSION} VERSION_LESS 4.3) # Xcode 4 defaults to the Apple LLVM Compiler. @@ -308,10 +308,6 @@ if(APPLE) execute_process(COMMAND xcodebuild -version OUTPUT_VARIABLE XCODE_VERS_BUILD_NR) string(SUBSTRING "${XCODE_VERS_BUILD_NR}" 6 3 XCODE_VERSION) # truncate away build-nr unset(XCODE_VERS_BUILD_NR) - # force CMAKE_OSX_DEPLOYMENT_TARGET for makefiles, will not work else ( cmake bug ? ) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") - add_definitions ("-DMACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}") endif() message(STATUS "Detected Xcode-version: " ${XCODE_VERSION}) @@ -330,6 +326,13 @@ if(APPLE) set(CMAKE_OSX_DEPLOYMENT_TARGET "10.5" CACHE STRING "" FORCE) # 10.5 is our min. target, if you use higher sdk, weak linking happens endif() + if(NOT ${CMAKE_GENERATOR} MATCHES "Xcode") + # force CMAKE_OSX_DEPLOYMENT_TARGET for makefiles, will not work else ( cmake bug ? ) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=${CMAKE_OSX_DEPLOYMENT_TARGET}") + add_definitions ("-DMACOSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}") + endif() + option(WITH_COCOA "Use Cocoa framework instead of deprecated Carbon" ON) option(USE_QTKIT "Use QtKit instead of Carbon quicktime (needed for having partial quicktime for 64bit)" OFF) option(WITH_LIBS10.5 "Use 10.5 libs (needed for 64bit builds)" OFF) @@ -1076,11 +1079,13 @@ elseif(WIN32) endif() if(WITH_JACK) - set(JACK_INCLUDE_DIRS - ${LIBDIR}/jack/include/jack - ${LIBDIR}/jack/include + find_library(JACK_FRAMEWORK + NAMES jackmp ) - set(JACK_LIBRARIES ${LIBDIR}/jack/lib/libjack.lib) + set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers) + if(NOT JACK_FRAMEWORK) + set(WITH_JACK OFF) + endif() endif() if(WITH_PYTHON) @@ -1460,18 +1465,22 @@ elseif(APPLE) if(WITH_INPUT_NDOF) # This thread it *should* work and check the framework - campbell # http://www.cmake.org/pipermail/cmake/2005-December/007740.html - find_library(3D_CONNEXION_CLIENT_LIBRARY + find_library(3DCONNEXION_CLIENT_FRAMEWORK NAMES 3DconnexionClient ) - if(NOT 3D_CONNEXION_CLIENT_LIBRARY) + if(NOT 3DCONNEXION_CLIENT_FRAMEWORK) set(WITH_INPUT_NDOF OFF) endif() if(WITH_INPUT_NDOF) - set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework 3DconnexionClient") + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework /Library/Frameworks/3DconnexionClient.framework/3DconnexionClient") endif() endif() + if(WITH_JACK) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -weak_framework jackmp") + endif() + else() set(PLATFORM_CFLAGS "-pipe -funsigned-char") set(PLATFORM_LINKFLAGS "-fexceptions -framework CoreServices -framework Foundation -framework IOKit -framework AppKit -framework Carbon -framework AGL -framework AudioUnit -framework AudioToolbox -framework CoreAudio -framework QuickTime") From 724c55aafaee9078e6f49fd0e50c80d24105a699 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 11 Nov 2012 18:26:39 +0000 Subject: [PATCH 111/118] Fix a stupid warning (due to last minute refactor...). --- source/blender/editors/gpencil/gpencil_edit.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index 7ddbed85226..dbf04e772f5 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -623,7 +623,7 @@ static void gp_stroke_path_animation_preprocess_gaps(tGpTimingData *gtd, int *nb } static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerRNA ptr, PropertyRNA *prop, FCurve *fcu, - Curve *cu, tGpTimingData *gtd, float cfra, float time_range, + Curve *cu, tGpTimingData *gtd, float time_range, int nbr_gaps, float tot_gaps_time) { /* Use actual recorded timing! */ @@ -638,6 +638,7 @@ static void gp_stroke_path_animation_add_keyframes(ReportList *reports, PointerR int nbr_done_gaps = 0; int i; + float cfra; /* This is a bit tricky, as: * - We can't add arbitrarily close points on FCurve (in time). @@ -709,7 +710,6 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu PointerRNA ptr; PropertyRNA *prop = NULL; - float cfra; int nbr_gaps = 0, i; if (gtd->mode == GP_STROKECONVERT_TIMING_NONE) @@ -739,6 +739,8 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu } if (gtd->mode == GP_STROKECONVERT_TIMING_LINEAR) { + float cfra; + /* Linear extrapolation! */ fcu->extend = FCURVE_EXTRAPOLATE_LINEAR; @@ -778,7 +780,7 @@ static void gp_stroke_path_animation(bContext *C, ReportList *reports, Curve *cu printf("Starting keying!\n"); } - gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, cfra, time_range, + gp_stroke_path_animation_add_keyframes(reports, ptr, prop, fcu, cu, gtd, time_range, nbr_gaps, tot_gaps_time); } From 6f32bece7faa16b9fbc5c794822c545c0ab51640 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Sun, 11 Nov 2012 18:28:45 +0000 Subject: [PATCH 112/118] revert muddle in changing jack in msvc instead apple --- CMakeLists.txt | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e162b0b1508..aa36995dfa6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1079,13 +1079,11 @@ elseif(WIN32) endif() if(WITH_JACK) - find_library(JACK_FRAMEWORK - NAMES jackmp + set(JACK_INCLUDE_DIRS + ${LIBDIR}/jack/include/jack + ${LIBDIR}/jack/include ) - set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers) - if(NOT JACK_FRAMEWORK) - set(WITH_JACK OFF) - endif() + set(JACK_LIBRARIES ${LIBDIR}/jack/lib/libjack.lib) endif() if(WITH_PYTHON) @@ -1358,10 +1356,13 @@ elseif(APPLE) endif() if(WITH_JACK) - set(JACK /usr/local) - set(JACK_INCLUDE_DIRS ${JACK}/include/jack) - set(JACK_LIBRARIES jack) - set(JACK_LIBPATH ${JACK}/lib) + find_library(JACK_FRAMEWORK + NAMES jackmp + ) + set(JACK_INCLUDE_DIRS ${JACK_FRAMEWORK}/headers) + if(NOT JACK_FRAMEWORK) + set(WITH_JACK OFF) + endif() endif() if(WITH_CODEC_SNDFILE) From 731e15be069d0d4231a93c3eb48b936f3b36179b Mon Sep 17 00:00:00 2001 From: Ton Roosendaal Date: Sun, 11 Nov 2012 18:33:35 +0000 Subject: [PATCH 113/118] Four fixes (own collection) - Screencast: stops working on window resize - crashes movie file output - Screencast now draws simple brush overlay to indicate mouse cursor. - Greasepencil now works again to use MMB for view rotates (and missed proper redraw signal for toolbar, at end of paint) --- .../blender/editors/gpencil/gpencil_paint.c | 8 ++- source/blender/editors/screen/screendump.c | 60 ++++++++++++++++++- .../editors/space_view3d/space_view3d.c | 2 +- .../blender/windowmanager/intern/wm_window.c | 5 ++ 4 files changed, 69 insertions(+), 6 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c index fa681ae2f70..fcead283033 100644 --- a/source/blender/editors/gpencil/gpencil_paint.c +++ b/source/blender/editors/gpencil/gpencil_paint.c @@ -1800,7 +1800,7 @@ static void gpencil_stroke_end(wmOperator *op) static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) { tGPsdata *p = op->customdata; - int estate = OPERATOR_RUNNING_MODAL; /* default exit state - we don't pass on events, GP is used with key-modifiers */ + int estate = OPERATOR_PASS_THROUGH; /* default exit state */ /* if (event->type == NDOF_MOTION) * return OPERATOR_PASS_THROUGH; @@ -1815,7 +1815,11 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, wmEvent *event) * in 3D space. */ - /* printf("\tGP - handle modal event...\n"); */ + /* we don't pass on key events, GP is used with key-modifiers - prevents Dkey to insert drivers */ + if (ISKEYBOARD(event->type)) + estate = OPERATOR_RUNNING_MODAL; + + //printf("\tGP - handle modal event...\n"); /* exit painting mode (and/or end current stroke) * NOTE: cannot do RIGHTMOUSE (as is standard for cancelling) as that would break polyline [#32647] diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index 0ecac5fc497..b8d620ae714 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -30,6 +30,7 @@ #include +#include #include "MEM_guardedalloc.h" @@ -52,6 +53,7 @@ #include "BKE_writeavi.h" #include "BIF_gl.h" +#include "BIF_glutil.h" #include "RNA_access.h" #include "RNA_define.h" @@ -278,6 +280,7 @@ void SCREEN_OT_screenshot(wmOperatorType *ot) typedef struct ScreenshotJob { Main *bmain; Scene *scene; + wmWindowManager *wm; unsigned int *dumprect; int x, y, dumpsx, dumpsy; short *stop; @@ -395,6 +398,54 @@ static void screenshot_startjob(void *sjv, short *stop, short *do_update, float BKE_report(&sj->reports, RPT_INFO, "Screencast job stopped"); } +/* Helper callback for drawing the cursor itself */ +static void screencast_draw_cursor(bContext *UNUSED(C), int x, int y, void *UNUSED(p_ptr)) +{ + + glPushMatrix(); + + glTranslatef((float)x, (float)y, 0.0f); + + + glEnable(GL_LINE_SMOOTH); + glEnable(GL_BLEND); + + glColor4ub(0, 0, 0, 32); + glutil_draw_filled_arc(0.0, M_PI * 2.0, 20, 40); + + glColor4ub(255, 255, 255, 128); + glutil_draw_lined_arc(0.0, M_PI * 2.0, 20, 40); + + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); + + glPopMatrix(); +} + +/* Turn brush cursor in 3D view on/off */ +static void screencast_cursor_toggle(wmWindowManager *wm, short enable) +{ + static void *cursor = NULL; + + if (cursor && !enable) { + /* clear cursor */ + WM_paint_cursor_end(wm, cursor); + cursor = NULL; + } + else if (enable) { + /* enable cursor */ + cursor = WM_paint_cursor_activate(wm, NULL, screencast_draw_cursor, NULL); + } +} + +static void screenshot_endjob(void *sjv) +{ + ScreenshotJob *sj = sjv; + + screencast_cursor_toggle(sj->wm, 0); +} + + static int screencast_exec(bContext *C, wmOperator *op) { bScreen *screen = CTX_wm_screen(C); @@ -418,15 +469,18 @@ static int screencast_exec(bContext *C, wmOperator *op) } sj->bmain = CTX_data_main(C); sj->scene = CTX_data_scene(C); - + sj->wm = CTX_wm_manager(C); + BKE_reports_init(&sj->reports, RPT_PRINT); /* setup job */ WM_jobs_customdata_set(wm_job, sj, screenshot_freejob); WM_jobs_timer(wm_job, 0.1, 0, NC_SCREEN | ND_SCREENCAST); - WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, NULL); + WM_jobs_callbacks(wm_job, screenshot_startjob, NULL, screenshot_updatejob, screenshot_endjob); - WM_jobs_start(CTX_wm_manager(C), wm_job); + WM_jobs_start(sj->wm, wm_job); + + screencast_cursor_toggle(sj->wm, 1); WM_event_add_notifier(C, NC_SCREEN | ND_SCREENCAST, screen); diff --git a/source/blender/editors/space_view3d/space_view3d.c b/source/blender/editors/space_view3d/space_view3d.c index 6818c78bbd6..3413377c7b9 100644 --- a/source/blender/editors/space_view3d/space_view3d.c +++ b/source/blender/editors/space_view3d/space_view3d.c @@ -945,7 +945,7 @@ static void view3d_buttons_area_listener(ARegion *ar, wmNotifier *wmn) ED_region_tag_redraw(ar); break; case NC_GPENCIL: - if (wmn->data == ND_DATA) + if (wmn->data == ND_DATA || wmn->action == NA_EDITED) ED_region_tag_redraw(ar); break; } diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 97052fd2fc6..a965cbf82d6 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -754,6 +754,11 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr state = GHOST_GetWindowState(win->ghostwin); win->windowstate = state; + /* stop screencast if resize */ + if (type == GHOST_kEventWindowSize) { + WM_jobs_stop(CTX_wm_manager(C), win->screen, NULL); + } + /* win32: gives undefined window size when minimized */ if (state != GHOST_kWindowStateMinimized) { GHOST_RectangleHandle client_rect; From 3dffa021d1425c51426fb77d698254ee4cf2e67c Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 11 Nov 2012 18:38:54 +0000 Subject: [PATCH 114/118] Fix for RNA soft values (confused with hard ones... tss). --- source/blender/editors/gpencil/gpencil_edit.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c index dbf04e772f5..1defcf65ae8 100644 --- a/source/blender/editors/gpencil/gpencil_edit.c +++ b/source/blender/editors/gpencil/gpencil_edit.c @@ -1567,8 +1567,8 @@ void GPENCIL_OT_convert(wmOperatorType *ot) ot->prop = RNA_def_enum(ot->srna, "type", prop_gpencil_convertmodes, 0, "Type", "Which type of curve to convert to"); RNA_def_boolean(ot->srna, "use_normalize_weights", TRUE, "Normalize Weight", "Normalize weight (set from stroke width)"); - RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 10.0f, "Radius Fac", - "Multiplier for the points' radii (set from stroke width)", 0.0f, 1000.0f); + RNA_def_float(ot->srna, "radius_multiplier", 1.0f, 0.0f, 1000.0f, "Radius Fac", + "Multiplier for the points' radii (set from stroke width)", 0.0f, 10.0f); RNA_def_boolean(ot->srna, "use_link_strokes", TRUE, "Link Strokes", "Whether to link strokes with zero-radius sections of curves"); prop = RNA_def_enum(ot->srna, "timing_mode", prop_gpencil_convert_timingmodes, GP_STROKECONVERT_TIMING_FULL, @@ -1583,13 +1583,13 @@ void GPENCIL_OT_convert(wmOperatorType *ot) prop = RNA_def_int(ot->srna, "end_frame", 250, 1, 100000, "End Frame", "The end frame of the path control curve (if Realtime is not set)", 1, 100000); RNA_def_property_update_runtime(prop, gp_convert_set_end_frame); - RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 1000.0f, "Gap Duration", + RNA_def_float(ot->srna, "gap_duration", 0.0f, 0.0f, 10000.0f, "Gap Duration", "Custom Gap mode: (Average) length of gaps, in frames " - "(note: realtime value, will be scaled if Realtime is not set)", 0.0f, 10000.0f); - RNA_def_float(ot->srna, "gap_randomness", 0.0f, 0.0f, 100.0f, "Gap Randomness", + "(note: realtime value, will be scaled if Realtime is not set)", 0.0f, 1000.0f); + RNA_def_float(ot->srna, "gap_randomness", 0.0f, 0.0f, 10000.0f, "Gap Randomness", "Custom Gap mode: Number of frames that gap lengths can vary", 0.0f, 1000.0f); - RNA_def_int(ot->srna, "seed", 0, 0, 100, "Random Seed", - "Custom Gap mode: Random generator seed", 0, 1000); + RNA_def_int(ot->srna, "seed", 0, 0, 1000, "Random Seed", + "Custom Gap mode: Random generator seed", 0, 100); /* Note: Internal use, this one will always be hidden by UI code... */ prop = RNA_def_boolean(ot->srna, "use_timing_data", FALSE, "Has Valid Timing", "Whether the converted grease pencil layer has valid timing data (internal use)"); From 13e474047bf6450392b078734f3ec9729bad1716 Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 11 Nov 2012 18:56:58 +0000 Subject: [PATCH 115/118] * Replace math.h with BLI_math.h, this fixes compile on windows. --- source/blender/editors/screen/screendump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/screen/screendump.c b/source/blender/editors/screen/screendump.c index b8d620ae714..ca85daadf3b 100644 --- a/source/blender/editors/screen/screendump.c +++ b/source/blender/editors/screen/screendump.c @@ -30,12 +30,12 @@ #include -#include #include "MEM_guardedalloc.h" #include "BLI_blenlib.h" #include "BLI_utildefines.h" +#include "BLI_math.h" #include "IMB_imbuf_types.h" #include "IMB_imbuf.h" From 0738284e32a76bd0d64534d0be44cb3b05145174 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Sun, 11 Nov 2012 19:46:36 +0000 Subject: [PATCH 116/118] =?UTF-8?q?Clen=20up=20of=20gettext=20stuff=20from?= =?UTF-8?q?=20scons=20scripts...=20Did=20not=20touch=20to=20buildbots=20on?= =?UTF-8?q?es,=20nor=20to=20iconv,=20as=20it=E2=80=99s=20still=20uncleare?= =?UTF-8?q?=20whether=20we=20can=20get=20rid=20of=20it=20:/?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build_files/scons/config/darwin-config.py | 5 ----- build_files/scons/config/freebsd7-config.py | 5 ----- build_files/scons/config/freebsd8-config.py | 5 ----- build_files/scons/config/freebsd9-config.py | 5 ----- build_files/scons/config/linux-config.py | 7 ------- build_files/scons/config/linuxcross-config.py | 5 ----- build_files/scons/config/win32-mingw-config.py | 5 ----- build_files/scons/config/win32-vc-config.py | 5 ----- build_files/scons/config/win64-mingw-config.py | 5 ----- build_files/scons/config/win64-vc-config.py | 5 ----- build_files/scons/tools/Blender.py | 5 ----- build_files/scons/tools/btools.py | 10 +--------- source/blender/blenfont/SConscript | 1 - 13 files changed, 1 insertion(+), 67 deletions(-) diff --git a/build_files/scons/config/darwin-config.py b/build_files/scons/config/darwin-config.py index 8511e9658c9..ea7d60a62eb 100644 --- a/build_files/scons/config/darwin-config.py +++ b/build_files/scons/config/darwin-config.py @@ -223,11 +223,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'intl' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/freebsd7-config.py b/build_files/scons/config/freebsd7-config.py index 412b08d895b..61358de12b4 100644 --- a/build_files/scons/config/freebsd7-config.py +++ b/build_files/scons/config/freebsd7-config.py @@ -77,11 +77,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = '/usr/local' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gettextlib' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = False WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/freebsd8-config.py b/build_files/scons/config/freebsd8-config.py index ece86f799c3..0f6c7f64786 100644 --- a/build_files/scons/config/freebsd8-config.py +++ b/build_files/scons/config/freebsd8-config.py @@ -77,11 +77,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = '/usr/local' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gettextlib' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = False WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/freebsd9-config.py b/build_files/scons/config/freebsd9-config.py index a31c6da90f0..c0df68f99ad 100644 --- a/build_files/scons/config/freebsd9-config.py +++ b/build_files/scons/config/freebsd9-config.py @@ -77,11 +77,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = '/usr/local' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gettextlib' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = False WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/linux-config.py b/build_files/scons/config/linux-config.py index 6160389a9ab..9bab4bc1dad 100644 --- a/build_files/scons/config/linux-config.py +++ b/build_files/scons/config/linux-config.py @@ -89,13 +89,6 @@ BF_ZLIB_LIB = 'z' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = '/usr' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gettextlib' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' -#WITH_BF_GETTEXT_STATIC = True -#BF_GETTEXT_LIB_STATIC = '${BF_GETTEXT}/lib/libgettextlib.a' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/linuxcross-config.py b/build_files/scons/config/linuxcross-config.py index 6866241793b..63264807720 100644 --- a/build_files/scons/config/linuxcross-config.py +++ b/build_files/scons/config/linuxcross-config.py @@ -83,11 +83,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gcc/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'intl' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = False WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/win32-mingw-config.py b/build_files/scons/config/win32-mingw-config.py index 29e7d8c0b1b..768722fac32 100644 --- a/build_files/scons/config/win32-mingw-config.py +++ b/build_files/scons/config/win32-mingw-config.py @@ -83,11 +83,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'intl' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_OPENJPEG = True BF_OPENJPEG = '#extern/libopenjpeg' BF_OPENJPEG_LIB = '' diff --git a/build_files/scons/config/win32-vc-config.py b/build_files/scons/config/win32-vc-config.py index dbb18177487..c093fdb4a99 100644 --- a/build_files/scons/config/win32-vc-config.py +++ b/build_files/scons/config/win32-vc-config.py @@ -87,11 +87,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gnu_gettext' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/config/win64-mingw-config.py b/build_files/scons/config/win64-mingw-config.py index 91206aa2e02..bca3df16289 100644 --- a/build_files/scons/config/win64-mingw-config.py +++ b/build_files/scons/config/win64-mingw-config.py @@ -80,11 +80,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'intl' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_OPENJPEG = True BF_OPENJPEG = '#extern/libopenjpeg' BF_OPENJPEG_LIB = '' diff --git a/build_files/scons/config/win64-vc-config.py b/build_files/scons/config/win64-vc-config.py index 45fef533a58..9d3f42f7c7b 100644 --- a/build_files/scons/config/win64-vc-config.py +++ b/build_files/scons/config/win64-vc-config.py @@ -83,11 +83,6 @@ BF_ZLIB_LIBPATH = '${BF_ZLIB}/lib' WITH_BF_INTERNATIONAL = True -BF_GETTEXT = LIBDIR + '/gettext' -BF_GETTEXT_INC = '${BF_GETTEXT}/include' -BF_GETTEXT_LIB = 'gnu_gettext' -BF_GETTEXT_LIBPATH = '${BF_GETTEXT}/lib' - WITH_BF_GAMEENGINE = True WITH_BF_PLAYER = True WITH_BF_OCEANSIM = True diff --git a/build_files/scons/tools/Blender.py b/build_files/scons/tools/Blender.py index eb646f27d53..7d7a32682cb 100644 --- a/build_files/scons/tools/Blender.py +++ b/build_files/scons/tools/Blender.py @@ -173,9 +173,6 @@ def setup_staticlibs(lenv): if lenv['WITH_BF_FFMPEG'] and lenv['WITH_BF_STATICFFMPEG']: statlibs += Split(lenv['BF_FFMPEG_LIB_STATIC']) if lenv['WITH_BF_INTERNATIONAL']: - libincs += Split(lenv['BF_GETTEXT_LIBPATH']) - if lenv['WITH_BF_GETTEXT_STATIC']: - statlibs += Split(lenv['BF_GETTEXT_LIB_STATIC']) if lenv['WITH_BF_FREETYPE_STATIC']: statlibs += Split(lenv['BF_FREETYPE_LIB_STATIC']) if lenv['WITH_BF_OPENAL']: @@ -252,8 +249,6 @@ def setup_syslibs(lenv): syslibs.append(lenv['BF_PYTHON_LIB']+'_d') else: syslibs.append(lenv['BF_PYTHON_LIB']) - if lenv['WITH_BF_INTERNATIONAL'] and not lenv['WITH_BF_GETTEXT_STATIC']: - syslibs += Split(lenv['BF_GETTEXT_LIB']) if lenv['WITH_BF_OPENAL']: if not lenv['WITH_BF_STATICOPENAL']: syslibs += Split(lenv['BF_OPENAL_LIB']) diff --git a/build_files/scons/tools/btools.py b/build_files/scons/tools/btools.py index 19652bb7851..90d3f578d98 100644 --- a/build_files/scons/tools/btools.py +++ b/build_files/scons/tools/btools.py @@ -116,7 +116,6 @@ def validate_arguments(args, bc): 'WITH_BF_TIFF', 'BF_TIFF', 'BF_TIFF_INC', 'BF_TIFF_LIB', 'BF_TIFF_LIBPATH', 'WITH_BF_STATICTIFF', 'BF_TIFF_LIB_STATIC', 'WITH_BF_ZLIB', 'BF_ZLIB', 'BF_ZLIB_INC', 'BF_ZLIB_LIB', 'BF_ZLIB_LIBPATH', 'WITH_BF_STATICZLIB', 'BF_ZLIB_LIB_STATIC', 'WITH_BF_INTERNATIONAL', - 'BF_GETTEXT', 'BF_GETTEXT_INC', 'BF_GETTEXT_LIB', 'WITH_BF_GETTEXT_STATIC', 'BF_GETTEXT_LIB_STATIC', 'BF_GETTEXT_LIBPATH', 'WITH_BF_ICONV', 'BF_ICONV', 'BF_ICONV_INC', 'BF_ICONV_LIB', 'BF_ICONV_LIBPATH', 'WITH_BF_GAMEENGINE', 'WITH_BF_BULLET', 'BF_BULLET', 'BF_BULLET_INC', 'BF_BULLET_LIB', @@ -381,15 +380,8 @@ def read_opts(env, cfg, args): ('BF_ZLIB_LIBPATH', 'ZLib library path', ''), ('BF_ZLIB_LIB_STATIC', 'ZLib static library', ''), - (BoolVariable('WITH_BF_INTERNATIONAL', 'Use Gettext if true', True)), + (BoolVariable('WITH_BF_INTERNATIONAL', 'Use Boost::locale if true', True)), - ('BF_GETTEXT', 'gettext base path', ''), - ('BF_GETTEXT_INC', 'gettext include path', ''), - ('BF_GETTEXT_LIB', 'gettext library', ''), - (BoolVariable('WITH_BF_GETTEXT_STATIC', 'Use static gettext library if true', False)), - ('BF_GETTEXT_LIB_STATIC', 'static gettext library', ''), - ('BF_GETTEXT_LIBPATH', 'gettext library path', ''), - (BoolVariable('WITH_BF_ICONV', 'Use iconv if true', True)), ('BF_ICONV', 'iconv base path', ''), ('BF_ICONV_INC', 'iconv include path', ''), diff --git a/source/blender/blenfont/SConscript b/source/blender/blenfont/SConscript index 91c9c6789cf..c0591c877ef 100644 --- a/source/blender/blenfont/SConscript +++ b/source/blender/blenfont/SConscript @@ -8,7 +8,6 @@ incs = '. intern #/intern/guardedalloc #/intern/locale ../blenkernel ../blenlib incs += ' ../makesdna ../makesrna ../imbuf ../editors/include' incs += ' #/extern/glew/include' incs += ' ' + env['BF_FREETYPE_INC'] -incs += ' ' + env['BF_GETTEXT_INC'] defs = ['GLEW_STATIC'] From 31fd76964127e9b9495f70c22786d4dbcce3944b Mon Sep 17 00:00:00 2001 From: Thomas Dinges Date: Sun, 11 Nov 2012 19:53:12 +0000 Subject: [PATCH 117/118] * Remove one last "gnu_gettext.dll" reference in scons. --- SConstruct | 4 ---- 1 file changed, 4 deletions(-) diff --git a/SConstruct b/SConstruct index 064ae0bc0b5..b7b27baae5a 100644 --- a/SConstruct +++ b/SConstruct @@ -819,10 +819,6 @@ else: if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'win64-vc', 'linuxcross'): dllsources = [] - if not env['OURPLATFORM'] in ('win32-mingw', 'linuxcross'): - # For MinGW and linuxcross static linking will be used - dllsources += ['${LCGDIR}/gettext/lib/gnu_gettext.dll'] - dllsources += ['${BF_ZLIB_LIBPATH}/zlib.dll'] # Used when linking to libtiff was dynamic # keep it here until compilation on all platform would be ok From fbc1cc712f281e1cf61f40d70f09f8479506e018 Mon Sep 17 00:00:00 2001 From: Jens Verwiebe Date: Sun, 11 Nov 2012 20:41:28 +0000 Subject: [PATCH 118/118] OSX: fix linking with new boost_locale --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index aa36995dfa6..d5c1b5c287f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1547,6 +1547,7 @@ elseif(APPLE) set(BOOST_LIBRARIES boost_date_time-mt boost_filesystem-mt boost_regex-mt boost_system-mt boost_thread-mt) if (WITH_INTERNATIONAL) list(APPEND BOOST_LIBRARIES boost_locale-mt) + set(PLATFORM_LINKFLAGS "${PLATFORM_LINKFLAGS} -liconv") # boost_locale needs it ! endif() set(BOOST_LIBPATH ${BOOST}/lib) set(BOOST_DEFINITIONS)