diff options
228 files changed, 4273 insertions, 2175 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f33bb73e607..80008e24d95 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1292,18 +1292,14 @@ elseif(WIN32) if(WITH_OPENCOLLADA) set(OPENCOLLADA ${LIBDIR}/opencollada) set(OPENCOLLADA_INCLUDE_DIRS - ${OPENCOLLADA}/include/COLLADAStreamWriter - ${OPENCOLLADA}/include/COLLADABaseUtils - ${OPENCOLLADA}/include/COLLADAFramework - ${OPENCOLLADA}/include/COLLADASaxFrameworkLoader - ${OPENCOLLADA}/include/GeneratedSaxParser + ${OPENCOLLADA}/include/opencollada/COLLADAStreamWriter + ${OPENCOLLADA}/include/opencollada/COLLADABaseUtils + ${OPENCOLLADA}/include/opencollada/COLLADAFramework + ${OPENCOLLADA}/include/opencollada/COLLADASaxFrameworkLoader + ${OPENCOLLADA}/include/opencollada/GeneratedSaxParser ) set(OPENCOLLADA_LIBPATH ${OPENCOLLADA}/lib/opencollada) - if(WITH_MINGW64) - set(OPENCOLLADA_LIBRARIES OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver pcre buffer ftoa xml) - else() - set(OPENCOLLADA_LIBRARIES OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver expat pcre buffer ftoa) - endif() + set(OPENCOLLADA_LIBRARIES OpenCOLLADAStreamWriter OpenCOLLADASaxFrameworkLoader OpenCOLLADAFramework OpenCOLLADABaseUtils GeneratedSaxParser UTF MathMLSolver buffer ftoa xml) set(PCRE_LIBRARIES pcre) endif() @@ -1416,8 +1412,8 @@ elseif(WIN32) LLVMX86Disassembler LLVMX86Info LLVMX86Utils LLVMipa LLVMipo LLVMCore) - #imagehelp is needed by LLVM 3.1 on MinGW, check lib\Support\Windows\Signals.inc - set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} -limagehlp") + #imagehelp is needed by LLVM 3.1 on MinGW, check lib\Support\Windows\Signals.inc + set(PLATFORM_LINKLIBS "${PLATFORM_LINKLIBS} -limagehlp") set(LLVM_STATIC YES) endif() diff --git a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp index c359c5ec3e2..408a4e56f1c 100644 --- a/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp +++ b/intern/audaspace/ffmpeg/AUD_FFMPEGReader.cpp @@ -88,7 +88,7 @@ int AUD_FFMPEGReader::decode(AVPacket& packet, AUD_Buffer& buffer) } } else - memcpy(((data_t*)buffer.getBuffer()) + buf_pos, frame->data[1], data_size); + memcpy(((data_t*)buffer.getBuffer()) + buf_pos, frame->data[0], data_size); buf_pos += data_size; } diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py index 039fd39fc7d..ac0a1d7bdb7 100644 --- a/intern/cycles/blender/addon/properties.py +++ b/intern/cycles/blender/addon/properties.py @@ -205,6 +205,13 @@ class CyclesRenderSettings(bpy.types.PropertyGroup): default=1, ) + cls.subsurface_samples = IntProperty( + name="Subsurface Samples", + description="Number of subsurface scattering samples to render for each AA sample", + min=1, max=10000, + default=1, + ) + cls.no_caustics = BoolProperty( name="No Caustics", description="Leave out caustics, resulting in a darker image with less noise", diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py index ee33bf6572a..d1d007079bb 100644 --- a/intern/cycles/blender/addon/ui.py +++ b/intern/cycles/blender/addon/ui.py @@ -83,6 +83,7 @@ class CyclesRender_PT_sampling(CyclesButtonsPanel, Panel): sub.prop(cscene, "transmission_samples", text="Transmission") sub.prop(cscene, "ao_samples", text="AO") sub.prop(cscene, "mesh_light_samples", text="Mesh Light") + sub.prop(cscene, "subsurface_samples", text="Subsurface") class CyclesRender_PT_light_paths(CyclesButtonsPanel, Panel): diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index b451764c347..7749f164b90 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -252,7 +252,6 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen else if (b_node.is_a(&RNA_ShaderNodeNormal)) { BL::Node::outputs_iterator out_it; b_node.outputs.begin(out_it); - BL::NodeSocket vec_sock(*out_it); NormalNode *norm = new NormalNode(); norm->direction = get_node_output_vector(b_node, "Normal"); @@ -302,6 +301,9 @@ static ShaderNode *add_node(Scene *scene, BL::BlendData b_data, BL::Scene b_scen else if (b_node.is_a(&RNA_ShaderNodeBsdfDiffuse)) { node = new DiffuseBsdfNode(); } + else if (b_node.is_a(&RNA_ShaderNodeSubsurfaceScattering)) { + node = new SubsurfaceScatteringNode(); + } else if (b_node.is_a(&RNA_ShaderNodeBsdfGlossy)) { BL::ShaderNodeBsdfGlossy b_glossy_node(b_node); GlossyBsdfNode *glossy = new GlossyBsdfNode(); diff --git a/intern/cycles/blender/blender_sync.cpp b/intern/cycles/blender/blender_sync.cpp index f6ff78ab2ac..721eaeefc08 100644 --- a/intern/cycles/blender/blender_sync.cpp +++ b/intern/cycles/blender/blender_sync.cpp @@ -19,7 +19,6 @@ #include "background.h" #include "camera.h" #include "film.h" -#include "../render/filter.h" #include "graph.h" #include "integrator.h" #include "light.h" @@ -197,6 +196,7 @@ void BlenderSync::sync_integrator() integrator->transmission_samples = get_int(cscene, "transmission_samples"); integrator->ao_samples = get_int(cscene, "ao_samples"); integrator->mesh_light_samples = get_int(cscene, "mesh_light_samples"); + integrator->subsurface_samples = get_int(cscene, "subsurface_samples"); integrator->progressive = get_boolean(cscene, "progressive"); if(integrator->modified(previntegrator)) @@ -213,18 +213,11 @@ void BlenderSync::sync_film() Film prevfilm = *film; film->exposure = get_float(cscene, "film_exposure"); + film->filter_type = (FilterType)RNA_enum_get(&cscene, "filter_type"); + film->filter_width = (film->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width"); if(film->modified(prevfilm)) film->tag_update(scene); - - Filter *filter = scene->filter; - Filter prevfilter = *filter; - - filter->filter_type = (FilterType)RNA_enum_get(&cscene, "filter_type"); - filter->filter_width = (filter->filter_type == FILTER_BOX)? 1.0f: get_float(cscene, "filter_width"); - - if(filter->modified(prevfilter)) - filter->tag_update(scene); } /* Render Layer */ diff --git a/intern/cycles/device/device_memory.h b/intern/cycles/device/device_memory.h index 3223ca91b9e..fd0bed33396 100644 --- a/intern/cycles/device/device_memory.h +++ b/intern/cycles/device/device_memory.h @@ -216,6 +216,14 @@ public: return mem; } + void copy_at(T *ptr, size_t offset, size_t size) + { + if(size > 0) { + size_t mem_size = size*data_elements*datatype_size(data_type); + memcpy(&data[0] + offset, ptr, mem_size); + } + } + void reference(T *ptr, size_t width, size_t height = 0) { data.clear(); diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index e83756b7c8a..fbaba1da094 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -42,6 +42,7 @@ set(SRC_HEADERS kernel_projection.h kernel_random.h kernel_shader.h + kernel_subsurface.h kernel_textures.h kernel_triangle.h kernel_types.h @@ -62,6 +63,7 @@ set(SRC_CLOSURE_HEADERS closure/bsdf_util.h closure/bsdf_ward.h closure/bsdf_westin.h + closure/bssrdf.h closure/emissive.h closure/volume.h ) diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index f26aefe7fd3..6403606c2df 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -29,6 +29,7 @@ #include "../closure/bsdf_ward.h" #endif #include "../closure/bsdf_westin.h" +#include "../closure/bssrdf.h" CCL_NAMESPACE_BEGIN diff --git a/intern/cycles/kernel/closure/bssrdf.h b/intern/cycles/kernel/closure/bssrdf.h new file mode 100644 index 00000000000..1327fbd011e --- /dev/null +++ b/intern/cycles/kernel/closure/bssrdf.h @@ -0,0 +1,154 @@ +/* + * Copyright 2013, Blender Foundation. + * + * 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. + */ + +#ifndef __KERNEL_BSSRDF_H__ +#define __KERNEL_BSSRDF_H__ + +CCL_NAMESPACE_BEGIN + +__device int bssrdf_setup(ShaderClosure *sc) +{ + if(sc->data0 < BSSRDF_MIN_RADIUS) { + /* revert to diffuse BSDF if radius too small */ + sc->data0 = 0.0f; + sc->data1 = 0.0f; + return bsdf_diffuse_setup(sc); + } + else { + /* radius + IOR params */ + sc->data0 = max(sc->data0, 0.0f); + sc->data1 = max(sc->data1, 1.0f); + sc->type = CLOSURE_BSSRDF_ID; + + return SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSSRDF; + } +} + +/* Simple Cubic BSSRDF falloff */ + +__device float bssrdf_cubic(float ld, float r) +{ + if(ld == 0.0f) + return (r == 0.0f)? 1.0f: 0.0f; + + return powf(ld - min(r, ld), 3.0f) * 4.0f/powf(ld, 4.0f); +} + +/* Original BSSRDF fallof function */ + +typedef struct BSSRDFParams { + float eta; /* index of refraction */ + float sigma_t_; /* reduced extinction coefficient */ + float sigma_tr; /* effective extinction coefficient */ + float Fdr; /* diffuse fresnel reflectance */ + float D; /* diffusion constant */ + float A; + float alpha_; /* reduced albedo */ + float zr; /* distance of virtual lightsource above surface */ + float zv; /* distance of virtual lightsource below surface */ + float ld; /* mean free path */ + float ro; /* diffuse reflectance */ +} BSSRDFParams; + +__device float bssrdf_reduced_albedo_Rd(float alpha_, float A, float ro) +{ + float sq; + + sq = sqrt(3.0f*(1.0f - alpha_)); + return (alpha_/2.0f)*(1.0f + expf((-4.0f/3.0f)*A*sq))*expf(-sq) - ro; +} + +__device float bssrdf_compute_reduced_albedo(float A, float ro) +{ + const float tolerance = 1e-8; + const int max_iteration_count = 20; + float d, fsub, xn_1 = 0.0f, xn = 1.0f, fxn, fxn_1; + int i; + + /* use secant method to compute reduced albedo using Rd function inverse + * with a given reflectance */ + fxn = bssrdf_reduced_albedo_Rd(xn, A, ro); + fxn_1 = bssrdf_reduced_albedo_Rd(xn_1, A, ro); + + for (i= 0; i < max_iteration_count; i++) { + fsub = (fxn - fxn_1); + if (fabsf(fsub) < tolerance) + break; + d = ((xn - xn_1)/fsub)*fxn; + if (fabsf(d) < tolerance) + break; + + xn_1 = xn; + fxn_1 = fxn; + xn = xn - d; + + if (xn > 1.0f) xn = 1.0f; + if (xn_1 > 1.0f) xn_1 = 1.0f; + + fxn = bssrdf_reduced_albedo_Rd(xn, A, ro); + } + + /* avoid division by zero later */ + if (xn <= 0.0f) + xn = 0.00001f; + + return xn; +} + +__device void bssrdf_setup_params(BSSRDFParams *ss, float refl, float radius, float ior) +{ + ss->eta = ior; + ss->Fdr = -1.440f/ior*ior + 0.710f/ior + 0.668f + 0.0636f*ior; + ss->A = (1.0f + ss->Fdr)/(1.0f - ss->Fdr); + ss->ld = radius; + ss->ro = min(refl, 0.999f); + + ss->alpha_ = bssrdf_compute_reduced_albedo(ss->A, ss->ro); + + ss->sigma_tr = 1.0f/ss->ld; + ss->sigma_t_ = ss->sigma_tr/sqrtf(3.0f*(1.0f - ss->alpha_)); + + ss->D = 1.0f/(3.0f*ss->sigma_t_); + + ss->zr = 1.0f/ss->sigma_t_; + ss->zv = ss->zr + 4.0f*ss->A*ss->D; +} + +/* exponential falloff function */ + +__device float bssrdf_original(const BSSRDFParams *ss, float r) +{ + if(ss->ld == 0.0f) + return (r == 0.0f)? 1.0f: 0.0f; + + float rr = r*r; + float sr, sv, Rdr, Rdv; + + sr = sqrt(rr + ss->zr*ss->zr); + sv = sqrt(rr + ss->zv*ss->zv); + + Rdr = ss->zr*(1.0f + ss->sigma_tr*sr)*expf(-ss->sigma_tr*sr)/(sr*sr*sr); + Rdv = ss->zv*(1.0f + ss->sigma_tr*sv)*expf(-ss->sigma_tr*sv)/(sv*sv*sv); + + return ss->alpha_*(1.0f/(4.0f*(float)M_PI))*(Rdr + Rdv); +} + +CCL_NAMESPACE_END + +#endif /* __KERNEL_BSSRDF_H__ */ + diff --git a/intern/cycles/kernel/kernel_bvh.h b/intern/cycles/kernel/kernel_bvh.h index 2b9ebf35d0c..b44e1194672 100644 --- a/intern/cycles/kernel/kernel_bvh.h +++ b/intern/cycles/kernel/kernel_bvh.h @@ -923,6 +923,330 @@ __device_inline bool scene_intersect(KernelGlobals *kg, const Ray *ray, const ui #endif } +/* Special ray intersection routines for subsurface scattering. In that case we + * only want to intersect with primitives in the same object, and if case of + * multiple hits we pick a single random primitive as the intersection point. */ + +__device_inline void bvh_triangle_intersect_subsurface(KernelGlobals *kg, Intersection *isect, + float3 P, float3 idir, int object, int triAddr, float tmax, int *num_hits, float subsurface_random) +{ + /* compute and check intersection t-value */ + float4 v00 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+0); + float4 v11 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+1); + float3 dir = 1.0f/idir; + + float Oz = v00.w - P.x*v00.x - P.y*v00.y - P.z*v00.z; + float invDz = 1.0f/(dir.x*v00.x + dir.y*v00.y + dir.z*v00.z); + float t = Oz * invDz; + + if(t > 0.0f && t < tmax) { + /* compute and check barycentric u */ + float Ox = v11.w + P.x*v11.x + P.y*v11.y + P.z*v11.z; + float Dx = dir.x*v11.x + dir.y*v11.y + dir.z*v11.z; + float u = Ox + t*Dx; + + if(u >= 0.0f) { + /* compute and check barycentric v */ + float4 v22 = kernel_tex_fetch(__tri_woop, triAddr*TRI_NODE_SIZE+2); + float Oy = v22.w + P.x*v22.x + P.y*v22.y + P.z*v22.z; + float Dy = dir.x*v22.x + dir.y*v22.y + dir.z*v22.z; + float v = Oy + t*Dy; + + if(v >= 0.0f && u + v <= 1.0f) { + (*num_hits)++; + + if(subsurface_random * (*num_hits) <= 1.0f) { + /* record intersection */ + isect->prim = triAddr; + isect->object = object; + isect->u = u; + isect->v = v; + isect->t = t; + } + } + } + } +} + +__device_inline int bvh_intersect_subsurface(KernelGlobals *kg, const Ray *ray, Intersection *isect, int subsurface_object, float subsurface_random) +{ + /* traversal stack in CUDA thread-local memory */ + int traversalStack[BVH_STACK_SIZE]; + traversalStack[0] = ENTRYPOINT_SENTINEL; + + /* traversal variables in registers */ + int stackPtr = 0; + int nodeAddr = kernel_data.bvh.root; + + /* ray parameters in registers */ + const float tmax = ray->t; + float3 P = ray->P; + float3 idir = bvh_inverse_direction(ray->D); + int object = ~0; + + int num_hits = 0; + + isect->t = tmax; + isect->object = ~0; + isect->prim = ~0; + isect->u = 0.0f; + isect->v = 0.0f; + + /* traversal loop */ + do { + do + { + /* traverse internal nodes */ + while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) + { + bool traverseChild0, traverseChild1, closestChild1; + int nodeAddrChild1; + + bvh_node_intersect(kg, &traverseChild0, &traverseChild1, + &closestChild1, &nodeAddr, &nodeAddrChild1, + P, idir, isect->t, ~0, nodeAddr); + + if(traverseChild0 != traverseChild1) { + /* one child was intersected */ + if(traverseChild1) { + nodeAddr = nodeAddrChild1; + } + } + else { + if(!traverseChild0) { + /* neither child was intersected */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + else { + /* both children were intersected, push the farther one */ + if(closestChild1) { + int tmp = nodeAddr; + nodeAddr = nodeAddrChild1; + nodeAddrChild1 = tmp; + } + + ++stackPtr; + traversalStack[stackPtr] = nodeAddrChild1; + } + } + } + + /* if node is leaf, fetch triangle list */ + if(nodeAddr < 0) { + float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1)); + int primAddr = __float_as_int(leaf.x); + +#ifdef __INSTANCING__ + if(primAddr >= 0) { +#endif + int primAddr2 = __float_as_int(leaf.y); + + /* pop */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + + /* primitive intersection */ + while(primAddr < primAddr2) { + /* only primitives from the same object */ + uint tri_object = (object == ~0)? kernel_tex_fetch(__prim_object, primAddr): object; + + if(tri_object == subsurface_object) { + /* intersect ray against primitive */ +#ifdef __HAIR__ + uint segment = kernel_tex_fetch(__prim_segment, primAddr); + if(segment == ~0) /* ignore hair for sss */ +#endif + bvh_triangle_intersect_subsurface(kg, isect, P, idir, object, primAddr, tmax, &num_hits, subsurface_random); + } + + primAddr++; + } +#ifdef __INSTANCING__ + } + else { + /* instance push */ + if(subsurface_object == kernel_tex_fetch(__prim_object, -primAddr-1)) { + object = subsurface_object; + bvh_instance_push(kg, object, ray, &P, &idir, &isect->t, tmax); + + ++stackPtr; + traversalStack[stackPtr] = ENTRYPOINT_SENTINEL; + + nodeAddr = kernel_tex_fetch(__object_node, object); + } + else { + /* pop */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + } +#endif + } + } while(nodeAddr != ENTRYPOINT_SENTINEL); + +#ifdef __INSTANCING__ + if(stackPtr >= 0) { + kernel_assert(object != ~0); + + /* instance pop */ + bvh_instance_pop(kg, object, ray, &P, &idir, &isect->t, tmax); + object = ~0; + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } +#endif + } while(nodeAddr != ENTRYPOINT_SENTINEL); + + return num_hits; +} + +#ifdef __OBJECT_MOTION__ +__device bool bvh_intersect_motion_subsurface(KernelGlobals *kg, const Ray *ray, Intersection *isect, int subsurface_object, float subsurface_random) +{ + /* traversal stack in CUDA thread-local memory */ + int traversalStack[BVH_STACK_SIZE]; + traversalStack[0] = ENTRYPOINT_SENTINEL; + + /* traversal variables in registers */ + int stackPtr = 0; + int nodeAddr = kernel_data.bvh.root; + + /* ray parameters in registers */ + const float tmax = ray->t; + float3 P = ray->P; + float3 idir = bvh_inverse_direction(ray->D); + int object = ~0; + + int num_hits = 0; + + Transform ob_tfm; + + isect->t = tmax; + isect->object = ~0; + isect->prim = ~0; + isect->u = 0.0f; + isect->v = 0.0f; + + /* traversal loop */ + do { + do + { + /* traverse internal nodes */ + while(nodeAddr >= 0 && nodeAddr != ENTRYPOINT_SENTINEL) + { + bool traverseChild0, traverseChild1, closestChild1; + int nodeAddrChild1; + + bvh_node_intersect(kg, &traverseChild0, &traverseChild1, + &closestChild1, &nodeAddr, &nodeAddrChild1, + P, idir, isect->t, ~0, nodeAddr); + + if(traverseChild0 != traverseChild1) { + /* one child was intersected */ + if(traverseChild1) { + nodeAddr = nodeAddrChild1; + } + } + else { + if(!traverseChild0) { + /* neither child was intersected */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + else { + /* both children were intersected, push the farther one */ + if(closestChild1) { + int tmp = nodeAddr; + nodeAddr = nodeAddrChild1; + nodeAddrChild1 = tmp; + } + + ++stackPtr; + traversalStack[stackPtr] = nodeAddrChild1; + } + } + } + + /* if node is leaf, fetch triangle list */ + if(nodeAddr < 0) { + float4 leaf = kernel_tex_fetch(__bvh_nodes, (-nodeAddr-1)*BVH_NODE_SIZE+(BVH_NODE_SIZE-1)); + int primAddr = __float_as_int(leaf.x); + + if(primAddr >= 0) { + int primAddr2 = __float_as_int(leaf.y); + + /* pop */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + + /* primitive intersection */ + while(primAddr < primAddr2) { + /* only primitives from the same object */ + uint tri_object = (object == ~0)? kernel_tex_fetch(__prim_object, primAddr): object; + + if(tri_object == subsurface_object) { + /* intersect ray against primitive */ +#ifdef __HAIR__ + uint segment = kernel_tex_fetch(__prim_segment, primAddr); + if(segment == ~0) /* ignore hair for sss */ +#endif + bvh_triangle_intersect_subsurface(kg, isect, P, idir, object, primAddr, tmax, &num_hits, subsurface_random); + } + + primAddr++; + } + } + else { + /* instance push */ + if(subsurface_object == kernel_tex_fetch(__prim_object, -primAddr-1)) { + object = subsurface_object; + object = kernel_tex_fetch(__prim_object, -primAddr-1); + bvh_instance_motion_push(kg, object, ray, &P, &idir, &isect->t, &ob_tfm, tmax); + + ++stackPtr; + traversalStack[stackPtr] = ENTRYPOINT_SENTINEL; + + nodeAddr = kernel_tex_fetch(__object_node, object); + } + else { + /* pop */ + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + } + } + } while(nodeAddr != ENTRYPOINT_SENTINEL); + + if(stackPtr >= 0) { + kernel_assert(object != ~0); + + /* instance pop */ + bvh_instance_motion_pop(kg, object, ray, &P, &idir, &isect->t, &ob_tfm, tmax); + object = ~0; + nodeAddr = traversalStack[stackPtr]; + --stackPtr; + } + } while(nodeAddr != ENTRYPOINT_SENTINEL); + + return num_hits; +} +#endif + +__device_inline int scene_intersect_subsurface(KernelGlobals *kg, const Ray *ray, Intersection *isect, int subsurface_object, float subsurface_random) +{ +#ifdef __OBJECT_MOTION__ + if(kernel_data.bvh.have_motion) + return bvh_intersect_motion_subsurface(kg, ray, isect, subsurface_object, subsurface_random); + else + return bvh_intersect_subsurface(kg, ray, isect, subsurface_object, subsurface_random); +#else + return bvh_intersect_subsurface(kg, ray, isect, subsurface_object, subsurface_random); +#endif +} + +/* Ray offset to avoid self intersection */ + __device_inline float3 ray_offset(float3 P, float3 Ng) { #ifdef __INTERSECTION_REFINE__ @@ -971,6 +1295,10 @@ __device_inline float3 ray_offset(float3 P, float3 Ng) #endif } +/* Refine triangle intersection to more precise hit point. For rays that travel + * far the precision is often not so good, this reintersects the primitive from + * a closer distance. */ + __device_inline float3 bvh_triangle_refine(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray) { float3 P = ray->P; diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h index 02f64cd649a..694ef8bd01d 100644 --- a/intern/cycles/kernel/kernel_camera.h +++ b/intern/cycles/kernel/kernel_camera.h @@ -53,7 +53,7 @@ __device void camera_sample_perspective(KernelGlobals *kg, float raster_x, float /* compute point on plane of focus */ float ft = kernel_data.cam.focaldistance/ray->D.z; - float3 Pfocus = ray->P + ray->D*ft; + float3 Pfocus = ray->D*ft; /* update ray for effect of lens */ ray->P = make_float3(lensuv.x, lensuv.y, 0.0f); @@ -112,11 +112,13 @@ __device void camera_sample_orthographic(KernelGlobals *kg, float raster_x, floa /* compute point on plane of focus */ float ft = kernel_data.cam.focaldistance/ray->D.z; - float3 Pfocus = ray->P + ray->D*ft; + float3 Pfocus = ray->D*ft; /* update ray for effect of lens */ ray->P = make_float3(lensuv.x, lensuv.y, 0.0f); ray->D = normalize(Pfocus - ray->P); + + ray->P += Pcamera; } /* transform ray from camera to world */ @@ -224,8 +226,9 @@ __device void camera_sample(KernelGlobals *kg, int x, int y, float filter_u, flo float lens_u, float lens_v, float time, Ray *ray) { /* pixel filter */ - float raster_x = x + kernel_tex_interp(__filter_table, filter_u, FILTER_TABLE_SIZE); - float raster_y = y + kernel_tex_interp(__filter_table, filter_v, FILTER_TABLE_SIZE); + int filter_table_offset = kernel_data.film.filter_table_offset; + float raster_x = x + lookup_table_read(kg, filter_u, filter_table_offset, FILTER_TABLE_SIZE); + float raster_y = y + lookup_table_read(kg, filter_v, filter_table_offset, FILTER_TABLE_SIZE); #ifdef __CAMERA_MOTION__ /* motion blur */ diff --git a/intern/cycles/kernel/kernel_compat_cpu.h b/intern/cycles/kernel/kernel_compat_cpu.h index 01bb78e8e1c..9972a63bfbb 100644 --- a/intern/cycles/kernel/kernel_compat_cpu.h +++ b/intern/cycles/kernel/kernel_compat_cpu.h @@ -57,19 +57,6 @@ template<typename T> struct texture { } #endif - float interp(float x, int size) - { - kernel_assert(size == width); - - x = clamp(x, 0.0f, 1.0f)*width; - - int index = min((int)x, width-1); - int nindex = min(index+1, width-1); - float t = x - index; - - return (1.0f - t)*data[index] + t*data[nindex]; - } - T *data; int width; }; @@ -157,7 +144,7 @@ typedef texture_image<uchar4> texture_image_uchar4; #define kernel_tex_fetch(tex, index) (kg->tex.fetch(index)) #define kernel_tex_fetch_m128(tex, index) (kg->tex.fetch_m128(index)) #define kernel_tex_fetch_m128i(tex, index) (kg->tex.fetch_m128i(index)) -#define kernel_tex_interp(tex, t, size) (kg->tex.interp(t, size)) +#define kernel_tex_lookup(tex, t, offset, size) (kg->tex.lookup(t, offset, size)) #define kernel_tex_image_interp(tex, x, y) ((tex < MAX_FLOAT_IMAGES) ? kg->texture_float_images[tex].interp(x, y) : kg->texture_byte_images[tex - MAX_FLOAT_IMAGES].interp(x, y)) #define kernel_data (kg->__data) diff --git a/intern/cycles/kernel/kernel_compat_cuda.h b/intern/cycles/kernel/kernel_compat_cuda.h index 9fd065c3cda..a11f8f403cd 100644 --- a/intern/cycles/kernel/kernel_compat_cuda.h +++ b/intern/cycles/kernel/kernel_compat_cuda.h @@ -58,7 +58,6 @@ typedef texture<uchar4, 2, cudaReadModeNormalizedFloat> texture_image_uchar4; /* Macros to handle different memory storage on different devices */ #define kernel_tex_fetch(t, index) tex1Dfetch(t, index) -#define kernel_tex_interp(t, x, size) tex1D(t, x) #define kernel_tex_image_interp(t, x, y) tex2D(t, x, y) #define kernel_data __data diff --git a/intern/cycles/kernel/kernel_compat_opencl.h b/intern/cycles/kernel/kernel_compat_opencl.h index abb2f094f5c..999820891b2 100644 --- a/intern/cycles/kernel/kernel_compat_opencl.h +++ b/intern/cycles/kernel/kernel_compat_opencl.h @@ -45,18 +45,6 @@ /* no assert in opencl */ #define kernel_assert(cond) -/* manual implementation of interpolated 1D lookup */ -__device float kernel_tex_interp_(__global float *data, int width, float x) -{ - x = clamp(x, 0.0f, 1.0f)*width; - - int index = min((int)x, width-1); - int nindex = min(index+1, width-1); - float t = x - index; - - return (1.0f - t)*data[index] + t*data[nindex]; -} - /* make_type definitions with opencl style element initializers */ #ifdef make_float2 #undef make_float2 @@ -114,7 +102,7 @@ __device float kernel_tex_interp_(__global float *data, int width, float x) /* data lookup defines */ #define kernel_data (*kg->data) -#define kernel_tex_interp(t, x, size) kernel_tex_interp_(kg->t, size, x) +#define kernel_tex_lookup(t, x, offset, size) kernel_tex_lookup_(kg->t, offset, size, x) #define kernel_tex_fetch(t, index) kg->t[index] /* define NULL */ diff --git a/intern/cycles/kernel/kernel_displace.h b/intern/cycles/kernel/kernel_displace.h index fc2be342e02..5f95e0c2e3b 100644 --- a/intern/cycles/kernel/kernel_displace.h +++ b/intern/cycles/kernel/kernel_displace.h @@ -66,8 +66,6 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float4 *ou out = shader_eval_background(kg, &sd, flag, SHADER_CONTEXT_MAIN); } - shader_release(kg, &sd); - /* write output */ output[i] = make_float4(out.x, out.y, out.z, 0.0f); } diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 9787af535bb..7d7494657e2 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -69,8 +69,6 @@ __device_noinline float3 direct_emissive_eval(KernelGlobals *kg, float rando, eval *= ls->eval_fac; - shader_release(kg, &sd); - return eval; } @@ -207,7 +205,6 @@ __device_noinline float3 indirect_background(KernelGlobals *kg, Ray *ray, int pa ShaderData sd; shader_setup_from_background(kg, &sd, ray); float3 L = shader_eval_background(kg, &sd, path_flag, SHADER_CONTEXT_EMISSION); - shader_release(kg, &sd); #ifdef __BACKGROUND_MIS__ /* check if background light exists or if we should skip pdf */ diff --git a/intern/cycles/kernel/kernel_globals.h b/intern/cycles/kernel/kernel_globals.h index 529b7b8768f..abf1f5b4cb0 100644 --- a/intern/cycles/kernel/kernel_globals.h +++ b/intern/cycles/kernel/kernel_globals.h @@ -88,5 +88,39 @@ typedef struct KernelGlobals { #endif +/* Interpolated lookup table access */ + +__device float lookup_table_read(KernelGlobals *kg, float x, int offset, int size) +{ + x = clamp(x, 0.0f, 1.0f)*(size-1); + + int index = min((int)x, size-1); + int nindex = min(index+1, size-1); + float t = x - index; + + float data0 = kernel_tex_fetch(__lookup_table, index + offset); + if(t == 0.0f) + return data0; + + float data1 = kernel_tex_fetch(__lookup_table, nindex + offset); + return (1.0f - t)*data0 + t*data1; +} + +__device float lookup_table_read_2D(KernelGlobals *kg, float x, float y, int offset, int xsize, int ysize) +{ + y = clamp(y, 0.0f, 1.0f)*(ysize-1); + + int index = min((int)y, ysize-1); + int nindex = min(index+1, ysize-1); + float t = y - index; + + float data0 = lookup_table_read(kg, x, offset + xsize*index, xsize); + if(t == 0.0f) + return data0; + + float data1 = lookup_table_read(kg, x, offset + xsize*nindex, xsize); + return (1.0f - t)*data0 + t*data1; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 865ba7ca676..7aa1ec365b7 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -37,6 +37,10 @@ #include "kernel_random.h" #include "kernel_passes.h" +#ifdef __SUBSURFACE__ +#include "kernel_subsurface.h" +#endif + CCL_NAMESPACE_BEGIN typedef struct PathState { @@ -149,7 +153,7 @@ __device_inline float path_state_terminate_probability(KernelGlobals *kg, PathSt } /* probalistic termination */ - return average(throughput); + return average(throughput); /* todo: try using max here */ } __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ray, float3 *shadow) @@ -212,8 +216,6 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra if(ray->t != FLT_MAX) ray->D = normalize_len(Pend - ray->P, &ray->t); - shader_release(kg, &sd); - bounce++; } } @@ -323,10 +325,8 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, L_transparent += average(holdout_weight*throughput); } - if(sd.flag & SD_HOLDOUT_MASK) { - shader_release(kg, &sd); + if(sd.flag & SD_HOLDOUT_MASK) break; - } } #endif @@ -345,13 +345,29 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, float probability = path_state_terminate_probability(kg, &state, throughput); float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE); - if(terminate >= probability) { - shader_release(kg, &sd); + if(terminate >= probability) break; - } throughput /= probability; +#ifdef __SUBSURFACE__ + /* bssrdf scatter to a different location on the same object, replacing + * the closures with a diffuse BSDF */ + if(sd.flag & SD_BSSRDF) { + float bssrdf_probability; + ShaderClosure *sc = subsurface_scatter_pick_closure(kg, &sd, &bssrdf_probability); + + /* modify throughput for picking bssrdf or bsdf */ + throughput *= bssrdf_probability; + + /* do bssrdf scatter step if we picked a bssrdf closure */ + if(sc) { + uint lcg_state = lcg_init(rbsdf); + subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, false); + } + } +#endif + #ifdef __AO__ /* ambient occlusion */ if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { @@ -415,10 +431,8 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, #endif /* no BSDF? we can stop here */ - if(!(sd.flag & SD_BSDF)) { - shader_release(kg, &sd); + if(!(sd.flag & SD_BSDF)) break; - } /* sample BSDF */ float bsdf_pdf; @@ -432,8 +446,6 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval, &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf); - shader_release(kg, &sd); - if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) break; @@ -481,7 +493,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, #ifdef __NON_PROGRESSIVE__ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray ray, __global float *buffer, - float3 throughput, float throughput_normalize, + float3 throughput, float num_samples_adjust, float min_ray_pdf, float ray_pdf, PathState state, int rng_offset, PathRadiance *L) { #ifdef __LAMP_MIS__ @@ -554,16 +566,32 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray /* path termination. this is a strange place to put the termination, it's * mainly due to the mixed in MIS that we use. gives too many unneeded * shader evaluations, only need emission if we are going to terminate */ - float probability = path_state_terminate_probability(kg, &state, throughput*throughput_normalize); + float probability = path_state_terminate_probability(kg, &state, throughput*num_samples_adjust); float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE); - if(terminate >= probability) { - shader_release(kg, &sd); + if(terminate >= probability) break; - } throughput /= probability; +#ifdef __SUBSURFACE__ + /* bssrdf scatter to a different location on the same object, replacing + * the closures with a diffuse BSDF */ + if(sd.flag & SD_BSSRDF) { + float bssrdf_probability; + ShaderClosure *sc = subsurface_scatter_pick_closure(kg, &sd, &bssrdf_probability); + + /* modify throughput for picking bssrdf or bsdf */ + throughput *= bssrdf_probability; + + /* do bssrdf scatter step if we picked a bssrdf closure */ + if(sc) { + uint lcg_state = lcg_init(rbsdf); + subsurface_scatter_step(kg, &sd, state.flag, sc, &lcg_state, false); + } + } +#endif + #ifdef __AO__ /* ambient occlusion */ if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { @@ -628,10 +656,8 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray #endif /* no BSDF? we can stop here */ - if(!(sd.flag & SD_BSDF)) { - shader_release(kg, &sd); + if(!(sd.flag & SD_BSDF)) break; - } /* sample BSDF */ float bsdf_pdf; @@ -645,8 +671,6 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray label = shader_bsdf_sample(kg, &sd, bsdf_u, bsdf_v, &bsdf_eval, &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf); - shader_release(kg, &sd); - if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) break; @@ -676,6 +700,193 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray } } +__device_noinline void kernel_path_non_progressive_lighting(KernelGlobals *kg, RNG *rng, int sample, + ShaderData *sd, float3 throughput, float num_samples_adjust, + float min_ray_pdf, float ray_pdf, PathState state, + int rng_offset, PathRadiance *L, __global float *buffer) +{ +#ifdef __AO__ + /* ambient occlusion */ + if(kernel_data.integrator.use_ambient_occlusion || (sd->flag & SD_AO)) { + int num_samples = ceil(kernel_data.integrator.ao_samples*num_samples_adjust); + float num_samples_inv = num_samples_adjust/num_samples; + float ao_factor = kernel_data.background.ao_factor; + float3 ao_N; + float3 ao_bsdf = shader_bsdf_ao(kg, sd, ao_factor, &ao_N); + + for(int j = 0; j < num_samples; j++) { + /* todo: solve correlation */ + float bsdf_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_U); + float bsdf_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_V); + + float3 ao_D; + float ao_pdf; + + sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); + + if(dot(sd->Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { + Ray light_ray; + float3 ao_shadow; + + light_ray.P = ray_offset(sd->P, sd->Ng); + light_ray.D = ao_D; + light_ray.t = kernel_data.background.ao_distance; +#ifdef __OBJECT_MOTION__ + light_ray.time = sd->time; +#endif + + if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) + path_radiance_accum_ao(L, throughput*num_samples_inv, ao_bsdf, ao_shadow, state.bounce); + } + } + } +#endif + + +#ifdef __EMISSION__ + /* sample illumination from lights to find path contribution */ + if(sd->flag & SD_BSDF_HAS_EVAL) { + Ray light_ray; + BsdfEval L_light; + bool is_lamp; + +#ifdef __OBJECT_MOTION__ + light_ray.time = sd->time; +#endif + + /* lamp sampling */ + for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) { + int num_samples = ceil(num_samples_adjust*light_select_num_samples(kg, i)); + float num_samples_inv = num_samples_adjust/(num_samples*kernel_data.integrator.num_all_lights); + + if(kernel_data.integrator.pdf_triangles != 0.0f) + num_samples_inv *= 0.5f; + + for(int j = 0; j < num_samples; j++) { + float light_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_U); + float light_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_V); + + if(direct_emission(kg, sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) { + /* trace shadow ray */ + float3 shadow; + + if(!shadow_blocked(kg, &state, &light_ray, &shadow)) { + /* accumulate */ + path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state.bounce, is_lamp); + } + } + } + } + + /* mesh light sampling */ + if(kernel_data.integrator.pdf_triangles != 0.0f) { + int num_samples = ceil(num_samples_adjust*kernel_data.integrator.mesh_light_samples); + float num_samples_inv = num_samples_adjust/num_samples; + + if(kernel_data.integrator.num_all_lights) + num_samples_inv *= 0.5f; + + for(int j = 0; j < num_samples; j++) { + float light_t = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT); + float light_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_U); + float light_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_V); + + /* only sample triangle lights */ + if(kernel_data.integrator.num_all_lights) + light_t = 0.5f*light_t; + + if(direct_emission(kg, sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) { + /* trace shadow ray */ + float3 shadow; + + if(!shadow_blocked(kg, &state, &light_ray, &shadow)) { + /* accumulate */ + path_radiance_accum_light(L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state.bounce, is_lamp); + } + } + } + } + } +#endif + + for(int i = 0; i< sd->num_closure; i++) { + const ShaderClosure *sc = &sd->closure[i]; + + if(!CLOSURE_IS_BSDF(sc->type)) + continue; + /* transparency is not handled here, but in outer loop */ + if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) + continue; + + int num_samples; + + if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) + num_samples = kernel_data.integrator.diffuse_samples; + else if(CLOSURE_IS_BSDF_GLOSSY(sc->type)) + num_samples = kernel_data.integrator.glossy_samples; + else + num_samples = kernel_data.integrator.transmission_samples; + + num_samples = ceil(num_samples_adjust*num_samples); + + float num_samples_inv = num_samples_adjust/num_samples; + + for(int j = 0; j < num_samples; j++) { + /* sample BSDF */ + float bsdf_pdf; + BsdfEval bsdf_eval; + float3 bsdf_omega_in; + differential3 bsdf_domega_in; + float bsdf_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_U); + float bsdf_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_V); + int label; + + label = shader_bsdf_sample_closure(kg, sd, sc, bsdf_u, bsdf_v, &bsdf_eval, + &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf); + + if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) + continue; + + /* modify throughput */ + float3 tp = throughput; + path_radiance_bsdf_bounce(L, &tp, &bsdf_eval, bsdf_pdf, state.bounce, label); + + /* set labels */ + float min_ray_pdf = FLT_MAX; + + if(!(label & LABEL_TRANSPARENT)) + min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf); + + /* modify path state */ + PathState ps = state; + path_state_next(kg, &ps, label); + + /* setup ray */ + Ray bsdf_ray; + + bsdf_ray.P = ray_offset(sd->P, (label & LABEL_TRANSMIT)? -sd->Ng: sd->Ng); + bsdf_ray.D = bsdf_omega_in; + bsdf_ray.t = FLT_MAX; +#ifdef __RAY_DIFFERENTIALS__ + bsdf_ray.dP = sd->dP; + bsdf_ray.dD = bsdf_domega_in; +#endif +#ifdef __OBJECT_MOTION__ + bsdf_ray.time = sd->time; +#endif + + kernel_path_indirect(kg, rng, sample*num_samples + j, bsdf_ray, buffer, + tp*num_samples_inv, num_samples, + min_ray_pdf, bsdf_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, L); + + /* for render passes, sum and reset indirect light pass variables + * for the next samples */ + path_radiance_sum_indirect(L); + path_radiance_reset_indirect(L); + } + } +} + __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sample, Ray ray, __global float *buffer) { /* initialize */ @@ -740,10 +951,8 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam L_transparent += average(holdout_weight*throughput); } - if(sd.flag & SD_HOLDOUT_MASK) { - shader_release(kg, &sd); + if(sd.flag & SD_HOLDOUT_MASK) break; - } } #endif @@ -763,195 +972,47 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam float probability = path_state_terminate_probability(kg, &state, throughput); float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE); - if(terminate >= probability) { - shader_release(kg, &sd); + if(terminate >= probability) break; - } throughput /= probability; } -#ifdef __AO__ - /* ambient occlusion */ - if(kernel_data.integrator.use_ambient_occlusion || (sd.flag & SD_AO)) { - int num_samples = kernel_data.integrator.ao_samples; - float num_samples_inv = 1.0f/num_samples; - float ao_factor = kernel_data.background.ao_factor; - float3 ao_N; - float3 ao_bsdf = shader_bsdf_ao(kg, &sd, ao_factor, &ao_N); - - for(int j = 0; j < num_samples; j++) { - /* todo: solve correlation */ - float bsdf_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_U); - float bsdf_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_V); - - float3 ao_D; - float ao_pdf; - - sample_cos_hemisphere(ao_N, bsdf_u, bsdf_v, &ao_D, &ao_pdf); - - if(dot(sd.Ng, ao_D) > 0.0f && ao_pdf != 0.0f) { - Ray light_ray; - float3 ao_shadow; - - light_ray.P = ray_offset(sd.P, sd.Ng); - light_ray.D = ao_D; - light_ray.t = kernel_data.background.ao_distance; -#ifdef __OBJECT_MOTION__ - light_ray.time = sd.time; -#endif - - if(!shadow_blocked(kg, &state, &light_ray, &ao_shadow)) - path_radiance_accum_ao(&L, throughput*num_samples_inv, ao_bsdf, ao_shadow, state.bounce); - } - } - } -#endif - -#ifdef __EMISSION__ - /* sample illumination from lights to find path contribution */ - if(sd.flag & SD_BSDF_HAS_EVAL) { - Ray light_ray; - BsdfEval L_light; - bool is_lamp; - -#ifdef __OBJECT_MOTION__ - light_ray.time = sd.time; -#endif - - /* lamp sampling */ - for(int i = 0; i < kernel_data.integrator.num_all_lights; i++) { - int num_samples = light_select_num_samples(kg, i); - float num_samples_inv = 1.0f/(num_samples*kernel_data.integrator.num_all_lights); - - if(kernel_data.integrator.pdf_triangles != 0.0f) - num_samples_inv *= 0.5f; - - for(int j = 0; j < num_samples; j++) { - float light_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_U); - float light_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_V); - - if(direct_emission(kg, &sd, i, 0.0f, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) { - /* trace shadow ray */ - float3 shadow; +#ifdef __SUBSURFACE__ + /* bssrdf scatter to a different location on the same object */ + if(sd.flag & SD_BSSRDF) { + for(int i = 0; i< sd.num_closure; i++) { + ShaderClosure *sc = &sd.closure[i]; - if(!shadow_blocked(kg, &state, &light_ray, &shadow)) { - /* accumulate */ - path_radiance_accum_light(&L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state.bounce, is_lamp); - } - } - } - } + if(!CLOSURE_IS_BSSRDF(sc->type)) + continue; - /* mesh light sampling */ - if(kernel_data.integrator.pdf_triangles != 0.0f) { - int num_samples = kernel_data.integrator.mesh_light_samples; + /* set up random number generator */ + uint lcg_state = lcg_init(rbsdf); + int num_samples = kernel_data.integrator.subsurface_samples; float num_samples_inv = 1.0f/num_samples; - if(kernel_data.integrator.num_all_lights) - num_samples_inv *= 0.5f; - + /* do subsurface scatter step with copy of shader data, this will + * replace the BSSRDF with a diffuse BSDF closure */ for(int j = 0; j < num_samples; j++) { - float light_t = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT); - float light_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_U); - float light_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_LIGHT_V); - - /* only sample triangle lights */ - if(kernel_data.integrator.num_all_lights) - light_t = 0.5f*light_t; - - if(direct_emission(kg, &sd, -1, light_t, 0.0f, light_u, light_v, &light_ray, &L_light, &is_lamp)) { - /* trace shadow ray */ - float3 shadow; - - if(!shadow_blocked(kg, &state, &light_ray, &shadow)) { - /* accumulate */ - path_radiance_accum_light(&L, throughput*num_samples_inv, &L_light, shadow, num_samples_inv, state.bounce, is_lamp); - } - } + ShaderData bssrdf_sd = sd; + subsurface_scatter_step(kg, &bssrdf_sd, state.flag, sc, &lcg_state, true); + + /* compute lighting with the BSDF closure */ + kernel_path_non_progressive_lighting(kg, rng, sample*num_samples + j, + &bssrdf_sd, throughput, num_samples_inv, + ray_pdf, ray_pdf, state, rng_offset, &L, buffer); } } } #endif - for(int i = 0; i< sd.num_closure; i++) { - const ShaderClosure *sc = &sd.closure[i]; - - if(!CLOSURE_IS_BSDF(sc->type)) - continue; - /* transparency is not handled here, but in outer loop */ - if(sc->type == CLOSURE_BSDF_TRANSPARENT_ID) - continue; - - int num_samples; - - if(CLOSURE_IS_BSDF_DIFFUSE(sc->type)) - num_samples = kernel_data.integrator.diffuse_samples; - else if(CLOSURE_IS_BSDF_GLOSSY(sc->type)) - num_samples = kernel_data.integrator.glossy_samples; - else - num_samples = kernel_data.integrator.transmission_samples; - - float num_samples_inv = 1.0f/num_samples; - - for(int j = 0; j < num_samples; j++) { - /* sample BSDF */ - float bsdf_pdf; - BsdfEval bsdf_eval; - float3 bsdf_omega_in; - differential3 bsdf_domega_in; - float bsdf_u = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_U); - float bsdf_v = path_rng(kg, rng, sample*num_samples + j, rng_offset + PRNG_BSDF_V); - int label; - - label = shader_bsdf_sample_closure(kg, &sd, sc, bsdf_u, bsdf_v, &bsdf_eval, - &bsdf_omega_in, &bsdf_domega_in, &bsdf_pdf); - - if(bsdf_pdf == 0.0f || bsdf_eval_is_zero(&bsdf_eval)) - continue; - - /* modify throughput */ - float3 tp = throughput; - path_radiance_bsdf_bounce(&L, &tp, &bsdf_eval, bsdf_pdf, state.bounce, label); - - /* set labels */ - float min_ray_pdf = FLT_MAX; - - if(!(label & LABEL_TRANSPARENT)) - min_ray_pdf = fminf(bsdf_pdf, min_ray_pdf); - - /* modify path state */ - PathState ps = state; - path_state_next(kg, &ps, label); - - /* setup ray */ - Ray bsdf_ray; - - bsdf_ray.P = ray_offset(sd.P, (label & LABEL_TRANSMIT)? -sd.Ng: sd.Ng); - bsdf_ray.D = bsdf_omega_in; - bsdf_ray.t = FLT_MAX; -#ifdef __RAY_DIFFERENTIALS__ - bsdf_ray.dP = sd.dP; - bsdf_ray.dD = bsdf_domega_in; -#endif -#ifdef __OBJECT_MOTION__ - bsdf_ray.time = sd.time; -#endif - - kernel_path_indirect(kg, rng, sample*num_samples + j, bsdf_ray, buffer, - tp*num_samples_inv, num_samples, - min_ray_pdf, bsdf_pdf, ps, rng_offset+PRNG_BOUNCE_NUM, &L); - - /* for render passes, sum and reset indirect light pass variables - * for the next samples */ - path_radiance_sum_indirect(&L); - path_radiance_reset_indirect(&L); - } - } + /* lighting */ + kernel_path_non_progressive_lighting(kg, rng, sample, &sd, throughput, + 1.0f, ray_pdf, ray_pdf, state, rng_offset, &L, buffer); /* continue in case of transparency */ throughput *= shader_bsdf_transparency(kg, &sd); - shader_release(kg, &sd); if(is_zero(throughput)) break; diff --git a/intern/cycles/kernel/kernel_random.h b/intern/cycles/kernel/kernel_random.h index 9083b7cbfd7..e2eb8d5db83 100644 --- a/intern/cycles/kernel/kernel_random.h +++ b/intern/cycles/kernel/kernel_random.h @@ -200,5 +200,19 @@ __device void path_rng_end(KernelGlobals *kg, __global uint *rng_state, RNG rng) #endif +__device float lcg_step(uint *rng) +{ + /* implicit mod 2^32 */ + *rng = (1103515245*(*rng) + 12345); + return (float)*rng * (1.0f/(float)0xFFFFFFFF); +} + +__device uint lcg_init(float seed) +{ + uint rng = __float_as_int(seed); + lcg_step(&rng); + return rng; +} + CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index df86b352697..444543bf709 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -158,6 +158,103 @@ __device_noinline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, #endif } +/* ShaderData setup from BSSRDF scatter */ + +#ifdef __SUBSURFACE__ +__device_inline void shader_setup_from_subsurface(KernelGlobals *kg, ShaderData *sd, + const Intersection *isect, const Ray *ray) +{ + bool backfacing = sd->flag & SD_BACKFACING; + + /* object, matrices, time, ray_length stay the same */ + sd->flag = kernel_tex_fetch(__object_flag, sd->object); + sd->prim = kernel_tex_fetch(__prim_index, isect->prim); + +#ifdef __HAIR__ + if(kernel_tex_fetch(__prim_segment, isect->prim) != ~0) { + /* Strand Shader setting*/ + float4 curvedata = kernel_tex_fetch(__curves, sd->prim); + + sd->shader = __float_as_int(curvedata.z); + sd->segment = isect->segment; + + float tcorr = isect->t; + if(kernel_data.curve_kernel_data.curveflags & CURVE_KN_POSTINTERSECTCORRECTION) + tcorr = (isect->u < 0)? tcorr + sqrtf(isect->v) : tcorr - sqrtf(isect->v); + + sd->P = bvh_curve_refine(kg, sd, isect, ray, tcorr); + } + else { +#endif + /* fetch triangle data */ + float4 Ns = kernel_tex_fetch(__tri_normal, sd->prim); + float3 Ng = make_float3(Ns.x, Ns.y, Ns.z); + sd->shader = __float_as_int(Ns.w); + +#ifdef __HAIR__ + sd->segment = ~0; +#endif + +#ifdef __UV__ + sd->u = isect->u; + sd->v = isect->v; +#endif + + /* vectors */ + sd->P = bvh_triangle_refine(kg, sd, isect, ray); + sd->Ng = Ng; + sd->N = Ng; + + /* smooth normal */ + if(sd->shader & SHADER_SMOOTH_NORMAL) + sd->N = triangle_smooth_normal(kg, sd->prim, sd->u, sd->v); + +#ifdef __DPDU__ + /* dPdu/dPdv */ + triangle_dPdudv(kg, &sd->dPdu, &sd->dPdv, sd->prim); +#endif + +#ifdef __HAIR__ + } +#endif + + sd->flag |= kernel_tex_fetch(__shader_flag, (sd->shader & SHADER_MASK)*2); + +#ifdef __INSTANCING__ + if(isect->object != ~0) { + /* instance transform */ + object_normal_transform(kg, sd, &sd->N); + object_normal_transform(kg, sd, &sd->Ng); +#ifdef __DPDU__ + object_dir_transform(kg, sd, &sd->dPdu); + object_dir_transform(kg, sd, &sd->dPdv); +#endif + } +#endif + + /* backfacing test */ + if(backfacing) { + sd->flag |= SD_BACKFACING; + sd->Ng = -sd->Ng; + sd->N = -sd->N; +#ifdef __DPDU__ + sd->dPdu = -sd->dPdu; + sd->dPdv = -sd->dPdv; +#endif + } + + /* should not get used in principle as the shading will only use a diffuse + * BSDF, but the shader might still access it */ + sd->I = sd->N; + +#ifdef __RAY_DIFFERENTIALS__ + /* differentials */ + differential_dudv(&sd->du, &sd->dv, sd->dPdu, sd->dPdv, sd->dP, sd->Ng); + /* don't modify dP and dI */ +#endif +} +#endif + /* ShaderData setup from position sampled on mesh */ __device_noinline void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, @@ -283,11 +380,9 @@ __device_noinline void shader_setup_from_sample(KernelGlobals *kg, ShaderData *s /* ShaderData setup for displacement */ -__device_noinline void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd, +__device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd, int object, int prim, float u, float v) { - /* Note: no OSLShader::init call here, this is done in shader_setup_from_sample! */ - float3 P, Ng, I = make_float3(0.0f, 0.0f, 0.0f); int shader; @@ -418,7 +513,7 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc = &sd->closure[sampled]; if(CLOSURE_IS_BSDF(sc->type)) { - sum += sd->closure[sampled].sample_weight; + sum += sc->sample_weight; if(r <= sum) break; @@ -811,7 +906,7 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd) ShaderClosure *scj = &sd->closure[j]; #ifdef __OSL__ - if(!sci->prim && sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1) { + if(!sci->prim && !scj->prim && sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1) { #else if(sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1) { #endif @@ -823,18 +918,12 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd) memmove(scj, scj+1, size*sizeof(ShaderClosure)); sd->num_closure--; + j--; } } } } #endif -/* Free ShaderData */ - -__device void shader_release(KernelGlobals *kg, ShaderData *sd) -{ - /* nothing to do currently */ -} - CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_subsurface.h b/intern/cycles/kernel/kernel_subsurface.h new file mode 100644 index 00000000000..5fef9965c7f --- /dev/null +++ b/intern/cycles/kernel/kernel_subsurface.h @@ -0,0 +1,241 @@ +/* + * Copyright 2013, Blender Foundation. + * + * 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. + */ + +CCL_NAMESPACE_BEGIN + +#define BSSRDF_MULTI_EVAL +#define BSSRDF_SKIP_NO_HIT + +__device float bssrdf_sample_distance(KernelGlobals *kg, float radius, float refl, float u) +{ + int table_offset = kernel_data.bssrdf.table_offset; + float r = lookup_table_read_2D(kg, u, refl, table_offset, BSSRDF_RADIUS_TABLE_SIZE, BSSRDF_REFL_TABLE_SIZE); + + return r*radius; +} + +#ifdef BSSRDF_MULTI_EVAL +__device float bssrdf_pdf(KernelGlobals *kg, float radius, float refl, float r) +{ + if(r >= radius) + return 0.0f; + + /* todo: when we use the real BSSRDF this will need to be divided by the maximum + * radius instead of the average radius */ + float t = r/radius; + + int table_offset = kernel_data.bssrdf.table_offset + BSSRDF_PDF_TABLE_OFFSET; + float pdf = lookup_table_read_2D(kg, t, refl, table_offset, BSSRDF_RADIUS_TABLE_SIZE, BSSRDF_REFL_TABLE_SIZE); + + pdf /= radius; + + return pdf; +} +#endif + +__device ShaderClosure *subsurface_scatter_pick_closure(KernelGlobals *kg, ShaderData *sd, float *probability) +{ + /* sum sample weights of bssrdf and bsdf */ + float bsdf_sum = 0.0f; + float bssrdf_sum = 0.0f; + + for(int i = 0; i < sd->num_closure; i++) { + ShaderClosure *sc = &sd->closure[i]; + + if(CLOSURE_IS_BSDF(sc->type)) + bsdf_sum += sc->sample_weight; + else if(CLOSURE_IS_BSSRDF(sc->type)) + bssrdf_sum += sc->sample_weight; + } + + /* use bsdf or bssrdf? */ + float r = sd->randb_closure*(bsdf_sum + bssrdf_sum); + + if(r < bsdf_sum) { + /* use bsdf, and adjust randb so we can reuse it for picking a bsdf */ + sd->randb_closure = r/bsdf_sum; + *probability = (bsdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/bsdf_sum: 1.0f; + return NULL; + } + + /* use bssrdf */ + r -= bsdf_sum; + sd->randb_closure = 0.0f; /* not needed anymore */ + + float sum = 0.0f; + + for(int i = 0; i < sd->num_closure; i++) { + ShaderClosure *sc = &sd->closure[i]; + + if(CLOSURE_IS_BSSRDF(sc->type)) { + sum += sc->sample_weight; + + if(r <= sum) { +#ifdef BSSRDF_MULTI_EVAL + *probability = (bssrdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/bssrdf_sum: 1.0f; +#else + *probability = (bssrdf_sum > 0.0f)? (bsdf_sum + bssrdf_sum)/sc->sample_weight: 1.0f; +#endif + return sc; + } + } + } + + /* should never happen */ + *probability = 1.0f; + return NULL; +} + +#ifdef BSSRDF_MULTI_EVAL +__device float3 subsurface_scatter_multi_eval(KernelGlobals *kg, ShaderData *sd, bool hit, float refl, float *r, int num_r, bool all) +{ + /* compute pdf */ + float3 eval_sum = make_float3(0.0f, 0.0f, 0.0f); + float pdf_sum = 0.0f; + float sample_weight_sum = 0.0f; + int num_bssrdf = 0; + + for(int i = 0; i < sd->num_closure; i++) { + ShaderClosure *sc = &sd->closure[i]; + + if(CLOSURE_IS_BSSRDF(sc->type)) { + float sample_weight = (all)? 1.0f: sc->sample_weight; + + /* compute pdf */ + float pdf = 1.0f; + for(int i = 0; i < num_r; i++) + pdf *= bssrdf_pdf(kg, sc->data0, refl, r[i]); + + eval_sum += sc->weight*pdf; + pdf_sum += sample_weight*pdf; + + sample_weight_sum += sample_weight; + num_bssrdf++; + } + } + + float inv_pdf_sum; + + if(pdf_sum > 0.0f) { + /* in case of non-progressive integrate we sample all bssrdf's once, + * for progressive we pick one, so adjust pdf for that */ + if(all) + inv_pdf_sum = 1.0f/pdf_sum; + else + inv_pdf_sum = sample_weight_sum/pdf_sum; + } + else + inv_pdf_sum = 0.0f; + + float3 weight = eval_sum * inv_pdf_sum; + + return weight; +} +#endif + +/* replace closures with a single diffuse bsdf closure after scatter step */ +__device void subsurface_scatter_setup_diffuse_bsdf(ShaderData *sd, float3 weight) +{ + ShaderClosure *sc = &sd->closure[0]; + sd->num_closure = 1; + + sc->weight = weight; + sc->sample_weight = 1.0f; + sc->data0 = 0.0f; + sc->data1 = 0.0f; + sc->N = sd->N; + sd->flag &= ~SD_CLOSURE_FLAGS; + sd->flag |= bsdf_diffuse_setup(sc); + sd->randb_closure = 0.0f; + + /* todo: evaluate shading to get blurred textures and bump mapping */ + /* shader_eval_surface(kg, sd, 0.0f, state_flag, SHADER_CONTEXT_SSS); */ +} + +/* subsurface scattering step, from a point on the surface to another nearby point on the same object */ +__device void subsurface_scatter_step(KernelGlobals *kg, ShaderData *sd, int state_flag, ShaderClosure *sc, uint *lcg_state, bool all) +{ + float radius = sc->data0; + float refl = max(average(sc->weight)*3.0f, 0.0f); + float r = 0.0f; + bool hit = false; + float3 weight = make_float3(1.0f, 1.0f, 1.0f); +#ifdef BSSRDF_MULTI_EVAL + float r_attempts[BSSRDF_MAX_ATTEMPTS]; +#endif + int num_attempts; + + /* attempt to find a hit a given number of times before giving up */ + for(num_attempts = 0; num_attempts < kernel_data.bssrdf.num_attempts; num_attempts++) { + /* random numbers for sampling */ + float u1 = lcg_step(lcg_state); + float u2 = lcg_step(lcg_state); + float u3 = lcg_step(lcg_state); + float u4 = lcg_step(lcg_state); + float u5 = lcg_step(lcg_state); + float u6 = lcg_step(lcg_state); + + r = bssrdf_sample_distance(kg, radius, refl, u5); +#ifdef BSSRDF_MULTI_EVAL + r_attempts[num_attempts] = r; +#endif + + float3 p1 = sd->P + sample_uniform_sphere(u1, u2)*r; + float3 p2 = sd->P + sample_uniform_sphere(u3, u4)*r; + + /* create ray */ + Ray ray; + ray.P = p1; + ray.D = normalize_len(p2 - p1, &ray.t); + ray.dP = sd->dP; + ray.dD.dx = make_float3(0.0f, 0.0f, 0.0f); + ray.dD.dy = make_float3(0.0f, 0.0f, 0.0f); + ray.time = sd->time; + + /* intersect with the same object. if multiple intersections are + * found it will randomly pick one of them */ + Intersection isect; + if(scene_intersect_subsurface(kg, &ray, &isect, sd->object, u6) == 0) + continue; + + /* setup new shading point */ + shader_setup_from_subsurface(kg, sd, &isect, &ray); + + hit = true; + num_attempts++; + break; + } + + /* evaluate subsurface scattering closures */ +#ifdef BSSRDF_MULTI_EVAL + weight *= subsurface_scatter_multi_eval(kg, sd, hit, refl, r_attempts, num_attempts, all); +#else + weight *= sc->weight; +#endif + +#ifdef BSSRDF_SKIP_NO_HIT + if(!hit) + weight = make_float3(0.0f, 0.0f, 0.0f); +#endif + + /* replace closures with a single diffuse BSDF */ + subsurface_scatter_setup_diffuse_bsdf(sd, weight); +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/kernel/kernel_textures.h b/intern/cycles/kernel/kernel_textures.h index e27de95e7ab..55c6e15ad04 100644 --- a/intern/cycles/kernel/kernel_textures.h +++ b/intern/cycles/kernel/kernel_textures.h @@ -66,8 +66,8 @@ KERNEL_TEX(uint4, texture_uint4, __svm_nodes) KERNEL_TEX(uint, texture_uint, __shader_flag) KERNEL_TEX(uint, texture_uint, __object_flag) -/* camera/film */ -KERNEL_TEX(float, texture_float, __filter_table) +/* lookup tables */ +KERNEL_TEX(float, texture_float, __lookup_table) /* sobol */ KERNEL_TEX(uint, texture_uint, __sobol_directions) diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index ddbda9240fb..526609d0506 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -37,6 +37,13 @@ CCL_NAMESPACE_BEGIN #define PARTICLE_SIZE 5 #define TIME_INVALID FLT_MAX +#define BSSRDF_RADIUS_TABLE_SIZE 1024 +#define BSSRDF_REFL_TABLE_SIZE 256 +#define BSSRDF_PDF_TABLE_OFFSET (BSSRDF_RADIUS_TABLE_SIZE*BSSRDF_REFL_TABLE_SIZE) +#define BSSRDF_LOOKUP_TABLE_SIZE (BSSRDF_RADIUS_TABLE_SIZE*BSSRDF_REFL_TABLE_SIZE*2) +#define BSSRDF_MIN_RADIUS 1e-8f +#define BSSRDF_MAX_ATTEMPTS 8 + #define TEX_NUM_FLOAT_IMAGES 5 /* device capabilities */ @@ -48,6 +55,7 @@ CCL_NAMESPACE_BEGIN #ifdef WITH_OSL #define __OSL__ #endif +#define __SUBSURFACE__ #endif #ifdef __KERNEL_CUDA__ @@ -423,7 +431,8 @@ typedef enum ShaderContext { SHADER_CONTEXT_INDIRECT = 1, SHADER_CONTEXT_EMISSION = 2, SHADER_CONTEXT_SHADOW = 3, - SHADER_CONTEXT_NUM = 4 + SHADER_CONTEXT_SSS = 4, + SHADER_CONTEXT_NUM = 5 } ShaderContext; /* Shader Data @@ -438,20 +447,23 @@ enum ShaderDataFlag { SD_BSDF = 4, /* have bsdf closure? */ SD_BSDF_HAS_EVAL = 8, /* have non-singular bsdf closure? */ SD_BSDF_GLOSSY = 16, /* have glossy bsdf */ - SD_HOLDOUT = 32, /* have holdout closure? */ - SD_VOLUME = 64, /* have volume closure? */ - SD_AO = 128, /* have ao closure? */ + SD_BSSRDF = 32, /* have bssrdf */ + SD_HOLDOUT = 64, /* have holdout closure? */ + SD_VOLUME = 128, /* have volume closure? */ + SD_AO = 256, /* have ao closure? */ + + SD_CLOSURE_FLAGS = (SD_EMISSION|SD_BSDF|SD_BSDF_HAS_EVAL|SD_BSDF_GLOSSY|SD_BSSRDF|SD_HOLDOUT|SD_VOLUME|SD_AO), /* shader flags */ - SD_SAMPLE_AS_LIGHT = 256, /* direct light sample */ - SD_HAS_SURFACE_TRANSPARENT = 512, /* has surface transparency */ - SD_HAS_VOLUME = 1024, /* has volume shader */ - SD_HOMOGENEOUS_VOLUME = 2048, /* has homogeneous volume */ + SD_SAMPLE_AS_LIGHT = 512, /* direct light sample */ + SD_HAS_SURFACE_TRANSPARENT = 1024, /* has surface transparency */ + SD_HAS_VOLUME = 2048, /* has volume shader */ + SD_HOMOGENEOUS_VOLUME = 4096, /* has homogeneous volume */ /* object flags */ - SD_HOLDOUT_MASK = 4096, /* holdout for camera rays */ - SD_OBJECT_MOTION = 8192, /* has object motion blur */ - SD_TRANSFORM_APPLIED = 16384 /* vertices have transform applied */ + SD_HOLDOUT_MASK = 8192, /* holdout for camera rays */ + SD_OBJECT_MOTION = 16384, /* has object motion blur */ + SD_TRANSFORM_APPLIED = 32768 /* vertices have transform applied */ }; typedef struct ShaderData { @@ -611,8 +623,9 @@ typedef struct KernelFilm { int pass_shadow; float pass_shadow_scale; - int pass_pad1; - int pass_pad2; + + int filter_table_offset; + int filter_pad; } KernelFilm; typedef struct KernelBackground { @@ -680,6 +693,9 @@ typedef struct KernelIntegrator { int ao_samples; int mesh_light_samples; int use_lamp_mis; + int subsurface_samples; + + int pad1, pad2, pad3; } KernelIntegrator; typedef struct KernelBVH { @@ -711,9 +727,14 @@ typedef struct KernelCurves { float encasing_ratio; int curveflags; int subdivisions; - } KernelCurves; +typedef struct KernelBSSRDF { + int table_offset; + int num_attempts; + int pad1, pad2; +} KernelBSSRDF; + typedef struct KernelData { KernelCamera cam; KernelFilm film; @@ -722,6 +743,7 @@ typedef struct KernelData { KernelIntegrator integrator; KernelBVH bvh; KernelCurves curve_kernel_data; + KernelBSSRDF bssrdf; } KernelData; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt index 5a27f7823e4..0ce40eda4df 100644 --- a/intern/cycles/kernel/osl/CMakeLists.txt +++ b/intern/cycles/kernel/osl/CMakeLists.txt @@ -18,12 +18,14 @@ set(SRC bsdf_phong_ramp.cpp bsdf_toon.cpp emissive.cpp + osl_bssrdf.cpp osl_closures.cpp osl_services.cpp osl_shader.cpp ) set(HEADER_SRC + osl_bssrdf.h osl_closures.h osl_globals.h osl_services.h diff --git a/intern/cycles/kernel/osl/osl_bssrdf.cpp b/intern/cycles/kernel/osl/osl_bssrdf.cpp new file mode 100644 index 00000000000..ba9b13126ac --- /dev/null +++ b/intern/cycles/kernel/osl/osl_bssrdf.cpp @@ -0,0 +1,90 @@ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <OpenImageIO/fmath.h> + +#include <OSL/genclosure.h> + +#include "osl_bssrdf.h" +#include "osl_closures.h" + +#include "kernel_types.h" +#include "kernel_montecarlo.h" + +#include "closure/bsdf_diffuse.h" +#include "closure/bssrdf.h" + +CCL_NAMESPACE_BEGIN + +using namespace OSL; + +class BSSRDFClosure : public CBSSRDFClosure { +public: + size_t memsize() const { return sizeof(*this); } + const char *name() const { return "bssrdf_cubic"; } + + void setup() + { + sc.prim = NULL; + sc.data0 = fabsf(average(radius)); + sc.data1 = 1.3f; + + m_shaderdata_flag = bssrdf_setup(&sc); + } + + bool mergeable(const ClosurePrimitive *other) const + { + return false; + } + + void print_on(std::ostream &out) const + { + out << name() << " ((" << sc.N[0] << ", " << sc.N[1] << ", " << sc.N[2] << "))"; + } +}; + +ClosureParam *closure_bssrdf_params() +{ + static ClosureParam params[] = { + CLOSURE_FLOAT3_PARAM(BSSRDFClosure, sc.N), + CLOSURE_FLOAT3_PARAM(BSSRDFClosure, radius), + //CLOSURE_FLOAT_PARAM(BSSRDFClosure, sc.data1), + CLOSURE_STRING_KEYPARAM("label"), + CLOSURE_FINISH_PARAM(BSSRDFClosure) + }; + return params; +} + +CLOSURE_PREPARE(closure_bssrdf_prepare, BSSRDFClosure) + +CCL_NAMESPACE_END + diff --git a/intern/cycles/kernel/osl/osl_bssrdf.h b/intern/cycles/kernel/osl/osl_bssrdf.h new file mode 100644 index 00000000000..54df055405e --- /dev/null +++ b/intern/cycles/kernel/osl/osl_bssrdf.h @@ -0,0 +1,65 @@ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __OSL_BSSRDF_H__ +#define __OSL_BSSRDF_H__ + +#include <OSL/oslclosure.h> +#include <OSL/oslexec.h> +#include <OSL/genclosure.h> + +#include "kernel_types.h" + +#include "util_types.h" + +CCL_NAMESPACE_BEGIN + +class CBSSRDFClosure : public OSL::ClosurePrimitive { +public: + ShaderClosure sc; + float3 radius; + + CBSSRDFClosure() : OSL::ClosurePrimitive(BSSRDF), + m_shaderdata_flag(0) { } + ~CBSSRDFClosure() { } + + int scattering() const { return LABEL_DIFFUSE; } + int shaderdata_flag() const { return m_shaderdata_flag; } + +protected: + int m_shaderdata_flag; +}; + +CCL_NAMESPACE_END + +#endif /* __OSL_BSSRDF_H__ */ + diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 9e65cda1e8f..9ce11ca1207 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -201,6 +201,8 @@ void OSLShader::register_closures(OSLShadingSystem *ss_) closure_bsdf_diffuse_toon_params(), closure_bsdf_diffuse_toon_prepare); register_closure(ss, "specular_toon", id++, closure_bsdf_specular_toon_params(), closure_bsdf_specular_toon_prepare); + register_closure(ss, "bssrdf_cubic", id++, + closure_bssrdf_params(), closure_bssrdf_prepare); } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index daccc03ede2..d0e25bb2b0c 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -51,6 +51,7 @@ OSL::ClosureParam *closure_bsdf_diffuse_ramp_params(); OSL::ClosureParam *closure_bsdf_phong_ramp_params(); OSL::ClosureParam *closure_bsdf_diffuse_toon_params(); OSL::ClosureParam *closure_bsdf_specular_toon_params(); +OSL::ClosureParam *closure_bssrdf_params(); void closure_emission_prepare(OSL::RendererServices *, int id, void *data); void closure_background_prepare(OSL::RendererServices *, int id, void *data); @@ -60,6 +61,7 @@ void closure_bsdf_diffuse_ramp_prepare(OSL::RendererServices *, int id, void *da void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data); void closure_bsdf_diffuse_toon_prepare(OSL::RendererServices *, int id, void *data); void closure_bsdf_specular_toon_prepare(OSL::RendererServices *, int id, void *data); +void closure_bssrdf_prepare(OSL::RendererServices *, int id, void *data); enum { AmbientOcclusion = 100 diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index a32c526a2be..555edf598f1 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -21,6 +21,7 @@ #include "kernel_globals.h" #include "kernel_object.h" +#include "osl_bssrdf.h" #include "osl_closures.h" #include "osl_globals.h" #include "osl_services.h" @@ -201,7 +202,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, } break; } - case OSL::ClosurePrimitive::Holdout: + case OSL::ClosurePrimitive::Holdout: { sc.sample_weight = 0.0f; sc.type = CLOSURE_HOLDOUT_ID; sc.prim = NULL; @@ -211,7 +212,43 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, sd->flag |= SD_HOLDOUT; } break; - case OSL::ClosurePrimitive::BSSRDF: + } + case OSL::ClosurePrimitive::BSSRDF: { + CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim; + float sample_weight = fabsf(average(weight)); + + if(sample_weight > 1e-5f && sd->num_closure+2 < MAX_CLOSURE) { + sc.sample_weight = sample_weight; + + sc.type = bssrdf->sc.type; + sc.N = bssrdf->sc.N; + sc.data1 = bssrdf->sc.data1; + sc.prim = NULL; + + /* create one closure for each color channel */ + if(fabsf(weight.x) > 0.0f) { + sc.weight = make_float3(weight.x, 0.0f, 0.0f); + sc.data0 = bssrdf->radius.x; + sd->closure[sd->num_closure++] = sc; + sd->flag |= bssrdf->shaderdata_flag(); + } + + if(fabsf(weight.y) > 0.0f) { + sc.weight = make_float3(0.0f, weight.y, 0.0f); + sc.data0 = bssrdf->radius.y; + sd->closure[sd->num_closure++] = sc; + sd->flag |= bssrdf->shaderdata_flag(); + } + + if(fabsf(weight.z) > 0.0f) { + sc.weight = make_float3(0.0f, 0.0f, weight.z); + sc.data0 = bssrdf->radius.z; + sd->closure[sd->num_closure++] = sc; + sd->flag |= bssrdf->shaderdata_flag(); + } + } + break; + } case OSL::ClosurePrimitive::Debug: break; /* not implemented */ case OSL::ClosurePrimitive::Background: diff --git a/intern/cycles/kernel/shaders/CMakeLists.txt b/intern/cycles/kernel/shaders/CMakeLists.txt index acae46f1615..0cff264d8e1 100644 --- a/intern/cycles/kernel/shaders/CMakeLists.txt +++ b/intern/cycles/kernel/shaders/CMakeLists.txt @@ -55,6 +55,7 @@ set(SRC_OSL node_separate_rgb.osl node_set_normal.osl node_sky_texture.osl + node_subsurface_scattering.osl node_tangent.osl node_texture_coordinate.osl node_translucent_bsdf.osl diff --git a/intern/cycles/kernel/shaders/node_subsurface_scattering.osl b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl new file mode 100644 index 00000000000..5c25c44ec8f --- /dev/null +++ b/intern/cycles/kernel/shaders/node_subsurface_scattering.osl @@ -0,0 +1,33 @@ +/* + * Copyright 2011, Blender Foundation. + * + * 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. + */ + +#include "stdosl.h" + +shader node_subsurface_scattering( + color Color = 0.8, + float Scale = 1.0, + vector Radius = vector(0.1, 0.1, 0.1), + float IOR = 1.3, + normal Normal = N, + output closure color BSSRDF = 0) +{ + float eta = max(IOR, 1.0 + 1e-5); + + BSSRDF = Color * bssrdf_cubic(N, Scale * Radius); +} + diff --git a/intern/cycles/kernel/shaders/stdosl.h b/intern/cycles/kernel/shaders/stdosl.h index f340eaff95f..010d6ddd200 100644 --- a/intern/cycles/kernel/shaders/stdosl.h +++ b/intern/cycles/kernel/shaders/stdosl.h @@ -461,6 +461,7 @@ closure color emission() BUILTIN; closure color background() BUILTIN; closure color holdout() BUILTIN; closure color ambient_occlusion() BUILTIN; +closure color bssrdf_cubic(normal N, vector radius) BUILTIN; // Renderer state int raytype (string typename) BUILTIN; diff --git a/intern/cycles/kernel/svm/svm_closure.h b/intern/cycles/kernel/svm/svm_closure.h index b5bd2b42cb4..72e6a047158 100644 --- a/intern/cycles/kernel/svm/svm_closure.h +++ b/intern/cycles/kernel/svm/svm_closure.h @@ -25,6 +25,7 @@ __device void svm_node_glass_setup(ShaderData *sd, ShaderClosure *sc, int type, if(type == CLOSURE_BSDF_SHARP_GLASS_ID) { if(refract) { sc->data0 = eta; + sc->data1 = 0.0f; sd->flag |= bsdf_refraction_setup(sc); } else @@ -58,6 +59,9 @@ __device_inline ShaderClosure *svm_node_closure_get_non_bsdf(ShaderData *sd, Clo if(sd->num_closure < MAX_CLOSURE) { sc->weight *= mix_weight; sc->type = type; +#ifdef __OSL__ + sc->prim = NULL; +#endif sd->num_closure++; return sc; } @@ -79,6 +83,9 @@ __device_inline ShaderClosure *svm_node_closure_get_bsdf(ShaderData *sd, float m sc->weight = weight; sc->sample_weight = sample_weight; sd->num_closure++; +#ifdef __OSL__ + sc->prim = NULL; +#endif return sc; } @@ -125,10 +132,13 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st float roughness = param1; if(roughness == 0.0f) { + sc->data0 = 0.0f; + sc->data1 = 0.0f; sd->flag |= bsdf_diffuse_setup(sc); } else { sc->data0 = roughness; + sc->data1 = 0.0f; sd->flag |= bsdf_oren_nayar_setup(sc); } } @@ -138,6 +148,8 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); if(sc) { + sc->data0 = 0.0f; + sc->data1 = 0.0f; sc->N = N; sd->flag |= bsdf_translucent_setup(sc); } @@ -147,6 +159,8 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st ShaderClosure *sc = svm_node_closure_get_bsdf(sd, mix_weight); if(sc) { + sc->data0 = 0.0f; + sc->data1 = 0.0f; sc->N = N; sd->flag |= bsdf_transparent_setup(sc); } @@ -164,6 +178,7 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st if(sc) { sc->N = N; sc->data0 = param1; + sc->data1 = 0.0f; /* setup bsdf */ if(type == CLOSURE_BSDF_REFLECTION_ID) @@ -302,10 +317,73 @@ __device void svm_node_closure_bsdf(KernelGlobals *kg, ShaderData *sd, float *st /* sigma */ sc->data0 = clamp(param1, 0.0f, 1.0f); + sc->data1 = 0.0f; sd->flag |= bsdf_ashikhmin_velvet_setup(sc); } break; } +#ifdef __SUBSURFACE__ + case CLOSURE_BSSRDF_ID: { + ShaderClosure *sc = &sd->closure[sd->num_closure]; + float3 weight = sc->weight * mix_weight; + float sample_weight = fabsf(average(weight)); + + if(sample_weight > 1e-5f && sd->num_closure+2 < MAX_CLOSURE) { + /* radius * scale */ + float3 radius = stack_load_float3(stack, data_node.w)*param1; + /* index of refraction */ + float eta = fmaxf(param2, 1.0f + 1e-5f); + + /* create one closure per color channel */ + if(fabsf(weight.x) > 0.0f) { + sc->weight = make_float3(weight.x, 0.0f, 0.0f); + sc->sample_weight = sample_weight; + sc->data0 = radius.x; + sc->data1 = eta; +#ifdef __OSL__ + sc->prim = NULL; +#endif + sc->N = N; + sd->flag |= bssrdf_setup(sc); + + sd->num_closure++; + sc++; + } + + if(fabsf(weight.y) > 0.0f) { + sc->weight = make_float3(0.0f, weight.y, 0.0f); + sc->sample_weight = sample_weight; + sc->data0 = radius.y; + sc->data1 = eta; +#ifdef __OSL__ + sc->prim = NULL; +#endif + sc->N = N; + sd->flag |= bssrdf_setup(sc); + + sd->num_closure++; + sc++; + } + + if(fabsf(weight.z) > 0.0f) { + sc->weight = make_float3(0.0f, 0.0f, weight.z); + sc->sample_weight = sample_weight; + sc->data0 = radius.z; + sc->data1 = eta; +#ifdef __OSL__ + sc->prim = NULL; +#endif + sc->N = N; + sd->flag |= bssrdf_setup(sc); + + sd->num_closure++; + sc++; + } + } + + break; + } +#endif default: break; } diff --git a/intern/cycles/kernel/svm/svm_types.h b/intern/cycles/kernel/svm/svm_types.h index 57177eec48f..70d73f98498 100644 --- a/intern/cycles/kernel/svm/svm_types.h +++ b/intern/cycles/kernel/svm/svm_types.h @@ -346,12 +346,11 @@ typedef enum ClosureType { CLOSURE_BSDF_TRANSPARENT_ID, - CLOSURE_BSSRDF_CUBIC_ID, + CLOSURE_BSSRDF_ID, CLOSURE_EMISSION_ID, CLOSURE_DEBUG_ID, CLOSURE_BACKGROUND_ID, CLOSURE_HOLDOUT_ID, - CLOSURE_SUBSURFACE_ID, CLOSURE_AMBIENT_OCCLUSION_ID, CLOSURE_VOLUME_ID, @@ -366,6 +365,7 @@ typedef enum ClosureType { #define CLOSURE_IS_BSDF_DIFFUSE(type) (type >= CLOSURE_BSDF_DIFFUSE_ID && type <= CLOSURE_BSDF_OREN_NAYAR_ID) #define CLOSURE_IS_BSDF_GLOSSY(type) (type >= CLOSURE_BSDF_GLOSSY_ID && type <= CLOSURE_BSDF_PHONG_RAMP_ID) #define CLOSURE_IS_BSDF_TRANSMISSION(type) (type >= CLOSURE_BSDF_TRANSMISSION_ID && type <= CLOSURE_BSDF_SHARP_GLASS_ID) +#define CLOSURE_IS_BSSRDF(type) (type == CLOSURE_BSSRDF_ID) #define CLOSURE_IS_VOLUME(type) (type >= CLOSURE_VOLUME_ID && type <= CLOSURE_VOLUME_ISOTROPIC_ID) #define CLOSURE_IS_EMISSION(type) (type == CLOSURE_EMISSION_ID) #define CLOSURE_IS_HOLDOUT(type) (type == CLOSURE_HOLDOUT_ID) diff --git a/intern/cycles/render/CMakeLists.txt b/intern/cycles/render/CMakeLists.txt index d67a686d1e8..e06364c6715 100644 --- a/intern/cycles/render/CMakeLists.txt +++ b/intern/cycles/render/CMakeLists.txt @@ -17,10 +17,10 @@ set(SRC attribute.cpp background.cpp buffers.cpp + bssrdf.cpp camera.cpp film.cpp # film_response.cpp (code unused) - filter.cpp graph.cpp image.cpp integrator.cpp @@ -37,6 +37,7 @@ set(SRC shader.cpp sobol.cpp svm.cpp + tables.cpp tile.cpp ) @@ -44,10 +45,10 @@ set(SRC_HEADERS attribute.h background.h buffers.h + bssrdf.h camera.h film.h # film_response.h (code unused) - filter.h graph.h image.h integrator.h @@ -63,6 +64,7 @@ set(SRC_HEADERS shader.h sobol.h svm.h + tables.h tile.h ) diff --git a/intern/cycles/render/bssrdf.cpp b/intern/cycles/render/bssrdf.cpp new file mode 100644 index 00000000000..f3f889f071a --- /dev/null +++ b/intern/cycles/render/bssrdf.cpp @@ -0,0 +1,141 @@ +/* + * Copyright 2011, Blender Foundation. + * + * 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. + */ + +#include "bssrdf.h" + +#include "util_algorithm.h" +#include "util_math.h" +#include "util_types.h" + +#include "kernel_types.h" +#include "kernel_montecarlo.h" + +#include "closure/bsdf_diffuse.h" +#include "closure/bssrdf.h" + +CCL_NAMESPACE_BEGIN + +/* Cumulative density function utilities */ + +static float cdf_lookup_inverse(const vector<float>& table, float2 range, float x) +{ + int index = upper_bound(table.begin(), table.end(), x) - table.begin(); + + if(index == 0) + return range[0]; + else if(index == table.size()) + return range[1]; + else + index--; + + float t = (x - table[index])/(table[index+1] - table[index]); + float y = ((index + t)/(table.size() - 1)); + + return y*(range[1] - range[0]) + range[0]; +} + +static void cdf_invert(vector<float>& to, float2 to_range, const vector<float>& from, float2 from_range) +{ + float step = 1.0f/(float)(to.size() - 1); + + for(int i = 0; i < to.size(); i++) { + float x = (i*step)*(from_range[1] - from_range[0]) + from_range[0]; + to[i] = cdf_lookup_inverse(from, to_range, x); + } +} + +/* BSSRDF */ + +static float bssrdf_lookup_table_max_radius(const BSSRDFParams *ss) +{ + /* todo: adjust when we use the real BSSRDF */ + return ss->ld; +} + +static void bssrdf_lookup_table_create(const BSSRDFParams *ss, vector<float>& sample_table, vector<float>& pdf_table) +{ + const int size = BSSRDF_RADIUS_TABLE_SIZE; + vector<float> cdf(size); + vector<float> pdf(size); + float step = 1.0f/(float)(size - 1); + float max_radius = bssrdf_lookup_table_max_radius(ss); + float pdf_sum = 0.0f; + + /* compute the probability density function */ + for(int i = 0; i < pdf.size(); i++) { + float x = (i*step)*max_radius; + pdf[i] = bssrdf_cubic(ss->ld, x); + pdf_sum += pdf[i]; + } + + /* adjust for area covered by each distance */ + for(int i = 0; i < pdf.size(); i++) { + float x = (i*step)*max_radius; + pdf[i] *= 2*M_PI_F*x; + } + + /* normalize pdf, we multiply in reflectance later */ + if(pdf_sum > 0.0f) + for(int i = 0; i < pdf.size(); i++) + pdf[i] /= pdf_sum; + + /* sum to account for sampling which uses overlapping sphere */ + for(int i = pdf.size() - 2; i >= 0; i--) + pdf[i] = pdf[i] + pdf[i+1]; + + /* compute the cumulative density function */ + cdf[0] = 0.0f; + + for(int i = 1; i < size; i++) + cdf[i] = cdf[i-1] + 0.5f*(pdf[i-1] + pdf[i])*step*max_radius; + + /* invert cumulative density function for importance sampling */ + float2 cdf_range = make_float2(0.0f, cdf[size - 1]); + float2 table_range = make_float2(0.0f, max_radius); + + cdf_invert(sample_table, table_range, cdf, cdf_range); + + /* copy pdf table */ + for(int i = 0; i < pdf.size(); i++) + pdf_table[i] = pdf[i]; +} + +void bssrdf_table_build(vector<float>& table) +{ + vector<float> sample_table(BSSRDF_RADIUS_TABLE_SIZE); + vector<float> pdf_table(BSSRDF_RADIUS_TABLE_SIZE); + + table.resize(BSSRDF_LOOKUP_TABLE_SIZE); + + /* create a 2D lookup table, for reflection x sample radius */ + for(int i = 0; i < BSSRDF_REFL_TABLE_SIZE; i++) { + float refl = (float)i/(float)(BSSRDF_REFL_TABLE_SIZE-1); + float ior = 1.3f; + float radius = 1.0f; + + BSSRDFParams ss; + bssrdf_setup_params(&ss, refl, radius, ior); + bssrdf_lookup_table_create(&ss, sample_table, pdf_table); + + memcpy(&table[i*BSSRDF_RADIUS_TABLE_SIZE], &sample_table[0], BSSRDF_RADIUS_TABLE_SIZE*sizeof(float)); + memcpy(&table[BSSRDF_PDF_TABLE_OFFSET + i*BSSRDF_RADIUS_TABLE_SIZE], &pdf_table[0], BSSRDF_RADIUS_TABLE_SIZE*sizeof(float)); + } +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/render/bssrdf.h b/intern/cycles/render/bssrdf.h new file mode 100644 index 00000000000..975ac0b46ec --- /dev/null +++ b/intern/cycles/render/bssrdf.h @@ -0,0 +1,31 @@ +/* + * Copyright 2011, Blender Foundation. + * + * 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. + */ + +#ifndef __BSSRDF_H__ +#define __BSSRDF_H__ + +#include "util_vector.h" + +CCL_NAMESPACE_BEGIN + +void bssrdf_table_build(vector<float>& table); + +CCL_NAMESPACE_END + +#endif /* __BSSRDF_H__ */ + diff --git a/intern/cycles/render/film.cpp b/intern/cycles/render/film.cpp index fdf25ca7908..9fc6e867166 100644 --- a/intern/cycles/render/film.cpp +++ b/intern/cycles/render/film.cpp @@ -22,9 +22,12 @@ #include "integrator.h" #include "mesh.h" #include "scene.h" +#include "tables.h" #include "util_algorithm.h" +#include "util_debug.h" #include "util_foreach.h" +#include "util_math.h" CCL_NAMESPACE_BEGIN @@ -171,12 +174,84 @@ bool Pass::contains(const vector<Pass>& passes, PassType type) return false; } +/* Pixel Filter */ + +static float filter_func_box(float v, float width) +{ + return (float)1; +} + +static float filter_func_gaussian(float v, float width) +{ + v *= (float)2/width; + return (float)expf((float)-2*v*v); +} + +static vector<float> filter_table(FilterType type, float width) +{ + const int filter_table_size = FILTER_TABLE_SIZE-1; + vector<float> filter_table_cdf(filter_table_size+1); + vector<float> filter_table(filter_table_size+1); + float (*filter_func)(float, float) = NULL; + int i, half_size = filter_table_size/2; + + switch(type) { + case FILTER_BOX: + filter_func = filter_func_box; + break; + case FILTER_GAUSSIAN: + filter_func = filter_func_gaussian; + break; + default: + assert(0); + } + + /* compute cumulative distribution function */ + filter_table_cdf[0] = 0.0f; + + for(i = 0; i < filter_table_size; i++) { + float x = i*width*0.5f/(filter_table_size-1); + float y = filter_func(x, width); + filter_table_cdf[i+1] += filter_table_cdf[i] + fabsf(y); + } + + for(i = 0; i <= filter_table_size; i++) + filter_table_cdf[i] /= filter_table_cdf[filter_table_size]; + + /* create importance sampling table */ + for(i = 0; i <= half_size; i++) { + float x = i/(float)half_size; + int index = upper_bound(filter_table_cdf.begin(), filter_table_cdf.end(), x) - filter_table_cdf.begin(); + float t; + + if(index < filter_table_size+1) { + t = (x - filter_table_cdf[index])/(filter_table_cdf[index+1] - filter_table_cdf[index]); + } + else { + t = 0.0f; + index = filter_table_size; + } + + float y = ((index + t)/(filter_table_size))*width; + + filter_table[half_size+i] = 0.5f*(1.0f + y); + filter_table[half_size-i] = 0.5f*(1.0f - y); + } + + return filter_table; +} + /* Film */ Film::Film() { exposure = 0.8f; Pass::add(PASS_COMBINED, passes); + + filter_type = FILTER_BOX; + filter_width = 1.0f; + filter_table_offset = TABLE_OFFSET_INVALID; + need_update = true; } @@ -184,10 +259,12 @@ Film::~Film() { } -void Film::device_update(Device *device, DeviceScene *dscene) +void Film::device_update(Device *device, DeviceScene *dscene, Scene *scene) { if(!need_update) return; + + device_free(device, dscene, scene); KernelFilm *kfilm = &dscene->data.film; @@ -284,17 +361,28 @@ void Film::device_update(Device *device, DeviceScene *dscene) kfilm->pass_stride = align_up(kfilm->pass_stride, 4); + /* update filter table */ + vector<float> table = filter_table(filter_type, filter_width); + filter_table_offset = scene->lookup_tables->add_table(dscene, table); + kfilm->filter_table_offset = (int)filter_table_offset; + need_update = false; } -void Film::device_free(Device *device, DeviceScene *dscene) +void Film::device_free(Device *device, DeviceScene *dscene, Scene *scene) { + if(filter_table_offset != TABLE_OFFSET_INVALID) { + scene->lookup_tables->remove_table(filter_table_offset); + filter_table_offset = TABLE_OFFSET_INVALID; + } } bool Film::modified(const Film& film) { return !(exposure == film.exposure - && Pass::equals(passes, film.passes)); + && Pass::equals(passes, film.passes) + && filter_type == film.filter_type + && filter_width == film.filter_width); } void Film::tag_passes_update(Scene *scene, const vector<Pass>& passes_) diff --git a/intern/cycles/render/film.h b/intern/cycles/render/film.h index 52d1a8428f8..bc1619c3f2d 100644 --- a/intern/cycles/render/film.h +++ b/intern/cycles/render/film.h @@ -30,6 +30,11 @@ class Device; class DeviceScene; class Scene; +typedef enum FilterType { + FILTER_BOX, + FILTER_GAUSSIAN +} FilterType; + class Pass { public: PassType type; @@ -47,13 +52,18 @@ class Film { public: float exposure; vector<Pass> passes; + + FilterType filter_type; + float filter_width; + size_t filter_table_offset; + bool need_update; Film(); ~Film(); - void device_update(Device *device, DeviceScene *dscene); - void device_free(Device *device, DeviceScene *dscene); + void device_update(Device *device, DeviceScene *dscene, Scene *scene); + void device_free(Device *device, DeviceScene *dscene, Scene *scene); bool modified(const Film& film); void tag_passes_update(Scene *scene, const vector<Pass>& passes_); diff --git a/intern/cycles/render/filter.cpp b/intern/cycles/render/filter.cpp deleted file mode 100644 index 0bd4fb4d579..00000000000 --- a/intern/cycles/render/filter.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * 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. - */ - -#include "camera.h" -#include "device.h" -#include "filter.h" -#include "scene.h" - -#include "kernel_types.h" - -#include "util_algorithm.h" -#include "util_debug.h" -#include "util_math.h" - -CCL_NAMESPACE_BEGIN - -Filter::Filter() -{ - filter_type = FILTER_BOX; - filter_width = 1.0f; - need_update = true; -} - -Filter::~Filter() -{ -} - -static float filter_func_box(float v, float width) -{ - return (float)1; -} - -static float filter_func_gaussian(float v, float width) -{ - v *= (float)2/width; - return (float)expf((float)-2*v*v); -} - -static vector<float> filter_table(FilterType type, float width) -{ - const int filter_table_size = FILTER_TABLE_SIZE-1; - vector<float> filter_table_cdf(filter_table_size+1); - vector<float> filter_table(filter_table_size+1); - float (*filter_func)(float, float) = NULL; - int i, half_size = filter_table_size/2; - - switch(type) { - case FILTER_BOX: - filter_func = filter_func_box; - break; - case FILTER_GAUSSIAN: - filter_func = filter_func_gaussian; - break; - default: - assert(0); - } - - /* compute cumulative distribution function */ - filter_table_cdf[0] = 0.0f; - - for(i = 0; i < filter_table_size; i++) { - float x = i*width*0.5f/(filter_table_size-1); - float y = filter_func(x, width); - filter_table_cdf[i+1] += filter_table_cdf[i] + fabsf(y); - } - - for(i = 0; i <= filter_table_size; i++) - filter_table_cdf[i] /= filter_table_cdf[filter_table_size]; - - /* create importance sampling table */ - for(i = 0; i <= half_size; i++) { - float x = i/(float)half_size; - int index = upper_bound(filter_table_cdf.begin(), filter_table_cdf.end(), x) - filter_table_cdf.begin(); - float t; - - if(index < filter_table_size+1) { - t = (x - filter_table_cdf[index])/(filter_table_cdf[index+1] - filter_table_cdf[index]); - } - else { - t = 0.0f; - index = filter_table_size; - } - - float y = ((index + t)/(filter_table_size))*width; - - filter_table[half_size+i] = 0.5f*(1.0f + y); - filter_table[half_size-i] = 0.5f*(1.0f - y); - } - - return filter_table; -} - -void Filter::device_update(Device *device, DeviceScene *dscene) -{ - if(!need_update) - return; - - device_free(device, dscene); - - /* update __filter_table */ - vector<float> table = filter_table(filter_type, filter_width); - - dscene->filter_table.copy(&table[0], table.size()); - device->tex_alloc("__filter_table", dscene->filter_table, true); - - need_update = false; -} - -void Filter::device_free(Device *device, DeviceScene *dscene) -{ - device->tex_free(dscene->filter_table); - dscene->filter_table.clear(); -} - -bool Filter::modified(const Filter& filter) -{ - return !(filter_type == filter.filter_type && - filter_width == filter.filter_width); -} - -void Filter::tag_update(Scene *scene) -{ - need_update = true; -} - -CCL_NAMESPACE_END - diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index c6b9ae08508..46043cf85d2 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -187,6 +187,7 @@ public: virtual bool has_surface_emission() { return false; } virtual bool has_surface_transparent() { return false; } + virtual bool has_surface_bssrdf() { return false; } vector<ShaderInput*> inputs; vector<ShaderOutput*> outputs; diff --git a/intern/cycles/render/integrator.cpp b/intern/cycles/render/integrator.cpp index 699e6979990..00039170733 100644 --- a/intern/cycles/render/integrator.cpp +++ b/intern/cycles/render/integrator.cpp @@ -54,6 +54,7 @@ Integrator::Integrator() transmission_samples = 1; ao_samples = 1; mesh_light_samples = 1; + subsurface_samples = 1; progressive = true; need_update = true; @@ -108,6 +109,7 @@ void Integrator::device_update(Device *device, DeviceScene *dscene, Scene *scene kintegrator->transmission_samples = transmission_samples; kintegrator->ao_samples = ao_samples; kintegrator->mesh_light_samples = mesh_light_samples; + kintegrator->subsurface_samples = subsurface_samples; /* sobol directions table */ int max_samples = 1; @@ -163,6 +165,7 @@ bool Integrator::modified(const Integrator& integrator) transmission_samples == integrator.transmission_samples && ao_samples == integrator.ao_samples && mesh_light_samples == integrator.mesh_light_samples && + subsurface_samples == integrator.subsurface_samples && motion_blur == integrator.motion_blur); } diff --git a/intern/cycles/render/integrator.h b/intern/cycles/render/integrator.h index 8fb341182b7..9867e310d4d 100644 --- a/intern/cycles/render/integrator.h +++ b/intern/cycles/render/integrator.h @@ -54,6 +54,7 @@ public: int transmission_samples; int ao_samples; int mesh_light_samples; + int subsurface_samples; bool progressive; diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index a4ffc2518fb..b4ff6e3152b 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -1262,16 +1262,19 @@ void ProxyNode::compile(OSLCompiler& compiler) /* BSDF Closure */ -BsdfNode::BsdfNode() -: ShaderNode("bsdf") +BsdfNode::BsdfNode(bool scattering_) +: ShaderNode("subsurface_scattering"), scattering(scattering_) { - closure = ccl::CLOSURE_BSDF_DIFFUSE_ID; + closure = ccl::CLOSURE_BSSRDF_ID; add_input("Color", SHADER_SOCKET_COLOR, make_float3(0.8f, 0.8f, 0.8f)); add_input("Normal", SHADER_SOCKET_NORMAL, ShaderInput::NORMAL); add_input("SurfaceMixWeight", SHADER_SOCKET_FLOAT, 0.0f, ShaderInput::USE_SVM); - add_output("BSDF", SHADER_SOCKET_CLOSURE); + if(scattering) + add_output("BSSRDF", SHADER_SOCKET_CLOSURE); + else + add_output("BSDF", SHADER_SOCKET_CLOSURE); } void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3) @@ -1313,7 +1316,8 @@ void BsdfNode::compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput * (param3)? param3->stack_offset: SVM_STACK_INVALID); } else { - compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset); + compiler.add_node(NODE_CLOSURE_BSDF, normal_in->stack_offset, SVM_STACK_INVALID, + (param3)? param3->stack_offset: SVM_STACK_INVALID); } } @@ -1548,6 +1552,29 @@ void TransparentBsdfNode::compile(OSLCompiler& compiler) compiler.add(this, "node_transparent_bsdf"); } +/* Subsurface Scattering Closure */ + +SubsurfaceScatteringNode::SubsurfaceScatteringNode() +: BsdfNode(true) +{ + name = "subsurface_scattering"; + closure = CLOSURE_BSSRDF_ID; + + add_input("Scale", SHADER_SOCKET_FLOAT, 0.01f); + add_input("Radius", SHADER_SOCKET_VECTOR, make_float3(0.1f, 0.1f, 0.1f)); + add_input("IOR", SHADER_SOCKET_FLOAT, 1.3f); +} + +void SubsurfaceScatteringNode::compile(SVMCompiler& compiler) +{ + BsdfNode::compile(compiler, input("Scale"), input("IOR"), input("Radius")); +} + +void SubsurfaceScatteringNode::compile(OSLCompiler& compiler) +{ + compiler.add(this, "node_subsurface_scattering"); +} + /* Emissive Closure */ EmissionNode::EmissionNode() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 1efe4ae076d..0d9f84327d0 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -198,11 +198,13 @@ public: class BsdfNode : public ShaderNode { public: - SHADER_NODE_CLASS(BsdfNode) + BsdfNode(bool scattering = false); + SHADER_NODE_BASE_CLASS(BsdfNode); void compile(SVMCompiler& compiler, ShaderInput *param1, ShaderInput *param2, ShaderInput *param3 = NULL); ClosureType closure; + bool scattering; }; class WardBsdfNode : public BsdfNode { @@ -257,6 +259,12 @@ public: static ShaderEnum distribution_enum; }; +class SubsurfaceScatteringNode : public BsdfNode { +public: + SHADER_NODE_CLASS(SubsurfaceScatteringNode) + bool has_surface_bssrdf() { return true; } +}; + class EmissionNode : public ShaderNode { public: SHADER_NODE_CLASS(EmissionNode) diff --git a/intern/cycles/render/osl.cpp b/intern/cycles/render/osl.cpp index f5585babf5c..cefb6315725 100644 --- a/intern/cycles/render/osl.cpp +++ b/intern/cycles/render/osl.cpp @@ -73,7 +73,7 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene if(!need_update) return; - device_free(device, dscene); + device_free(device, dscene, scene); /* determine which shaders are in use */ device_update_shaders_used(scene); @@ -114,11 +114,11 @@ void OSLShaderManager::device_update(Device *device, DeviceScene *dscene, Scene device_update_common(device, dscene, scene, progress); } -void OSLShaderManager::device_free(Device *device, DeviceScene *dscene) +void OSLShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene) { OSLGlobals *og = (OSLGlobals*)device->osl_memory(); - device_free_common(device, dscene); + device_free_common(device, dscene, scene); /* clear shader engine */ og->use = false; @@ -328,6 +328,7 @@ const char *OSLShaderManager::shader_load_bytecode(const string& hash, const str OSLShaderInfo info; info.has_surface_emission = (bytecode.find("\"emission\"") != string::npos); info.has_surface_transparent = (bytecode.find("\"transparent\"") != string::npos); + info.has_surface_bssrdf = (bytecode.find("\"bssrdf\"") != string::npos); loaded_shaders[hash] = info; return loaded_shaders.find(hash)->first.c_str(); @@ -511,6 +512,8 @@ void OSLCompiler::add(ShaderNode *node, const char *name, bool isfilepath) current_shader->has_surface_emission = true; if(info->has_surface_transparent) current_shader->has_surface_transparent = true; + if(info->has_surface_bssrdf) + current_shader->has_surface_bssrdf = true; } } @@ -671,6 +674,8 @@ void OSLCompiler::generate_nodes(const set<ShaderNode*>& nodes) current_shader->has_surface_emission = true; if(node->has_surface_transparent()) current_shader->has_surface_transparent = true; + if(node->has_surface_bssrdf()) + current_shader->has_surface_bssrdf = true; } else nodes_done = false; @@ -736,6 +741,7 @@ void OSLCompiler::compile(OSLGlobals *og, Shader *shader) shader->has_surface = false; shader->has_surface_emission = false; shader->has_surface_transparent = false; + shader->has_surface_bssrdf = false; shader->has_volume = false; shader->has_displacement = false; diff --git a/intern/cycles/render/osl.h b/intern/cycles/render/osl.h index 4b4ed6cba00..2d3996df0eb 100644 --- a/intern/cycles/render/osl.h +++ b/intern/cycles/render/osl.h @@ -50,11 +50,13 @@ class ShaderOutput; struct OSLShaderInfo { OSLShaderInfo() - : has_surface_emission(false), has_surface_transparent(false) + : has_surface_emission(false), has_surface_transparent(false), + has_surface_bssrdf(false) {} bool has_surface_emission; bool has_surface_transparent; + bool has_surface_bssrdf; }; /* Shader Manage */ @@ -69,7 +71,7 @@ public: bool use_osl() { return true; } void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); - void device_free(Device *device, DeviceScene *dscene); + void device_free(Device *device, DeviceScene *dscene, Scene *scene); /* osl compile and query */ static bool osl_compile(const string& inputfile, const string& outputfile); diff --git a/intern/cycles/render/scene.cpp b/intern/cycles/render/scene.cpp index 7b82a91cae8..a6dca62ffd0 100644 --- a/intern/cycles/render/scene.cpp +++ b/intern/cycles/render/scene.cpp @@ -20,19 +20,19 @@ #include "background.h" #include "camera.h" +#include "curves.h" #include "device.h" #include "film.h" -#include "filter.h" #include "integrator.h" #include "light.h" -#include "shader.h" #include "mesh.h" #include "object.h" +#include "osl.h" #include "particles.h" -#include "curves.h" #include "scene.h" +#include "shader.h" #include "svm.h" -#include "osl.h" +#include "tables.h" #include "util_foreach.h" #include "util_progress.h" @@ -46,7 +46,7 @@ Scene::Scene(const SceneParams& params_, const DeviceInfo& device_info_) memset(&dscene.data, 0, sizeof(dscene.data)); camera = new Camera(); - filter = new Filter(); + lookup_tables = new LookupTables(); film = new Film(); background = new Background(); light_manager = new LightManager(); @@ -93,14 +93,13 @@ void Scene::free_memory(bool final) if(device) { camera->device_free(device, &dscene); - filter->device_free(device, &dscene); - film->device_free(device, &dscene); + film->device_free(device, &dscene, this); background->device_free(device, &dscene); integrator->device_free(device, &dscene); object_manager->device_free(device, &dscene); mesh_manager->device_free(device, &dscene); - shader_manager->device_free(device, &dscene); + shader_manager->device_free(device, &dscene, this); light_manager->device_free(device, &dscene); particle_system_manager->device_free(device, &dscene); @@ -108,10 +107,12 @@ void Scene::free_memory(bool final) if(!params.persistent_data || final) image_manager->device_free(device, &dscene); + + lookup_tables->device_free(device, &dscene); } if(final) { - delete filter; + delete lookup_tables; delete camera; delete film; delete background; @@ -188,13 +189,8 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel()) return; - progress.set_status("Updating Filter"); - filter->device_update(device, &dscene); - - if(progress.get_cancel()) return; - progress.set_status("Updating Film"); - film->device_update(device, &dscene); + film->device_update(device, &dscene, this); if(progress.get_cancel()) return; @@ -203,6 +199,11 @@ void Scene::device_update(Device *device_, Progress& progress) if(progress.get_cancel()) return; + progress.set_status("Updating Lookup Tables"); + lookup_tables->device_update(device, &dscene); + + if(progress.get_cancel()) return; + progress.set_status("Updating Device", "Writing constant memory"); device->const_copy_to("__data", &dscene.data, sizeof(dscene.data)); } @@ -247,7 +248,7 @@ bool Scene::need_reset() || object_manager->need_update || mesh_manager->need_update || light_manager->need_update - || filter->need_update + || lookup_tables->need_update || integrator->need_update || shader_manager->need_update || particle_system_manager->need_update @@ -261,7 +262,6 @@ void Scene::reset() /* ensure all objects are updated */ camera->tag_update(); - filter->tag_update(this); film->tag_update(this); background->tag_update(this); integrator->tag_update(this); diff --git a/intern/cycles/render/scene.h b/intern/cycles/render/scene.h index fc6b538af03..545a765cc22 100644 --- a/intern/cycles/render/scene.h +++ b/intern/cycles/render/scene.h @@ -39,10 +39,10 @@ class Camera; class Device; class DeviceInfo; class Film; -class Filter; class Integrator; class Light; class LightManager; +class LookupTables; class Mesh; class MeshManager; class Object; @@ -99,8 +99,8 @@ public: device_vector<uint> shader_flag; device_vector<uint> object_flag; - /* filter */ - device_vector<float> filter_table; + /* lookup tables */ + device_vector<float> lookup_table; /* integrator */ device_vector<uint> sobol_directions; @@ -155,7 +155,7 @@ class Scene { public: /* data */ Camera *camera; - Filter *filter; + LookupTables *lookup_tables; Film *film; Background *background; Integrator *integrator; diff --git a/intern/cycles/render/shader.cpp b/intern/cycles/render/shader.cpp index b9b49bf2989..c7f39b4151a 100644 --- a/intern/cycles/render/shader.cpp +++ b/intern/cycles/render/shader.cpp @@ -16,6 +16,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include "bssrdf.h" #include "device.h" #include "graph.h" #include "light.h" @@ -25,6 +26,7 @@ #include "scene.h" #include "shader.h" #include "svm.h" +#include "tables.h" #include "util_foreach.h" @@ -46,6 +48,7 @@ Shader::Shader() has_surface = false; has_surface_transparent = false; has_surface_emission = false; + has_surface_bssrdf = false; has_volume = false; has_displacement = false; @@ -115,6 +118,7 @@ void Shader::tag_used(Scene *scene) ShaderManager::ShaderManager() { need_update = true; + bssrdf_table_offset = TABLE_OFFSET_INVALID; } ShaderManager::~ShaderManager() @@ -196,7 +200,8 @@ void ShaderManager::device_update_shaders_used(Scene *scene) void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) { - device_free_common(device, dscene); + device->tex_free(dscene->shader_flag); + dscene->shader_flag.clear(); if(scene->shaders.size() == 0) return; @@ -204,6 +209,7 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc uint shader_flag_size = scene->shaders.size()*4; uint *shader_flag = dscene->shader_flag.resize(shader_flag_size); uint i = 0; + bool has_surface_bssrdf = false; foreach(Shader *shader, scene->shaders) { uint flag = 0; @@ -216,6 +222,8 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc flag |= SD_HAS_VOLUME; if(shader->homogeneous_volume) flag |= SD_HOMOGENEOUS_VOLUME; + if(shader->has_surface_bssrdf) + has_surface_bssrdf = true; shader_flag[i++] = flag; shader_flag[i++] = shader->pass_id; @@ -224,10 +232,32 @@ void ShaderManager::device_update_common(Device *device, DeviceScene *dscene, Sc } device->tex_alloc("__shader_flag", dscene->shader_flag); + + /* bssrdf lookup table */ + KernelBSSRDF *kbssrdf = &dscene->data.bssrdf; + + if(has_surface_bssrdf && bssrdf_table_offset == TABLE_OFFSET_INVALID) { + vector<float> table; + + bssrdf_table_build(table); + bssrdf_table_offset = scene->lookup_tables->add_table(dscene, table); + + kbssrdf->table_offset = (int)bssrdf_table_offset; + kbssrdf->num_attempts = BSSRDF_MAX_ATTEMPTS; + } + else if(!has_surface_bssrdf && bssrdf_table_offset != TABLE_OFFSET_INVALID) { + scene->lookup_tables->remove_table(bssrdf_table_offset); + bssrdf_table_offset = TABLE_OFFSET_INVALID; + } } -void ShaderManager::device_free_common(Device *device, DeviceScene *dscene) +void ShaderManager::device_free_common(Device *device, DeviceScene *dscene, Scene *scene) { + if(bssrdf_table_offset != TABLE_OFFSET_INVALID) { + scene->lookup_tables->remove_table(bssrdf_table_offset); + bssrdf_table_offset = TABLE_OFFSET_INVALID; + } + device->tex_free(dscene->shader_flag); dscene->shader_flag.clear(); } diff --git a/intern/cycles/render/shader.h b/intern/cycles/render/shader.h index b38e098e3cb..2a9f1198467 100644 --- a/intern/cycles/render/shader.h +++ b/intern/cycles/render/shader.h @@ -75,6 +75,7 @@ public: bool has_surface_transparent; bool has_volume; bool has_displacement; + bool has_surface_bssrdf; /* requested mesh attributes */ AttributeRequestSet attributes; @@ -116,11 +117,11 @@ public: /* device update */ virtual void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress) = 0; - virtual void device_free(Device *device, DeviceScene *dscene) = 0; + virtual void device_free(Device *device, DeviceScene *dscene, Scene *scene) = 0; void device_update_shaders_used(Scene *scene); void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); - void device_free_common(Device *device, DeviceScene *dscene); + void device_free_common(Device *device, DeviceScene *dscene, Scene *scene); /* get globally unique id for a type of attribute */ uint get_attribute_id(ustring name); @@ -138,6 +139,8 @@ protected: typedef unordered_map<ustring, uint, ustringHash> AttributeIDMap; AttributeIDMap unique_attribute_id; + + size_t bssrdf_table_offset; }; CCL_NAMESPACE_END diff --git a/intern/cycles/render/svm.cpp b/intern/cycles/render/svm.cpp index 5cb11a4ec1a..ea2fe4991db 100644 --- a/intern/cycles/render/svm.cpp +++ b/intern/cycles/render/svm.cpp @@ -50,7 +50,7 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene return; /* test if we need to update */ - device_free(device, dscene); + device_free(device, dscene, scene); /* determine which shaders are in use */ device_update_shaders_used(scene); @@ -99,9 +99,9 @@ void SVMShaderManager::device_update(Device *device, DeviceScene *dscene, Scene need_update = false; } -void SVMShaderManager::device_free(Device *device, DeviceScene *dscene) +void SVMShaderManager::device_free(Device *device, DeviceScene *dscene, Scene *scene) { - device_free_common(device, dscene); + device_free_common(device, dscene, scene); device->tex_free(dscene->svm_nodes); dscene->svm_nodes.clear(); @@ -486,6 +486,8 @@ void SVMCompiler::generate_closure(ShaderNode *node, set<ShaderNode*>& done) current_shader->has_surface_emission = true; if(node->has_surface_transparent()) current_shader->has_surface_transparent = true; + if(node->has_surface_bssrdf()) + current_shader->has_surface_bssrdf = true; /* end node is added outside of this */ } @@ -546,6 +548,8 @@ void SVMCompiler::generate_multi_closure(ShaderNode *node, set<ShaderNode*>& don current_shader->has_surface_emission = true; if(node->has_surface_transparent()) current_shader->has_surface_transparent = true; + if(node->has_surface_bssrdf()) + current_shader->has_surface_bssrdf = true; } done.insert(node); @@ -654,6 +658,7 @@ void SVMCompiler::compile(Shader *shader, vector<int4>& global_svm_nodes, int in shader->has_surface = false; shader->has_surface_emission = false; shader->has_surface_transparent = false; + shader->has_surface_bssrdf = false; shader->has_volume = false; shader->has_displacement = false; diff --git a/intern/cycles/render/svm.h b/intern/cycles/render/svm.h index c1ce619e12a..e09144a4e76 100644 --- a/intern/cycles/render/svm.h +++ b/intern/cycles/render/svm.h @@ -48,7 +48,7 @@ public: void reset(Scene *scene); void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress& progress); - void device_free(Device *device, DeviceScene *dscene); + void device_free(Device *device, DeviceScene *dscene, Scene *scene); }; /* Graph Compiler */ diff --git a/intern/cycles/render/tables.cpp b/intern/cycles/render/tables.cpp new file mode 100644 index 00000000000..c7c86f68960 --- /dev/null +++ b/intern/cycles/render/tables.cpp @@ -0,0 +1,110 @@ +/* + * Copyright 2011, Blender Foundation. + * + * 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. + */ + +#include "device.h" +#include "scene.h" +#include "tables.h" + +#include "util_debug.h" + +CCL_NAMESPACE_BEGIN + +/* Lookup Tables */ + +LookupTables::LookupTables() +{ + need_update = true; +} + +LookupTables::~LookupTables() +{ + assert(lookup_tables.size() == 0); +} + +void LookupTables::device_update(Device *device, DeviceScene *dscene) +{ + if(!need_update) + return; + + device->tex_alloc("__lookup_table", dscene->lookup_table); + + need_update = false; +} + +void LookupTables::device_free(Device *device, DeviceScene *dscene) +{ + device->tex_free(dscene->lookup_table); + dscene->lookup_table.clear(); +} + +static size_t round_up_to_multiple(size_t size, size_t chunk) +{ + return ((size + chunk - 1)/chunk) * chunk; +} + +size_t LookupTables::add_table(DeviceScene *dscene, vector<float>& data) +{ + assert(data.size() > 0); + + need_update = true; + + Table new_table; + new_table.offset = 0; + new_table.size = round_up_to_multiple(data.size(), TABLE_CHUNK_SIZE); + + /* find space to put lookup table */ + list<Table>::iterator table; + + for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) { + if(new_table.offset + new_table.size <= table->offset) { + lookup_tables.insert(table, new_table); + break; + } + else + new_table.offset = table->offset + table->size; + } + + if(table == lookup_tables.end()) { + /* add at the end */ + lookup_tables.push_back(new_table); + dscene->lookup_table.resize(new_table.offset + new_table.size); + } + + /* copy table data and return offset */ + dscene->lookup_table.copy_at(&data[0], new_table.offset, data.size()); + return new_table.offset; +} + +void LookupTables::remove_table(size_t offset) +{ + need_update = true; + + list<Table>::iterator table; + + for(table = lookup_tables.begin(); table != lookup_tables.end(); table++) { + if(table->offset == offset) { + lookup_tables.erase(table); + break; + } + } + + assert(table != lookup_tables.end()); +} + +CCL_NAMESPACE_END + diff --git a/intern/cycles/render/filter.h b/intern/cycles/render/tables.h index 5df7bb8fd14..605efd3747f 100644 --- a/intern/cycles/render/filter.h +++ b/intern/cycles/render/tables.h @@ -16,8 +16,10 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __FILTER_H__ -#define __FILTER_H__ +#ifndef __TABLES_H__ +#define __TABLES_H__ + +#include <util_list.h> CCL_NAMESPACE_BEGIN @@ -25,29 +27,30 @@ class Device; class DeviceScene; class Scene; -typedef enum FilterType { - FILTER_BOX, - FILTER_GAUSSIAN -} FilterType; +enum { TABLE_CHUNK_SIZE = 256 }; +enum { TABLE_OFFSET_INVALID = -1 }; -class Filter { +class LookupTables { public: - /* pixel filter */ - FilterType filter_type; - float filter_width; + struct Table { + size_t offset; + size_t size; + }; + bool need_update; + list<Table> lookup_tables; - Filter(); - ~Filter(); + LookupTables(); + ~LookupTables(); void device_update(Device *device, DeviceScene *dscene); void device_free(Device *device, DeviceScene *dscene); - bool modified(const Filter& filter); - void tag_update(Scene *scene); + size_t add_table(DeviceScene *dscene, vector<float>& data); + void remove_table(size_t offset); }; CCL_NAMESPACE_END -#endif /* __FILTER_H__ */ +#endif /* __TABLES_H__ */ diff --git a/intern/cycles/util/util_math.h b/intern/cycles/util/util_math.h index c37fa1a4dc6..f2e814527fd 100644 --- a/intern/cycles/util/util_math.h +++ b/intern/cycles/util/util_math.h @@ -1151,14 +1151,7 @@ __device float safe_logf(float a, float b) __device float safe_divide(float a, float b) { - float result; - - if(b == 0.0f) - result = 0.0f; - else - result = a/b; - - return result; + return (b != 0.0f)? a/b: 0.0f; } /* Ray Intersection */ diff --git a/intern/ffmpeg/ffmpeg_compat.h b/intern/ffmpeg/ffmpeg_compat.h index 69e2e014761..aaedbe2dccd 100644 --- a/intern/ffmpeg/ffmpeg_compat.h +++ b/intern/ffmpeg/ffmpeg_compat.h @@ -171,6 +171,20 @@ void av_update_cur_dts(AVFormatContext *s, AVStream *ref_st, int64_t timestamp) } #endif +#if ((LIBAVCODEC_VERSION_MAJOR < 54) || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR < 28)) +static inline +void avcodec_free_frame(AVFrame **frame) +{ + /* don't need to do anything with old AVFrame + * since it does not have malloced members */ + (void)frame; +} +#endif + +#if ((LIBAVCODEC_VERSION_MAJOR > 54) || (LIBAVCODEC_VERSION_MAJOR == 54 && LIBAVCODEC_VERSION_MINOR >= 13)) +#define FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT +#endif + #ifndef FFMPEG_HAVE_AVIO #define AVIO_FLAG_WRITE URL_WRONLY #define avio_open url_fopen diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm index 795b5200ae2..61b853d79b0 100644 --- a/intern/ghost/intern/GHOST_WindowCocoa.mm +++ b/intern/ghost/intern/GHOST_WindowCocoa.mm @@ -454,7 +454,7 @@ GHOST_WindowCocoa::GHOST_WindowCocoa( GHOST_TDrawingContextType type, const bool stereoVisual, const GHOST_TUns16 numOfAASamples ) : - GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, numOfAASamples), + GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone, stereoVisual, false, numOfAASamples), m_customCursor(0) { NSOpenGLPixelFormatAttribute pixelFormatAttrsWindow[40]; diff --git a/intern/ghost/intern/GHOST_WindowNULL.h b/intern/ghost/intern/GHOST_WindowNULL.h index e3d092101b0..f595fa7d794 100644 --- a/intern/ghost/intern/GHOST_WindowNULL.h +++ b/intern/ghost/intern/GHOST_WindowNULL.h @@ -53,7 +53,7 @@ public: const bool stereoVisual, const GHOST_TUns16 numOfAASamples ) : - GHOST_Window(width, height, state, type, stereoVisual, numOfAASamples), + GHOST_Window(width, height, state, type, stereoVisual, false, numOfAASamples), m_system(system) { setTitle(title); diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index b1a9ca52605..2b1bdfa78f0 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -130,7 +130,7 @@ GHOST_WindowWin32::GHOST_WindowWin32( int msPixelFormat) : GHOST_Window(width, height, state, GHOST_kDrawingContextTypeNone, - stereoVisual, numOfAASamples), + stereoVisual, false, numOfAASamples), m_system(system), m_hDC(0), m_hGlRc(0), diff --git a/intern/opencolorio/CMakeLists.txt b/intern/opencolorio/CMakeLists.txt index 5680ce79762..30a74baa646 100644 --- a/intern/opencolorio/CMakeLists.txt +++ b/intern/opencolorio/CMakeLists.txt @@ -44,6 +44,7 @@ set(SRC if(WITH_OPENCOLORIO) add_definitions( -DWITH_OCIO + -DGLEW_STATIC ) list(APPEND INC_SYS diff --git a/intern/opencolorio/SConscript b/intern/opencolorio/SConscript index 73a8fd7a2e0..7f050f25cae 100644 --- a/intern/opencolorio/SConscript +++ b/intern/opencolorio/SConscript @@ -30,7 +30,7 @@ Import('env') sources = env.Glob('*.cc') incs = '. ../guardedalloc ../../source/blender/blenlib' -defs = [] +defs = [ 'GLEW_STATIC' ] if env['WITH_BF_OCIO']: defs.append('WITH_OCIO') diff --git a/intern/opencolorio/fallback_impl.cc b/intern/opencolorio/fallback_impl.cc index 47c648e9cba..37f624e1f8b 100644 --- a/intern/opencolorio/fallback_impl.cc +++ b/intern/opencolorio/fallback_impl.cc @@ -381,8 +381,9 @@ void FallbackImpl::matrixTransformScale(float * , float * , const float *) { } -void FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor) +bool FallbackImpl::setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide) { + return false; } void FallbackImpl::finishGLSLDraw(OCIO_GLSLDrawState *state) diff --git a/intern/opencolorio/ocio_capi.cc b/intern/opencolorio/ocio_capi.cc index 73d8af295f2..c8db2c2b531 100644 --- a/intern/opencolorio/ocio_capi.cc +++ b/intern/opencolorio/ocio_capi.cc @@ -283,9 +283,9 @@ void OCIO_matrixTransformScale(float * m44, float * offset4, const float *scale4 impl->matrixTransformScale(m44, offset4, scale4f); } -void OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor) +int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide) { - impl->setupGLSLDraw(state_r, processor); + return (int) impl->setupGLSLDraw(state_r, processor, (bool) predivide); } void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state) diff --git a/intern/opencolorio/ocio_capi.h b/intern/opencolorio/ocio_capi.h index 3c42e0a1a1e..3632a0da1c6 100644 --- a/intern/opencolorio/ocio_capi.h +++ b/intern/opencolorio/ocio_capi.h @@ -121,7 +121,7 @@ void OCIO_matrixTransformRelease(OCIO_MatrixTransformRcPtr *mt); void OCIO_matrixTransformScale(float * m44, float * offset4, const float * scale4); -void OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor); +int OCIO_setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, int predivide); void OCIO_finishGLSLDraw(struct OCIO_GLSLDrawState *state); void OCIO_freeOGLState(struct OCIO_GLSLDrawState *state); diff --git a/intern/opencolorio/ocio_impl.cc b/intern/opencolorio/ocio_impl.cc index 8803814ce3f..05c29fd5854 100644 --- a/intern/opencolorio/ocio_impl.cc +++ b/intern/opencolorio/ocio_impl.cc @@ -551,228 +551,3 @@ void OCIOImpl::matrixTransformScale(float * m44, float * offset4, const float *s { MatrixTransform::Scale(m44, offset4, scale4f); } - -/* **** OpenGL drawing routines using GLSL for color space transform ***** */ - -/* Some of the GLSL transform related functions below are adopted from - * ociodisplay utility of OpenColorIO project which are originally - * - * Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved. - */ - -typedef struct OCIO_GLSLDrawState { - bool lut3d_texture_allocated; /* boolean flag indicating whether - * lut texture is allocated - */ - - GLuint lut3d_texture; /* OGL texture ID for 3D LUT */ - - float *lut3d; /* 3D LUT table */ - - /* Cache */ - std::string lut3dcacheid; - std::string shadercacheid; - - /* GLSL stuff */ - GLuint fragShader; - GLuint program; - - /* Previous OpenGL state. */ - GLint last_texture, last_texture_unit; -} OCIO_GLSLDrawState; - -static const char * g_fragShaderText = "" -"\n" -"uniform sampler2D tex1;\n" -"uniform sampler3D tex2;\n" -"\n" -"void main()\n" -"{\n" -" vec4 col = texture2D(tex1, gl_TexCoord[0].st);\n" -" gl_FragColor = OCIODisplay(col, tex2);\n" -"}\n"; - -static GLuint compileShaderText(GLenum shaderType, const char *text) -{ - GLuint shader; - GLint stat; - - shader = glCreateShader(shaderType); - glShaderSource(shader, 1, (const GLchar **) &text, NULL); - glCompileShader(shader); - glGetShaderiv(shader, GL_COMPILE_STATUS, &stat); - - if (!stat) { - GLchar log[1000]; - GLsizei len; - glGetShaderInfoLog(shader, 1000, &len, log); - return 0; - } - - return shader; -} - -static GLuint linkShaders(GLuint fragShader) -{ - if (!fragShader) - return 0; - - GLuint program = glCreateProgram(); - - if (fragShader) - glAttachShader(program, fragShader); - - glLinkProgram(program); - - /* check link */ - { - GLint stat; - glGetProgramiv(program, GL_LINK_STATUS, &stat); - if (!stat) { - GLchar log[1000]; - GLsizei len; - glGetProgramInfoLog(program, 1000, &len, log); - fprintf(stderr, "Shader link error:\n%s\n", log); - return 0; - } - } - - return program; -} - -static OCIO_GLSLDrawState *allocateOpenGLState(void) -{ - OCIO_GLSLDrawState *state; - - /* Allocate memory for state. */ - state = (OCIO_GLSLDrawState *) MEM_callocN(sizeof(OCIO_GLSLDrawState), - "OCIO OpenGL State struct"); - - /* Call constructors on new memory. */ - new (&state->lut3dcacheid) std::string(""); - new (&state->shadercacheid) std::string(""); - - return state; -} - -/* Ensure LUT texture and array are allocated */ -static void ensureLUT3DAllocated(OCIO_GLSLDrawState *state) -{ - int num_3d_entries = 3 * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE * LUT3D_EDGE_SIZE; - - if (state->lut3d_texture_allocated) - return; - - glGenTextures(1, &state->lut3d_texture); - - state->lut3d = (float *) MEM_callocN(sizeof(float) * num_3d_entries, "OCIO GPU 3D LUT"); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_3D, state->lut3d_texture); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); - glTexImage3D(GL_TEXTURE_3D, 0, GL_RGB16F_ARB, - LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, - 0, GL_RGB,GL_FLOAT, &state->lut3d); - - state->lut3d_texture_allocated = true; -} - -/** - * Setup OpenGL contexts for a transform defined by processor using GLSL - * All LUT allocating baking and shader compilation happens here. - * - * Once this function is called, callee could start drawing images - * using regular 2D texture. - * - * When all drawing is finished, finishGLSLDraw shall be called to - * restore OpenGL context to it's pre-GLSL draw state. - */ -void OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor) -{ - ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor; - - /* Create state if needed. */ - OCIO_GLSLDrawState *state; - if (!*state_r) - *state_r = allocateOpenGLState(); - state = *state_r; - - glGetIntegerv(GL_TEXTURE_2D, &state->last_texture); - glGetIntegerv(GL_ACTIVE_TEXTURE, &state->last_texture_unit); - - ensureLUT3DAllocated(state); - - /* Step 1: Create a GPU Shader Description */ - GpuShaderDesc shaderDesc; - shaderDesc.setLanguage(GPU_LANGUAGE_GLSL_1_0); - shaderDesc.setFunctionName("OCIODisplay"); - shaderDesc.setLut3DEdgeLen(LUT3D_EDGE_SIZE); - - /* Step 2: Compute the 3D LUT */ - std::string lut3dCacheID = ocio_processor->getGpuLut3DCacheID(shaderDesc); - if (lut3dCacheID != state->lut3dcacheid) { - state->lut3dcacheid = lut3dCacheID; - ocio_processor->getGpuLut3D(state->lut3d, shaderDesc); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_3D, state->lut3d_texture); - glTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, - LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, LUT3D_EDGE_SIZE, - GL_RGB, GL_FLOAT, state->lut3d); - } - - /* Step 3: Compute the Shader */ - std::string shaderCacheID = ocio_processor->getGpuShaderTextCacheID(shaderDesc); - if (state->program == 0 || shaderCacheID != state->shadercacheid) { - state->shadercacheid = shaderCacheID; - - std::ostringstream os; - os << ocio_processor->getGpuShaderText(shaderDesc) << "\n"; - os << g_fragShaderText; - - if (state->fragShader) - glDeleteShader(state->fragShader); - state->fragShader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str()); - - if (state->program) - glDeleteProgram(state->program); - - state->program = linkShaders(state->fragShader); - } - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_3D, state->lut3d_texture); - - glActiveTexture(GL_TEXTURE0); - - glUseProgram(state->program); - glUniform1i(glGetUniformLocation(state->program, "tex1"), 0); - glUniform1i(glGetUniformLocation(state->program, "tex2"), 1); -} - -void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState *state) -{ - glActiveTexture(state->last_texture_unit); - glBindTexture(GL_TEXTURE_2D, state->last_texture); - glUseProgram(0); -} - -void OCIOImpl::freeGLState(struct OCIO_GLSLDrawState *state) -{ - using std::string; - - if (state->lut3d_texture_allocated) - glDeleteTextures(1, &state->lut3d_texture); - - if (state->lut3d) - MEM_freeN(state->lut3d); - - state->lut3dcacheid.~string(); - state->shadercacheid.~string(); - - MEM_freeN(state); -} diff --git a/intern/opencolorio/ocio_impl.h b/intern/opencolorio/ocio_impl.h index 2a1f88be5f4..a328470ccb5 100644 --- a/intern/opencolorio/ocio_impl.h +++ b/intern/opencolorio/ocio_impl.h @@ -96,7 +96,7 @@ public: virtual void matrixTransformScale(float * m44, float * offset4, const float * scale4) = 0; - virtual void setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor) = 0; + virtual bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide) = 0; virtual void finishGLSLDraw(struct OCIO_GLSLDrawState *state) = 0; virtual void freeGLState(struct OCIO_GLSLDrawState *state_r) = 0; }; @@ -169,7 +169,7 @@ public: void matrixTransformScale(float * m44, float * offset4, const float * scale4); - void setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor); + bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide); void finishGLSLDraw(struct OCIO_GLSLDrawState *state); void freeGLState(struct OCIO_GLSLDrawState *state_r); }; @@ -243,7 +243,7 @@ public: void matrixTransformScale(float * m44, float * offset4, const float * scale4); - void setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor); + bool setupGLSLDraw(struct OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide); void finishGLSLDraw(struct OCIO_GLSLDrawState *state); void freeGLState(struct OCIO_GLSLDrawState *state_r); }; diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc index c79593779cf..9343a13e888 100644 --- a/intern/opencolorio/ocio_impl_glsl.cc +++ b/intern/opencolorio/ocio_impl_glsl.cc @@ -77,15 +77,33 @@ typedef struct OCIO_GLSLDrawState { GLint last_texture, last_texture_unit; } OCIO_GLSLDrawState; -static const char * g_fragShaderText = "" +/* Hardcoded to do alpha predivide before color space conversion */ +static const char *g_fragShaderText = "" "\n" "uniform sampler2D tex1;\n" "uniform sampler3D tex2;\n" +"uniform bool predivide;\n" "\n" "void main()\n" "{\n" " vec4 col = texture2D(tex1, gl_TexCoord[0].st);\n" -" gl_FragColor = OCIODisplay(col, tex2);\n" +" if (predivide == false || col[3] == 1.0f || col[3] == 0.0f) {\n" +" gl_FragColor = OCIODisplay(col, tex2);\n" +" } else {\n" +" float alpha = col[3];\n" +" float inv_alpha = 1.0f / alpha;\n" +"\n" +" col[0] *= inv_alpha;\n" +" col[1] *= inv_alpha;\n" +" col[2] *= inv_alpha;\n" +"\n" +" gl_FragColor = OCIODisplay(col, tex2);\n" +"\n" +" col[0] *= alpha;\n" +" col[1] *= alpha;\n" +" col[2] *= alpha;\n" +" }\n" +"\n" "}\n"; static GLuint compileShaderText(GLenum shaderType, const char *text) @@ -187,7 +205,7 @@ static void ensureLUT3DAllocated(OCIO_GLSLDrawState *state) * When all drawing is finished, finishGLSLDraw shall be called to * restore OpenGL context to it's pre-GLSL draw state. */ -void OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor) +bool OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRcPtr *processor, bool predivide) { ConstProcessorRcPtr ocio_processor = *(ConstProcessorRcPtr *) processor; @@ -232,22 +250,36 @@ void OCIOImpl::setupGLSLDraw(OCIO_GLSLDrawState **state_r, OCIO_ConstProcessorRc if (state->fragShader) glDeleteShader(state->fragShader); + state->fragShader = compileShaderText(GL_FRAGMENT_SHADER, os.str().c_str()); - if (state->program) - glDeleteProgram(state->program); + if (state->fragShader) { + if (state->program) + glDeleteProgram(state->program); - state->program = linkShaders(state->fragShader); + state->program = linkShaders(state->fragShader); + } } - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_3D, state->lut3d_texture); + if (state->program) { + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_3D, state->lut3d_texture); + + glActiveTexture(GL_TEXTURE0); + + glUseProgram(state->program); + glUniform1i(glGetUniformLocation(state->program, "tex1"), 0); + glUniform1i(glGetUniformLocation(state->program, "tex2"), 1); + glUniform1i(glGetUniformLocation(state->program, "predivide"), predivide); - glActiveTexture(GL_TEXTURE0); + return true; + } + else { + glActiveTexture(state->last_texture_unit); + glBindTexture(GL_TEXTURE_2D, state->last_texture); - glUseProgram(state->program); - glUniform1i(glGetUniformLocation(state->program, "tex1"), 0); - glUniform1i(glGetUniformLocation(state->program, "tex2"), 1); + return false; + } } void OCIOImpl::finishGLSLDraw(OCIO_GLSLDrawState *state) @@ -267,6 +299,12 @@ void OCIOImpl::freeGLState(struct OCIO_GLSLDrawState *state) if (state->lut3d) MEM_freeN(state->lut3d); + if (state->program) + glDeleteProgram(state->program); + + if (state->fragShader) + glDeleteShader(state->fragShader); + state->lut3dcacheid.~string(); state->shadercacheid.~string(); diff --git a/release/datafiles/colormanagement/config.ocio b/release/datafiles/colormanagement/config.ocio index d73561338ba..2d5f68f0a45 100644 --- a/release/datafiles/colormanagement/config.ocio +++ b/release/datafiles/colormanagement/config.ocio @@ -66,7 +66,7 @@ colorspaces: Rec. 709 (Full Range), Blender native linear space isdata: false allocation: lg2 - allocationvars: [-8.5, 5] + allocationvars: [-15, 6] - !<ColorSpace> name: Raw diff --git a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py index 3dbddc30f0d..9daddfe5dc4 100644 --- a/release/scripts/modules/bl_i18n_utils/utils_spell_check.py +++ b/release/scripts/modules/bl_i18n_utils/utils_spell_check.py @@ -296,6 +296,7 @@ class SpellChecker(): "spacebar", "tooltip", "tooltips", "trackpad", + "tuple", "unicode", "viewport", "viewports", "viscoelastic", @@ -437,6 +438,7 @@ class SpellChecker(): "ascii", "atrac", "bsdf", + "bssrdf", "bw", "ccd", "cmd", diff --git a/release/scripts/startup/bl_ui/properties_object.py b/release/scripts/startup/bl_ui/properties_object.py index c5dbe946012..7c32e72b3e3 100644 --- a/release/scripts/startup/bl_ui/properties_object.py +++ b/release/scripts/startup/bl_ui/properties_object.py @@ -204,36 +204,40 @@ class OBJECT_PT_display(ObjectButtonsPanel, Panel): def draw(self, context): layout = self.layout - ob = context.object + obj = context.object split = layout.split() col = split.column() - col.prop(ob, "draw_type", text="Type") + col.prop(obj, "draw_type", text="Type") col = split.column() row = col.row() - row.prop(ob, "show_bounds", text="Bounds") + row.prop(obj, "show_bounds", text="Bounds") sub = row.row() - sub.active = ob.show_bounds - sub.prop(ob, "draw_bounds_type", text="") + sub.active = obj.show_bounds + sub.prop(obj, "draw_bounds_type", text="") split = layout.split() col = split.column() - col.prop(ob, "show_name", text="Name") - col.prop(ob, "show_axis", text="Axis") - if ob.type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'}: + col.prop(obj, "show_name", text="Name") + col.prop(obj, "show_axis", text="Axis") + + obj_type = obj.type + + if obj_type in {'MESH', 'CURVE', 'SURFACE', 'META', 'FONT'}: # Makes no sense for cameras, armtures, etc.! - col.prop(ob, "show_wire", text="Wire") + col.prop(obj, "show_wire", text="Wire") # Only useful with object having faces/materials... - col.prop(ob, "color", text="Object Color") + col.prop(obj, "color", text="Object Color") col = split.column() - col.prop(ob, "show_texture_space", text="Texture Space") - col.prop(ob, "show_x_ray", text="X-Ray") - if ob.type == 'MESH': - col.prop(ob, "show_transparent", text="Transparency") - col.prop(ob, "show_all_edges") + col.prop(obj, "show_texture_space", text="Texture Space") + col.prop(obj, "show_x_ray", text="X-Ray") + if obj_type == 'MESH' or (obj_type == 'EMPTY' and obj.empty_draw_type == 'IMAGE'): + col.prop(obj, "show_transparent", text="Transparency") + if obj_type == 'MESH': + col.prop(obj, "show_all_edges") class OBJECT_PT_duplication(ObjectButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/space_clip.py b/release/scripts/startup/bl_ui/space_clip.py index 43761dd439e..d81356b3113 100644 --- a/release/scripts/startup/bl_ui/space_clip.py +++ b/release/scripts/startup/bl_ui/space_clip.py @@ -886,6 +886,7 @@ class CLIP_PT_tools_clip(CLIP_PT_clip_view_panel, Panel): layout.operator("clip.set_viewport_background") layout.operator("clip.setup_tracking_scene") + layout.operator("clip.prefetch") class CLIP_MT_view(Menu): @@ -945,6 +946,7 @@ class CLIP_MT_clip(Menu): layout.operator("clip.open") if clip: + layout.operator("clip.prefetch") layout.operator("clip.reload") layout.menu("CLIP_MT_proxy") diff --git a/release/scripts/startup/bl_ui/space_node.py b/release/scripts/startup/bl_ui/space_node.py index 26c76bd6655..ac76b988e05 100644 --- a/release/scripts/startup/bl_ui/space_node.py +++ b/release/scripts/startup/bl_ui/space_node.py @@ -151,10 +151,17 @@ class NODE_MT_select(Menu): layout.operator("node.select_all", text="Inverse").action = 'INVERT' layout.operator("node.select_linked_from") layout.operator("node.select_linked_to") + + layout.separator() + layout.operator("node.select_same_type") layout.operator("node.select_same_type_step").prev = True layout.operator("node.select_same_type_step").prev = False + layout.separator() + + layout.operator("node.find_node") + class NODE_MT_node(Menu): bl_label = "Node" diff --git a/source/blender/blenkernel/BKE_DerivedMesh.h b/source/blender/blenkernel/BKE_DerivedMesh.h index 0c988ac45fc..2cb9d42b479 100644 --- a/source/blender/blenkernel/BKE_DerivedMesh.h +++ b/source/blender/blenkernel/BKE_DerivedMesh.h @@ -247,6 +247,7 @@ struct DerivedMesh { void *(*getVertDataArray)(DerivedMesh *dm, int type); void *(*getEdgeDataArray)(DerivedMesh *dm, int type); void *(*getTessFaceDataArray)(DerivedMesh *dm, int type); + void *(*getLoopDataArray)(DerivedMesh *dm, int type); void *(*getPolyDataArray)(DerivedMesh *dm, int type); /** Retrieves the base CustomData structures for diff --git a/source/blender/blenkernel/BKE_group.h b/source/blender/blenkernel/BKE_group.h index 8c36a73a088..0f36b7a8cfc 100644 --- a/source/blender/blenkernel/BKE_group.h +++ b/source/blender/blenkernel/BKE_group.h @@ -41,18 +41,17 @@ struct Object; struct bAction; struct Scene; -void BKE_group_free(struct Group *group); -void BKE_group_unlink(struct Group *group); -struct Group *add_group(struct Main *bmain, const char *name); +void BKE_group_free(struct Group *group); +void BKE_group_unlink(struct Group *group); +struct Group *BKE_group_add(struct Main *bmain, const char *name); struct Group *BKE_group_copy(struct Group *group); -int add_to_group(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); -int rem_from_group(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); -struct Group *find_group(struct Object *ob, struct Group *group); -int object_in_group(struct Object *ob, struct Group *group); -int group_is_animated(struct Object *parent, struct Group *group); +bool BKE_group_object_add(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); +bool BKE_group_object_unlink(struct Group *group, struct Object *ob, struct Scene *scene, struct Base *base); +struct Group *BKE_group_object_find(struct Group *group, struct Object *ob); +bool BKE_group_object_exists(struct Group *group, struct Object *ob); +bool BKE_group_is_animated(struct Group *group, struct Object *parent); -void group_tag_recalc(struct Group *group); -void group_handle_recalc_and_update(struct Scene *scene, struct Object *parent, struct Group *group); - -#endif +void BKE_group_tag_recalc(struct Group *group); +void BKE_group_handle_recalc_and_update(struct Scene *scene, struct Object *parent, struct Group *group); +#endif /* __BKE_GROUP_H__ */ diff --git a/source/blender/blenkernel/BKE_library.h b/source/blender/blenkernel/BKE_library.h index 944b6e9b8c0..99247414cff 100644 --- a/source/blender/blenkernel/BKE_library.h +++ b/source/blender/blenkernel/BKE_library.h @@ -107,10 +107,12 @@ __attribute__((nonnull)) ; void clear_id_newpoins(void); +#if 0 void IDnames_to_pupstring(const char **str, const char *title, const char *extraops, struct ListBase *lb, struct ID *link, short *nr); void IMAnames_to_pupstring(const char **str, const char *title, const char *extraops, struct ListBase *lb, struct ID *link, short *nr); +#endif void flag_listbase_ids(ListBase *lb, short flag, short value); void flag_all_listbases_ids(short flag, short value); diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h index 350eaf23f6f..0bcbbb8576a 100644 --- a/source/blender/blenkernel/BKE_material.h +++ b/source/blender/blenkernel/BKE_material.h @@ -59,7 +59,8 @@ struct Material *give_node_material(struct Material *ma); /* returns node materi void BKE_material_make_local(struct Material *ma); void extern_local_matarar(struct Material **matar, short totcol); -void automatname(struct Material *); +/* UNUSED */ +// void automatname(struct Material *); /* material slots */ diff --git a/source/blender/blenkernel/BKE_movieclip.h b/source/blender/blenkernel/BKE_movieclip.h index f97b5b1f3a1..4828df2fbec 100644 --- a/source/blender/blenkernel/BKE_movieclip.h +++ b/source/blender/blenkernel/BKE_movieclip.h @@ -45,6 +45,7 @@ void BKE_movieclip_unlink(struct Main *bmain, struct MovieClip *clip); struct MovieClip *BKE_movieclip_file_add(struct Main *bmain, const char *name); void BKE_movieclip_reload(struct MovieClip *clip); +void BKE_movieclip_clear_cache(struct MovieClip *clip); struct ImBuf *BKE_movieclip_get_ibuf(struct MovieClip *clip, struct MovieClipUser *user); struct ImBuf *BKE_movieclip_get_postprocessed_ibuf(struct MovieClip *clip, struct MovieClipUser *user, int postprocess_flag); diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index fc1cd6e45d5..3c4c3fc6f5c 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -444,9 +444,6 @@ const char * nodeStaticSocketInterfaceType(int type, int subtype); BLI_ghashIterator_free(__node_socket_type_iter__); \ } -void nodeMakeDynamicType(struct bNode *node); -int nodeDynamicUnlinkText(struct ID *txtid); - struct bNodeSocket *nodeFindSocket(struct bNode *node, int in_out, const char *identifier); struct bNodeSocket *nodeAddSocket(struct bNodeTree *ntree, struct bNode *node, int in_out, const char *idname, const char *identifier, const char *name); @@ -575,9 +572,6 @@ void BKE_node_preview_set_pixel(struct bNodePreview *preview, const f /* ************** NODE TYPE ACCESS *************** */ const char *nodeLabel(struct bNode *node); -struct bNodeTree *nodeGroupEditGet(struct bNode *node); -struct bNodeTree *nodeGroupEditSet(struct bNode *node, int edit); -void nodeGroupEditClear(struct bNode *node); int nodeGroupPoll(struct bNodeTree *nodetree, struct bNodeTree *grouptree); @@ -752,6 +746,7 @@ struct ShadeResult; #define SH_NODE_TANGENT 174 #define SH_NODE_NORMAL_MAP 175 #define SH_NODE_HAIR_INFO 176 +#define SH_NODE_SUBSURFACE_SCATTERING 177 /* custom defines options for Material node */ #define SH_NODE_MAT_DIFF 1 diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 1009472cf40..2b753cba098 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -255,7 +255,8 @@ struct ParticleSystem *psys_get_current(struct Object *ob); /* for rna */ short psys_get_current_num(struct Object *ob); void psys_set_current_num(Object *ob, int index); -struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys); +/* UNUSED */ +// struct Object *psys_find_object(struct Scene *scene, struct ParticleSystem *psys); struct Object *psys_get_lattice(struct ParticleSimulationData *sim); diff --git a/source/blender/blenkernel/BKE_smoke.h b/source/blender/blenkernel/BKE_smoke.h index 3a9d2b86b41..20366f00df6 100644 --- a/source/blender/blenkernel/BKE_smoke.h +++ b/source/blender/blenkernel/BKE_smoke.h @@ -45,7 +45,6 @@ void smokeModifier_reset_turbulence(struct SmokeModifierData *smd); void smokeModifier_createType(struct SmokeModifierData *smd); void smokeModifier_copy(struct SmokeModifierData *smd, struct SmokeModifierData *tsmd); -long long smoke_get_mem_req(int xres, int yres, int zres, int amplify); float smoke_get_velocity_at(struct Object *ob, float position[3], float velocity[3]); int smoke_get_data_flags(struct SmokeDomainSettings *sds); diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h index 621fc13af67..23a6a96c75c 100644 --- a/source/blender/blenkernel/BKE_texture.h +++ b/source/blender/blenkernel/BKE_texture.h @@ -78,7 +78,8 @@ struct MTex *add_mtex_id(struct ID *id, int slot); struct Tex *BKE_texture_copy(struct Tex *tex); struct Tex *localize_texture(struct Tex *tex); void BKE_texture_make_local(struct Tex *tex); -void autotexname(struct Tex *tex); +/* UNUSED */ +// void autotexname(struct Tex *tex); struct Tex *give_current_object_texture(struct Object *ob); struct Tex *give_current_material_texture(struct Material *ma); diff --git a/source/blender/blenkernel/depsgraph_private.h b/source/blender/blenkernel/depsgraph_private.h index 14e7d220449..c8ce2bb2a77 100644 --- a/source/blender/blenkernel/depsgraph_private.h +++ b/source/blender/blenkernel/depsgraph_private.h @@ -124,7 +124,6 @@ void push_queue(DagNodeQueue *queue, DagNode *node); void push_stack(DagNodeQueue *queue, DagNode *node); DagNode *pop_queue(DagNodeQueue *queue); DagNode *get_top_node_queue(DagNodeQueue *queue); -int queue_count(DagNodeQueue *queue); void queue_delete(DagNodeQueue *queue); // Dag management @@ -137,9 +136,6 @@ DagNode *dag_get_node(DagForest *forest, void *fob); DagNode *dag_get_sub_node(DagForest *forest, void *fob); void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name); -DagNodeQueue *graph_dfs(void); - -void set_node_xy(DagNode *node, float x, float y); void graph_print_queue(DagNodeQueue *nqueue); void graph_print_queue_dist(DagNodeQueue *nqueue); void graph_print_adj_list(DagForest *dag); diff --git a/source/blender/blenkernel/intern/DerivedMesh.c b/source/blender/blenkernel/intern/DerivedMesh.c index f53743ea06e..bf29fd571c4 100644 --- a/source/blender/blenkernel/intern/DerivedMesh.c +++ b/source/blender/blenkernel/intern/DerivedMesh.c @@ -270,6 +270,7 @@ void DM_init_funcs(DerivedMesh *dm) dm->getEdgeDataArray = DM_get_edge_data_layer; dm->getTessFaceDataArray = DM_get_tessface_data_layer; dm->getPolyDataArray = DM_get_poly_data_layer; + dm->getLoopDataArray = DM_get_loop_data_layer; bvhcache_init(&dm->bvhCache); } diff --git a/source/blender/blenkernel/intern/anim.c b/source/blender/blenkernel/intern/anim.c index ad791852253..8c49ce22dea 100644 --- a/source/blender/blenkernel/intern/anim.c +++ b/source/blender/blenkernel/intern/anim.c @@ -766,10 +766,10 @@ static void group_duplilist(ListBase *lb, Scene *scene, Object *ob, int persiste if (flag & DUPLILIST_DO_UPDATE) { /* note: update is optional because we don't always need object * transformations to be correct. Also fixes bug [#29616]. */ - group_handle_recalc_and_update(scene, ob, group); + BKE_group_handle_recalc_and_update(scene, ob, group); } - if (group_is_animated(ob, group)) + if (BKE_group_is_animated(group, ob)) flag |= DUPLILIST_ANIMATED; for (go = group->gobject.first, id = 0; go; go = go->next, id++) { @@ -953,6 +953,7 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl float vec[3], no[3], pmat[4][4]; int totvert, a, oblay; unsigned int lay; + CustomDataMask dm_mask; copy_m4_m4(pmat, par->obmat); @@ -961,16 +962,18 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl em = BMEdit_FromObject(par); - if (em) { - dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); - } + /* get derived mesh */ + dm_mask = CD_MASK_BAREMESH; + if (flag & DUPLILIST_FOR_RENDER) + dm_mask |= CD_MASK_ORCO; + + if (em) + dm = editbmesh_get_derived_cage(scene, par, em, dm_mask); else - dm = mesh_get_derived_final(scene, par, CD_MASK_BAREMESH); + dm = mesh_get_derived_final(scene, par, dm_mask); - if (flag & DUPLILIST_FOR_RENDER) { - vdd.orco = (float(*)[3])BKE_mesh_orco_verts_get(par); - BKE_mesh_orco_verts_transform(me, vdd.orco, me->totvert, 0); - } + if (flag & DUPLILIST_FOR_RENDER) + vdd.orco = dm->getVertDataArray(dm, CD_ORCO); else vdd.orco = NULL; @@ -1057,8 +1060,6 @@ static void vertex_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, fl else go = go->next; /* group loop */ } - if (vdd.orco) - MEM_freeN(vdd.orco); dm->release(dm); } @@ -1069,7 +1070,6 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa Base *base = NULL; DupliObject *dob; DerivedMesh *dm; - Mesh *me = par->data; MLoopUV *mloopuv; MPoly *mpoly, *mp; MLoop *mloop; @@ -1081,6 +1081,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa GroupObject *go = NULL; BMEditMesh *em; float ob__obmat[4][4]; /* needed for groups where the object matrix needs to be modified */ + CustomDataMask dm_mask; /* simple preventing of too deep nested groups */ if (level > MAX_DUPLI_RECUR) return; @@ -1088,11 +1089,16 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa copy_m4_m4(pmat, par->obmat); em = BMEdit_FromObject(par); + /* get derived mesh */ + dm_mask = CD_MASK_BAREMESH; + if (flag & DUPLILIST_FOR_RENDER) + dm_mask |= CD_MASK_ORCO | CD_MASK_MLOOPUV; + if (em) { - dm = editbmesh_get_derived_cage(scene, par, em, CD_MASK_BAREMESH); + dm = editbmesh_get_derived_cage(scene, par, em, dm_mask); } else { - dm = mesh_get_derived_final(scene, par, CD_MASK_BAREMESH); + dm = mesh_get_derived_final(scene, par, dm_mask); } totface = dm->getNumPolys(dm); @@ -1101,9 +1107,8 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa mvert = dm->getVertArray(dm); if (flag & DUPLILIST_FOR_RENDER) { - orco = (float(*)[3])BKE_mesh_orco_verts_get(par); - BKE_mesh_orco_verts_transform(me, orco, me->totvert, 0); - mloopuv = me->mloopuv; + orco = dm->getVertDataArray(dm, CD_ORCO); + mloopuv = dm->getLoopDataArray(dm, CD_MLOOPUV); } else { orco = NULL; @@ -1215,7 +1220,7 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa if (mloopuv) { int j; for (j = 0; j < mpoly->totloop; j++) { - madd_v2_v2fl(dob->orco, mloopuv[loopstart[j].v].uv, w); + madd_v2_v2fl(dob->uv, mloopuv[mp->loopstart + j].uv, w); } } } @@ -1238,9 +1243,6 @@ static void face_duplilist(ListBase *lb, ID *id, Scene *scene, Object *par, floa else go = go->next; /* group loop */ } - if (orco) - MEM_freeN(orco); - dm->release(dm); } @@ -1331,7 +1333,7 @@ static void new_particle_duplilist(ListBase *lb, ID *id, Scene *scene, Object *p /* gather list of objects or single object */ if (part->ren_as == PART_DRAW_GR) { if (flag & DUPLILIST_DO_UPDATE) { - group_handle_recalc_and_update(scene, par, part->dup_group); + BKE_group_handle_recalc_and_update(scene, par, part->dup_group); } if (part->draw & PART_DRAW_COUNT_GR) { diff --git a/source/blender/blenkernel/intern/colortools.c b/source/blender/blenkernel/intern/colortools.c index 5176f93f4f3..04cc3cc6a09 100644 --- a/source/blender/blenkernel/intern/colortools.c +++ b/source/blender/blenkernel/intern/colortools.c @@ -1008,6 +1008,7 @@ void BKE_histogram_update_sample_line(Histogram *hist, ImBuf *ibuf, const ColorM IMB_colormanagement_processor_free(cm_processor); } +/* if view_settings, it also applies this to byte buffers */ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings *view_settings, const ColorManagedDisplaySettings *display_settings) { @@ -1021,7 +1022,7 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * float rgba[4], ycc[3], luma; int ycc_mode = -1; const short is_float = (ibuf->rect_float != NULL); - + void *cache_handle = NULL; struct ColormanageProcessor *cm_processor = NULL; if (ibuf->rect == NULL && ibuf->rect_float == NULL) return; @@ -1090,9 +1091,10 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * if (is_float) rf = ibuf->rect_float; - else - rc = (unsigned char *)ibuf->rect; - + else { + rc = (unsigned char *)IMB_display_buffer_acquire(ibuf, view_settings, display_settings, &cache_handle); + } + if (ibuf->rect_float) cm_processor = IMB_colormanagement_display_processor_new(view_settings, display_settings); @@ -1173,11 +1175,12 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * if (bin_b[x] > nb) nb = bin_b[x]; if (bin_a[x] > na) na = bin_a[x]; } - divl = 1.0 / (double)nl; - diva = 1.0 / (double)na; - divr = 1.0 / (double)nr; - divg = 1.0 / (double)ng; - divb = 1.0 / (double)nb; + divl = nl ? 1.0 / (double)nl : 1.0; + diva = na ? 1.0 / (double)na : 1.0; + divr = nr ? 1.0 / (double)nr : 1.0; + divg = ng ? 1.0 / (double)ng : 1.0; + divb = nb ? 1.0 / (double)nb : 1.0; + for (x = 0; x < 256; x++) { scopes->hist.data_luma[x] = bin_lum[x] * divl; scopes->hist.data_r[x] = bin_r[x] * divr; @@ -1193,7 +1196,9 @@ void scopes_update(Scopes *scopes, ImBuf *ibuf, const ColorManagedViewSettings * if (cm_processor) IMB_colormanagement_processor_free(cm_processor); - + if (cache_handle) + IMB_display_buffer_release(cache_handle); + scopes->ok = 1; } diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c index 4d9f0fc769c..12fa16e3273 100644 --- a/source/blender/blenkernel/intern/constraint.c +++ b/source/blender/blenkernel/intern/constraint.c @@ -1204,8 +1204,8 @@ static void followpath_get_tarmat(bConstraint *con, bConstraintOb *cob, bConstra vec_to_quat(quat, dir, (short)data->trackflag, (short)data->upflag); normalize_v3(dir); - q[0] = (float)cos(0.5 * vec[3]); - x1 = (float)sin(0.5 * vec[3]); + q[0] = cosf(0.5 * vec[3]); + x1 = sinf(0.5 * vec[3]); q[1] = -x1 * dir[0]; q[2] = -x1 * dir[1]; q[3] = -x1 * dir[2]; diff --git a/source/blender/blenkernel/intern/group.c b/source/blender/blenkernel/intern/group.c index 98d1d301f65..d0a9a6efe6b 100644 --- a/source/blender/blenkernel/intern/group.c +++ b/source/blender/blenkernel/intern/group.c @@ -95,7 +95,9 @@ void BKE_group_unlink(Group *group) /* ensure objects are not in this group */ for (; base; base = base->next) { - if (rem_from_group(group, base->object, sce, base) && find_group(base->object, NULL) == NULL) { + if (BKE_group_object_unlink(group, base->object, sce, base) && + BKE_group_object_find(NULL, base->object) == NULL) + { base->object->flag &= ~OB_FROMGROUP; base->flag &= ~OB_FROMGROUP; } @@ -132,7 +134,7 @@ void BKE_group_unlink(Group *group) group->id.us = 0; } -Group *add_group(Main *bmain, const char *name) +Group *BKE_group_add(Main *bmain, const char *name) { Group *group; @@ -152,7 +154,7 @@ Group *BKE_group_copy(Group *group) } /* external */ -static int add_to_group_internal(Group *group, Object *ob) +static int group_object_add_internal(Group *group, Object *ob) { GroupObject *go; @@ -173,9 +175,9 @@ static int add_to_group_internal(Group *group, Object *ob) return TRUE; } -int add_to_group(Group *group, Object *object, Scene *scene, Base *base) +bool BKE_group_object_add(Group *group, Object *object, Scene *scene, Base *base) { - if (add_to_group_internal(group, object)) { + if (group_object_add_internal(group, object)) { if ((object->flag & OB_FROMGROUP) == 0) { if (scene && base == NULL) @@ -186,15 +188,15 @@ int add_to_group(Group *group, Object *object, Scene *scene, Base *base) if (base) base->flag |= OB_FROMGROUP; } - return 1; + return true; } else { - return 0; + return false; } } /* also used for (ob == NULL) */ -static int rem_from_group_internal(Group *group, Object *ob) +static int group_object_unlink_internal(Group *group, Object *ob) { GroupObject *go, *gon; int removed = 0; @@ -214,11 +216,11 @@ static int rem_from_group_internal(Group *group, Object *ob) return removed; } -int rem_from_group(Group *group, Object *object, Scene *scene, Base *base) +bool BKE_group_object_unlink(Group *group, Object *object, Scene *scene, Base *base) { - if (rem_from_group_internal(group, object)) { + if (group_object_unlink_internal(group, object)) { /* object can be NULL */ - if (object && find_group(object, NULL) == NULL) { + if (object && BKE_group_object_find(NULL, object) == NULL) { if (scene && base == NULL) base = BKE_scene_base_find(scene, object); @@ -227,23 +229,24 @@ int rem_from_group(Group *group, Object *object, Scene *scene, Base *base) if (base) base->flag &= ~OB_FROMGROUP; } - return 1; + return true; } else { - return 0; + return false; } } -int object_in_group(Object *ob, Group *group) +bool BKE_group_object_exists(Group *group, Object *ob) { if (group == NULL || ob == NULL) { - return FALSE; + return false; + } + else { + return (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob)) != NULL); } - - return (BLI_findptr(&group->gobject, ob, offsetof(GroupObject, ob)) != NULL); } -Group *find_group(Object *ob, Group *group) +Group *BKE_group_object_find(Group *group, Object *ob) { if (group) group = group->id.next; @@ -251,14 +254,14 @@ Group *find_group(Object *ob, Group *group) group = G.main->group.first; while (group) { - if (object_in_group(ob, group)) + if (BKE_group_object_exists(group, ob)) return group; group = group->id.next; } return NULL; } -void group_tag_recalc(Group *group) +void BKE_group_tag_recalc(Group *group) { GroupObject *go; @@ -270,7 +273,7 @@ void group_tag_recalc(Group *group) } } -int group_is_animated(Object *UNUSED(parent), Group *group) +bool BKE_group_is_animated(Group *group, Object *UNUSED(parent)) { GroupObject *go; @@ -281,9 +284,9 @@ int group_is_animated(Object *UNUSED(parent), Group *group) for (go = group->gobject.first; go; go = go->next) if (go->ob && go->ob->proxy) - return 1; + return true; - return 0; + return false; } #if 0 // add back when timeoffset & animsys work again @@ -332,7 +335,7 @@ static void group_replaces_nla(Object *parent, Object *target, char mode) * you can draw everything, leaves tags in objects to signal it needs further updating */ /* note: does not work for derivedmesh and render... it recreates all again in convertblender.c */ -void group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Group *group) +void BKE_group_handle_recalc_and_update(Scene *scene, Object *UNUSED(parent), Group *group) { GroupObject *go; diff --git a/source/blender/blenkernel/intern/library.c b/source/blender/blenkernel/intern/library.c index 56480434b70..3a59f578446 100644 --- a/source/blender/blenkernel/intern/library.c +++ b/source/blender/blenkernel/intern/library.c @@ -1065,6 +1065,7 @@ ID *BKE_libblock_find_name(const short type, const char *name) /* type: "OB return BLI_findstring(lb, name, offsetof(ID, name) + 2); } +#if 0 /* UNUSED */ static void get_flags_for_id(ID *id, char *buf) { int isfake = id->flag & LIB_FAKEUSER; @@ -1145,7 +1146,6 @@ static void IDnames_to_dyn_pupstring(DynStr *pupds, ListBase *lb, ID *link, shor } } - /* used by headerbuttons.c buttons.c editobject.c editseq.c */ /* if (nr == NULL) no MAX_IDPUP, this for non-header browsing */ void IDnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr) @@ -1170,7 +1170,6 @@ void IDnames_to_pupstring(const char **str, const char *title, const char *extra } /* skips viewer images */ -#if 0 /* unused */ void IMAnames_to_pupstring(const char **str, const char *title, const char *extraops, ListBase *lb, ID *link, short *nr) { DynStr *pupds = BLI_dynstr_new(); diff --git a/source/blender/blenkernel/intern/mball.c b/source/blender/blenkernel/intern/mball.c index 72284130869..b93d924ddf9 100644 --- a/source/blender/blenkernel/intern/mball.c +++ b/source/blender/blenkernel/intern/mball.c @@ -1426,7 +1426,8 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, while (1) { if (i++ == RES) return; p[0] = 0.5f * (pos[0] + neg[0]); - if ((function(p[0], p[1], p[2])) > 0.0f) pos[0] = p[0]; else neg[0] = p[0]; + if ((function(p[0], p[1], p[2])) > 0.0f) pos[0] = p[0]; + else neg[0] = p[0]; } } @@ -1436,7 +1437,8 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, while (1) { if (i++ == RES) return; p[1] = 0.5f * (pos[1] + neg[1]); - if ((function(p[0], p[1], p[2])) > 0.0f) pos[1] = p[1]; else neg[1] = p[1]; + if ((function(p[0], p[1], p[2])) > 0.0f) pos[1] = p[1]; + else neg[1] = p[1]; } } @@ -1446,7 +1448,8 @@ static void converge(const float p1[3], const float p2[3], float v1, float v2, while (1) { if (i++ == RES) return; p[2] = 0.5f * (pos[2] + neg[2]); - if ((function(p[0], p[1], p[2])) > 0.0f) pos[2] = p[2]; else neg[2] = p[2]; + if ((function(p[0], p[1], p[2])) > 0.0f) pos[2] = p[2]; + else neg[2] = p[2]; } } diff --git a/source/blender/blenkernel/intern/movieclip.c b/source/blender/blenkernel/intern/movieclip.c index d0eb1494451..c8f3399665c 100644 --- a/source/blender/blenkernel/intern/movieclip.c +++ b/source/blender/blenkernel/intern/movieclip.c @@ -1162,13 +1162,17 @@ static void free_buffers(MovieClip *clip) BKE_free_animdata((ID *) clip); } +void BKE_movieclip_clear_cache(MovieClip *clip) +{ + free_buffers(clip); +} + void BKE_movieclip_reload(MovieClip *clip) { /* clear cache */ free_buffers(clip); clip->tracking.stabilization.ok = FALSE; - clip->prefetch_ok = FALSE; /* update clip source */ detect_clip_source(clip); diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index 5cf8758aa1b..83e2ff6593b 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -190,7 +190,10 @@ static void node_socket_set_typeinfo(bNodeTree *ntree, bNodeSocket *sock, bNodeS { if (typeinfo) { sock->typeinfo = typeinfo; - + + /* deprecated integer type */ + sock->type = typeinfo->type; + if (sock->default_value == NULL) { /* initialize the default_value pointer used by standard socket types */ node_socket_init_default_value(sock); @@ -435,28 +438,6 @@ GHashIterator *nodeSocketTypeGetIterator(void) return BLI_ghashIterator_new(nodesockettypes_hash); } -void nodeMakeDynamicType(bNode *UNUSED(node)) -{ - #if 0 /* XXX deprecated */ - /* find SH_DYNAMIC_NODE ntype */ - bNodeType *ntype = ntreeType_Shader->node_types.first; - while (ntype) { - if (ntype->type == NODE_DYNAMIC) - break; - ntype = ntype->next; - } - - /* make own type struct to fill */ - if (ntype) { - /*node->typeinfo= MEM_dupallocN(ntype);*/ - bNodeType *newtype = MEM_callocN(sizeof(bNodeType), "dynamic bNodeType"); - *newtype = *ntype; - BLI_strncpy(newtype->name, ntype->name, sizeof(newtype->name)); - node->typeinfo = newtype; - } - #endif -} - struct bNodeSocket *nodeFindSocket(bNode *node, int in_out, const char *identifier) { bNodeSocket *sock = (in_out == SOCK_IN ? node->inputs.first : node->outputs.first); @@ -3438,6 +3419,7 @@ static void registerShaderNodes(void) register_node_type_sh_holdout(); //register_node_type_sh_volume_transparent(); //register_node_type_sh_volume_isotropic(); + register_node_type_sh_subsurface_scattering(); register_node_type_sh_mix_shader(); register_node_type_sh_add_shader(); diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6f0f6a357bb..3750eadb6db 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -771,7 +771,7 @@ void BKE_object_unlink(Object *ob) /* groups */ group = bmain->group.first; while (group) { - rem_from_group(group, ob, NULL, NULL); + BKE_group_object_unlink(group, ob, NULL, NULL); group = group->id.next; } @@ -1848,8 +1848,8 @@ static void ob_parcurve(Scene *scene, Object *ob, Object *par, float mat[4][4]) /* the tilt */ normalize_v3(dir); - q[0] = (float)cos(0.5 * vec[3]); - si = (float)sin(0.5 * vec[3]); + q[0] = cosf(0.5 * vec[3]); + si = sinf(0.5 * vec[3]); q[1] = -si * dir[0]; q[2] = -si * dir[1]; q[3] = -si * dir[2]; @@ -3403,7 +3403,7 @@ struct LinkNode *BKE_object_groups(Object *ob) { LinkNode *group_linknode = NULL; Group *group = NULL; - while ((group = find_group(ob, group))) { + while ((group = BKE_group_object_find(group, ob))) { BLI_linklist_prepend(&group_linknode, group); } @@ -3420,7 +3420,7 @@ void BKE_object_groups_clear(Scene *scene, Base *base, Object *object) base = BKE_scene_base_find(scene, object); } - while ((group = find_group(base->object, group))) { - rem_from_group(group, object, scene, base); + while ((group = BKE_group_object_find(group, base->object))) { + BKE_group_object_unlink(group, object, scene, base); } } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index d9dabf24ba0..4e78ab52499 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -314,7 +314,7 @@ void psys_check_group_weights(ParticleSettings *part) /* first remove all weights that don't have an object in the group */ dw = part->dupliweights.first; while (dw) { - if (!object_in_group(dw->ob, part->dup_group)) { + if (!BKE_group_object_exists(part->dup_group, dw->ob)) { tdw = dw->next; BLI_freelinkN(&part->dupliweights, dw); dw = tdw; diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index 83ee6759b4f..c2d25ce54db 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -1093,7 +1093,7 @@ static void scene_depsgraph_hack(Scene *scene, Scene *scene_parent) if (go->ob) go->ob->recalc |= recalc; } - group_handle_recalc_and_update(scene_parent, ob, ob->dup_group); + BKE_group_handle_recalc_and_update(scene_parent, ob, ob->dup_group); } } } @@ -1136,7 +1136,7 @@ static void scene_update_tagged_recursive(Main *bmain, Scene *scene, Scene *scen BKE_object_handle_update_ex(scene_parent, ob, scene->rigidbody_world); if (ob->dup_group && (ob->transflag & OB_DUPLIGROUP)) - group_handle_recalc_and_update(scene_parent, ob, ob->dup_group); + BKE_group_handle_recalc_and_update(scene_parent, ob, ob->dup_group); /* always update layer, so that animating layers works (joshua july 2010) */ /* XXX commented out, this has depsgraph issues anyway - and this breaks setting scenes diff --git a/source/blender/blenkernel/intern/writeffmpeg.c b/source/blender/blenkernel/intern/writeffmpeg.c index a88a9e4954b..3249de49fe6 100644 --- a/source/blender/blenkernel/intern/writeffmpeg.c +++ b/source/blender/blenkernel/intern/writeffmpeg.c @@ -88,10 +88,11 @@ static uint8_t *video_buffer = 0; static int video_buffersize = 0; static uint8_t *audio_input_buffer = 0; +static uint8_t *audio_deinterleave_buffer = 0; static int audio_input_samples = 0; -static uint8_t *audio_output_buffer = 0; -static int audio_outbuf_size = 0; static double audio_time = 0.0f; +static bool audio_deinterleave = false; +static int audio_sample_size = 0; #ifdef WITH_AUDASPACE static AUD_Device *audio_mixdown_device = 0; @@ -122,37 +123,69 @@ static int write_audio_frame(void) { AVCodecContext *c = NULL; AVPacket pkt; + AVFrame *frame; + int got_output = 0; c = audio_stream->codec; av_init_packet(&pkt); pkt.size = 0; + pkt.data = NULL; + + frame = avcodec_alloc_frame(); + frame->nb_samples = audio_input_samples; + frame->format = c->sample_fmt; +#ifdef FFMPEG_HAVE_FRAME_CHANNEL_LAYOUT + frame->channel_layout = c->channel_layout; +#endif AUD_readDevice(audio_mixdown_device, audio_input_buffer, audio_input_samples); audio_time += (double) audio_input_samples / (double) c->sample_rate; - pkt.size = avcodec_encode_audio(c, audio_output_buffer, audio_outbuf_size, (short *) audio_input_buffer); + if (audio_deinterleave) { + int channel, i; + uint8_t *temp; + + for (channel = 0; channel < c->channels; channel++) { + for (i = 0; i < frame->nb_samples; i++) { + memcpy(audio_deinterleave_buffer + (i + channel * frame->nb_samples) * audio_sample_size, + audio_input_buffer + (c->channels * i + channel) * audio_sample_size, audio_sample_size); + } + } + + temp = audio_deinterleave_buffer; + audio_deinterleave_buffer = audio_input_buffer; + audio_input_buffer = temp; + } + + avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, audio_input_buffer, + audio_input_samples * c->channels * audio_sample_size, 0); - if (pkt.size < 0) { + if (avcodec_encode_audio2(c, &pkt, frame, &got_output) < 0) { // XXX error("Error writing audio packet"); return -1; } - pkt.data = audio_output_buffer; + if (got_output) { + if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) { + pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_stream->time_base); + PRINT("Audio Frame PTS: %d\n", (int) pkt.pts); + } - if (c->coded_frame && c->coded_frame->pts != AV_NOPTS_VALUE) { - pkt.pts = av_rescale_q(c->coded_frame->pts, c->time_base, audio_stream->time_base); - PRINT("Audio Frame PTS: %d\n", (int) pkt.pts); - } + pkt.stream_index = audio_stream->index; - pkt.stream_index = audio_stream->index; + pkt.flags |= AV_PKT_FLAG_KEY; - pkt.flags |= AV_PKT_FLAG_KEY; + if (av_interleaved_write_frame(outfile, &pkt) != 0) { + fprintf(stderr, "Error writing audio packet!\n"); + return -1; + } - if (av_interleaved_write_frame(outfile, &pkt) != 0) { - fprintf(stderr, "Error writing audio packet!\n"); - return -1; + av_free_packet(&pkt); } + + avcodec_free_frame(&frame); + return 0; } #endif // #ifdef WITH_AUDASPACE @@ -608,8 +641,6 @@ static AVStream *alloc_video_stream(RenderData *rd, int codec_id, AVFormatContex return st; } -/* Prepare an audio stream for the output file */ - static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContext *of, char *error, int error_size) { AVStream *st; @@ -659,11 +690,6 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex } } - if (c->sample_fmt == AV_SAMPLE_FMT_FLTP) { - BLI_strncpy(error, "Requested audio codec requires planar float sample format, which is not supported yet", error_size); - return NULL; - } - if (codec->supported_samplerates) { const int *p = codec->supported_samplerates; int best = 0; @@ -692,24 +718,23 @@ static AVStream *alloc_audio_stream(RenderData *rd, int codec_id, AVFormatContex st->codec->time_base.num = 1; st->codec->time_base.den = st->codec->sample_rate; - audio_outbuf_size = FF_MIN_BUFFER_SIZE; - - if ((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD)) - audio_input_samples = audio_outbuf_size * 8 / c->bits_per_coded_sample / c->channels; + if (c->frame_size == 0) + // used to be if((c->codec_id >= CODEC_ID_PCM_S16LE) && (c->codec_id <= CODEC_ID_PCM_DVD)) + // not sure if that is needed anymore, so let's try out if there are any + // complaints regarding some ffmpeg versions users might have + audio_input_samples = FF_MIN_BUFFER_SIZE * 8 / c->bits_per_coded_sample / c->channels; else { audio_input_samples = c->frame_size; - if (c->frame_size * c->channels * sizeof(int16_t) * 4 > audio_outbuf_size) - audio_outbuf_size = c->frame_size * c->channels * sizeof(int16_t) * 4; } - audio_output_buffer = (uint8_t *) av_malloc(audio_outbuf_size); + audio_deinterleave = av_sample_fmt_is_planar(c->sample_fmt); - if (c->sample_fmt == AV_SAMPLE_FMT_FLT) { - audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(float)); - } - else { - audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * sizeof(int16_t)); - } + audio_sample_size = av_get_bytes_per_sample(c->sample_fmt); + + audio_input_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * audio_sample_size); + + if (audio_deinterleave) + audio_deinterleave_buffer = (uint8_t *) av_malloc(audio_input_samples * c->channels * audio_sample_size); audio_time = 0.0f; @@ -1010,12 +1035,27 @@ int BKE_ffmpeg_start(struct Scene *scene, RenderData *rd, int rectx, int recty, AVCodecContext *c = audio_stream->codec; AUD_DeviceSpecs specs; specs.channels = c->channels; - if (c->sample_fmt == AV_SAMPLE_FMT_FLT) { - specs.format = AUD_FORMAT_FLOAT32; - } - else { + + switch (av_get_packed_sample_fmt(c->sample_fmt)) { + case AV_SAMPLE_FMT_U8: + specs.format = AUD_FORMAT_U8; + break; + case AV_SAMPLE_FMT_S16: specs.format = AUD_FORMAT_S16; + break; + case AV_SAMPLE_FMT_S32: + specs.format = AUD_FORMAT_S32; + break; + case AV_SAMPLE_FMT_FLT: + specs.format = AUD_FORMAT_FLOAT32; + break; + case AV_SAMPLE_FMT_DBL: + specs.format = AUD_FORMAT_FLOAT64; + break; + default: + return -31415; } + specs.rate = rd->ffcodecdata.audio_mixrate; audio_mixdown_device = sound_mixdown(scene, specs, rd->sfra, rd->ffcodecdata.audio_volume); #ifdef FFMPEG_CODEC_TIME_BASE @@ -1138,15 +1178,16 @@ static void end_ffmpeg_impl(int is_autosplit) MEM_freeN(video_buffer); video_buffer = 0; } - if (audio_output_buffer) { - av_free(audio_output_buffer); - audio_output_buffer = 0; - } if (audio_input_buffer) { av_free(audio_input_buffer); audio_input_buffer = 0; } + if (audio_deinterleave_buffer) { + av_free(audio_deinterleave_buffer); + audio_deinterleave_buffer = 0; + } + if (img_convert_ctx) { sws_freeContext(img_convert_ctx); img_convert_ctx = 0; diff --git a/source/blender/blenlib/BLI_math_vector.h b/source/blender/blenlib/BLI_math_vector.h index 9cf571aa98b..d4f16506551 100644 --- a/source/blender/blenlib/BLI_math_vector.h +++ b/source/blender/blenlib/BLI_math_vector.h @@ -244,6 +244,8 @@ void minmax_v2v2_v2(float min[2], float max[2], const float vec[2]); void dist_ensure_v3_v3fl(float v1[3], const float v2[3], const float dist); void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist); +void axis_sort_v3(const float axis_values[3], int r_axis_order[3]); + /***************************** Array Functions *******************************/ /* attempted to follow fixed length vertex functions. names could be improved*/ double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size); diff --git a/source/blender/blenlib/intern/math_rotation.c b/source/blender/blenlib/intern/math_rotation.c index 26576b2dcb2..cf9280d418f 100644 --- a/source/blender/blenlib/intern/math_rotation.c +++ b/source/blender/blenlib/intern/math_rotation.c @@ -539,9 +539,9 @@ void QuatInterpolW(float *result, float quat1[4], float quat2[4], float t) if ((1.0f - cosom) > 0.0001f) { omega = (float)acos(cosom); - sinom = (float)sin(omega); - sc1 = (float)sin((1.0 - t) * omega) / sinom; - sc2 = (float)sin(t * omega) / sinom; + sinom = sinf(omega); + sc1 = sinf((1.0 - t) * omega) / sinom; + sc2 = sinf(t * omega) / sinom; } else { sc1 = 1.0f - t; @@ -558,8 +558,8 @@ void QuatInterpolW(float *result, float quat1[4], float quat2[4], float t) result[2] = quat2[1]; result[3] = -quat2[0]; - sc1 = (float)sin((1.0 - t) * M_PI_2); - sc2 = (float)sin(t * M_PI_2); + sc1 = sinf((1.0 - t) * M_PI_2); + sc2 = sinf(t * M_PI_2); result[0] = sc1 * quat1[0] + sc2 * result[0]; result[1] = sc1 * quat1[1] + sc2 * result[1]; diff --git a/source/blender/blenlib/intern/math_vector.c b/source/blender/blenlib/intern/math_vector.c index 58d444f5794..572bc4526af 100644 --- a/source/blender/blenlib/intern/math_vector.c +++ b/source/blender/blenlib/intern/math_vector.c @@ -527,6 +527,28 @@ void dist_ensure_v2_v2fl(float v1[2], const float v2[2], const float dist) } } +void axis_sort_v3(const float axis_values[3], int r_axis_order[3]) +{ + float v[3]; + copy_v3_v3(v, axis_values); + +#define SWAP_AXIS(a, b) { \ + SWAP(float, v[a], v[b]); \ + SWAP(int, r_axis_order[a], r_axis_order[b]); \ +} (void)0 + + if (v[0] < v[1]) { + if (v[2] < v[0]) { SWAP_AXIS(0, 2); } + } + else { + if (v[1] < v[2]) { SWAP_AXIS(0, 1); } + else { SWAP_AXIS(0, 2); } + } + if (v[2] < v[1]) { SWAP_AXIS(1, 2); } + +#undef SWAP_AXIS +} + /***************************** Array Functions *******************************/ double dot_vn_vn(const float *array_src_a, const float *array_src_b, const int size) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index ccbe3b9beaa..c4f56b345a1 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2374,7 +2374,7 @@ static void lib_node_do_versions_group_indices(bNode *gnode) int old_index = sock->to_index; for (link = ngroup->links.first; link; link = link->next) { - if (link->tonode->type == NODE_GROUP_OUTPUT && link->fromsock->own_index == old_index) { + if (link->tonode == NULL && link->fromsock->own_index == old_index) { strcpy(sock->identifier, link->fromsock->identifier); /* deprecated */ sock->own_index = link->fromsock->own_index; @@ -2387,7 +2387,7 @@ static void lib_node_do_versions_group_indices(bNode *gnode) int old_index = sock->to_index; for (link = ngroup->links.first; link; link = link->next) { - if (link->fromnode->type == NODE_GROUP_INPUT && link->tosock->own_index == old_index) { + if (link->fromnode == NULL && link->tosock->own_index == old_index) { strcpy(sock->identifier, link->tosock->identifier); /* deprecated */ sock->own_index = link->tosock->own_index; @@ -6553,7 +6553,7 @@ static void lib_link_group(FileData *fd, Main *main) } } if (add_us) group->id.us++; - rem_from_group(group, NULL, NULL, NULL); /* removes NULL entries */ + BKE_group_object_unlink(group, NULL, NULL, NULL); /* removes NULL entries */ } } } @@ -6606,8 +6606,6 @@ static void direct_link_movieclip(FileData *fd, MovieClip *clip) clip->tracking.dopesheet.channels.first = clip->tracking.dopesheet.channels.last = NULL; clip->tracking.dopesheet.coverage_segments.first = clip->tracking.dopesheet.coverage_segments.last = NULL; - clip->prefetch_ok = FALSE; - link_list(fd, &tracking->objects); for (object = tracking->objects.first; object; object = object->next) { diff --git a/source/blender/blenloader/intern/versioning_250.c b/source/blender/blenloader/intern/versioning_250.c index 2445775ad44..034857d7c54 100644 --- a/source/blender/blenloader/intern/versioning_250.c +++ b/source/blender/blenloader/intern/versioning_250.c @@ -742,22 +742,6 @@ static void do_versions_socket_default_value_259(bNodeSocket *sock) } } -static void do_versions_nodetree_default_value_259(bNodeTree *ntree) -{ - bNode *node; - bNodeSocket *sock; - for (node=ntree->nodes.first; node; node=node->next) { - for (sock = node->inputs.first; sock; sock = sock->next) - do_versions_socket_default_value_259(sock); - for (sock = node->outputs.first; sock; sock = sock->next) - do_versions_socket_default_value_259(sock); - } - for (sock = ntree->inputs.first; sock; sock = sock->next) - do_versions_socket_default_value_259(sock); - for (sock = ntree->outputs.first; sock; sock = sock->next) - do_versions_socket_default_value_259(sock); -} - void blo_do_versions_250(FileData *fd, Library *lib, Main *main) { /* WATCH IT!!!: pointers from libdata have not been converted */ @@ -2736,33 +2720,25 @@ void blo_do_versions_250(FileData *fd, Library *lib, Main *main) if (main->versionfile < 259 || (main->versionfile == 259 && main->subversionfile < 2)) { { /* Convert default socket values from bNodeStack */ - Scene *sce; - Material *mat; - Tex *tex; - bNodeTree *ntree; - - for (ntree = main->nodetree.first; ntree; ntree = ntree->id.next) { - do_versions_nodetree_default_value_259(ntree); + FOREACH_NODETREE(main, ntree, id) { + bNode *node; + bNodeSocket *sock; + + for (node=ntree->nodes.first; node; node=node->next) { + for (sock = node->inputs.first; sock; sock = sock->next) + do_versions_socket_default_value_259(sock); + for (sock = node->outputs.first; sock; sock = sock->next) + do_versions_socket_default_value_259(sock); + } + + for (sock = ntree->inputs.first; sock; sock = sock->next) + do_versions_socket_default_value_259(sock); + for (sock = ntree->outputs.first; sock; sock = sock->next) + do_versions_socket_default_value_259(sock); + ntree->update |= NTREE_UPDATE; } - - for (sce = main->scene.first; sce; sce = sce->id.next) - if (sce->nodetree) { - do_versions_nodetree_default_value_259(sce->nodetree); - sce->nodetree->update |= NTREE_UPDATE; - } - - for (mat = main->mat.first; mat; mat = mat->id.next) - if (mat->nodetree) { - do_versions_nodetree_default_value_259(mat->nodetree); - mat->nodetree->update |= NTREE_UPDATE; - } - - for (tex = main->tex.first; tex; tex = tex->id.next) - if (tex->nodetree) { - do_versions_nodetree_default_value_259(tex->nodetree); - tex->nodetree->update |= NTREE_UPDATE; - } + FOREACH_NODETREE_END } { diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c index 4e29756104a..2cc84671e41 100644 --- a/source/blender/bmesh/intern/bmesh_marking.c +++ b/source/blender/bmesh/intern/bmesh_marking.c @@ -619,7 +619,7 @@ void BM_editselection_center(BMEditSelection *ese, float r_center[3]) } else if (ese->htype == BM_FACE) { BMFace *efa = (BMFace *)ese->ele; - BM_face_calc_center_bounds(efa, r_center); + BM_face_calc_center_mean(efa, r_center); } } @@ -710,8 +710,28 @@ void BM_editselection_plane(BMEditSelection *ese, float r_plane[3]) cross_v3_v3v3(r_plane, efa->no, vec); } else { - if (efa->len == 4) { - BMVert *verts[4] = {NULL}; + if (efa->len == 3) { + BMVert *verts[3]; + float lens[3]; + float difs[3]; + int order[3] = {0, 1, 2}; + + BM_face_as_array_vert_tri(efa, verts); + + lens[0] = len_v3v3(verts[0]->co, verts[1]->co); + lens[1] = len_v3v3(verts[1]->co, verts[2]->co); + lens[2] = len_v3v3(verts[2]->co, verts[0]->co); + + /* find the shortest or the longest loop */ + difs[0] = fabsf(lens[1] - lens[2]); + difs[1] = fabsf(lens[2] - lens[0]); + difs[2] = fabsf(lens[0] - lens[1]); + + axis_sort_v3(difs, order); + sub_v3_v3v3(r_plane, verts[order[0]]->co, verts[(order[0] + 1) % 3]->co); + } + else if (efa->len == 4) { + BMVert *verts[4]; float vecA[3], vecB[3]; // BM_iter_as_array(NULL, BM_VERTS_OF_FACE, efa, (void **)verts, 4); diff --git a/source/blender/compositor/nodes/COM_BoxMaskNode.cpp b/source/blender/compositor/nodes/COM_BoxMaskNode.cpp index 0580a32ed8c..e3fb6ecc704 100644 --- a/source/blender/compositor/nodes/COM_BoxMaskNode.cpp +++ b/source/blender/compositor/nodes/COM_BoxMaskNode.cpp @@ -24,6 +24,9 @@ #include "COM_BoxMaskOperation.h" #include "COM_ExecutionSystem.h" +#include "COM_SetValueOperation.h" +#include "COM_ScaleOperation.h" + BoxMaskNode::BoxMaskNode(bNode *editorNode) : Node(editorNode) { /* pass */ @@ -34,9 +37,41 @@ void BoxMaskNode::convertToOperations(ExecutionSystem *graph, CompositorContext BoxMaskOperation *operation; operation = new BoxMaskOperation(); operation->setData((NodeBoxMask *)this->getbNode()->storage); - this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); + + InputSocket *inputSocket = this->getInputSocket(0); + OutputSocket *outputSocket = this->getOutputSocket(0); + + if (inputSocket->isConnected()) { + inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); + outputSocket->relinkConnections(operation->getOutputSocket()); + } + else { + /* Value operation to produce original transparent image */ + SetValueOperation *valueOperation = new SetValueOperation(); + valueOperation->setValue(0.0f); + graph->addOperation(valueOperation); + + /* Scale that image up to render resolution */ + const RenderData *rd = context->getRenderData(); + ScaleFixedSizeOperation *scaleOperation = new ScaleFixedSizeOperation(); + + scaleOperation->setIsAspect(false); + scaleOperation->setIsCrop(false); + scaleOperation->setOffset(0.0f, 0.0f); + + scaleOperation->setNewWidth(rd->xsch * rd->size / 100.0f); + scaleOperation->setNewHeight(rd->ysch * rd->size / 100.0f); + + addLink(graph, valueOperation->getOutputSocket(0), scaleOperation->getInputSocket(0)); + addLink(graph, scaleOperation->getOutputSocket(0), operation->getInputSocket(0)); + outputSocket->relinkConnections(operation->getOutputSocket(0)); + + scaleOperation->getInputSocket(0)->getConnection()->setIgnoreResizeCheck(true); + + graph->addOperation(scaleOperation); + } + this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph); - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0)); operation->setMaskType(this->getbNode()->custom1); graph->addOperation(operation); diff --git a/source/blender/compositor/nodes/COM_EllipseMaskNode.cpp b/source/blender/compositor/nodes/COM_EllipseMaskNode.cpp index dc4421abb25..fe0c85c173a 100644 --- a/source/blender/compositor/nodes/COM_EllipseMaskNode.cpp +++ b/source/blender/compositor/nodes/COM_EllipseMaskNode.cpp @@ -24,6 +24,9 @@ #include "COM_EllipseMaskOperation.h" #include "COM_ExecutionSystem.h" +#include "COM_SetValueOperation.h" +#include "COM_ScaleOperation.h" + EllipseMaskNode::EllipseMaskNode(bNode *editorNode) : Node(editorNode) { /* pass */ @@ -32,11 +35,44 @@ EllipseMaskNode::EllipseMaskNode(bNode *editorNode) : Node(editorNode) void EllipseMaskNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context) { EllipseMaskOperation *operation; + operation = new EllipseMaskOperation(); operation->setData((NodeEllipseMask *)this->getbNode()->storage); - this->getInputSocket(0)->relinkConnections(operation->getInputSocket(0), 0, graph); + + InputSocket *inputSocket = this->getInputSocket(0); + OutputSocket *outputSocket = this->getOutputSocket(0); + + if (inputSocket->isConnected()) { + inputSocket->relinkConnections(operation->getInputSocket(0), 0, graph); + outputSocket->relinkConnections(operation->getOutputSocket()); + } + else { + /* Value operation to produce original transparent image */ + SetValueOperation *valueOperation = new SetValueOperation(); + valueOperation->setValue(0.0f); + graph->addOperation(valueOperation); + + /* Scale that image up to render resolution */ + const RenderData *rd = context->getRenderData(); + ScaleFixedSizeOperation *scaleOperation = new ScaleFixedSizeOperation(); + + scaleOperation->setIsAspect(false); + scaleOperation->setIsCrop(false); + scaleOperation->setOffset(0.0f, 0.0f); + + scaleOperation->setNewWidth(rd->xsch * rd->size / 100.0f); + scaleOperation->setNewHeight(rd->ysch * rd->size / 100.0f); + + addLink(graph, valueOperation->getOutputSocket(0), scaleOperation->getInputSocket(0)); + addLink(graph, scaleOperation->getOutputSocket(0), operation->getInputSocket(0)); + outputSocket->relinkConnections(operation->getOutputSocket(0)); + + scaleOperation->getInputSocket(0)->getConnection()->setIgnoreResizeCheck(true); + + graph->addOperation(scaleOperation); + } + this->getInputSocket(1)->relinkConnections(operation->getInputSocket(1), 1, graph); - this->getOutputSocket(0)->relinkConnections(operation->getOutputSocket(0)); operation->setMaskType(this->getbNode()->custom1); graph->addOperation(operation); diff --git a/source/blender/editors/animation/anim_filter.c b/source/blender/editors/animation/anim_filter.c index 61e03806391..df840df05e7 100644 --- a/source/blender/editors/animation/anim_filter.c +++ b/source/blender/editors/animation/anim_filter.c @@ -2326,7 +2326,7 @@ static size_t animdata_filter_dopesheet(bAnimContext *ac, ListBase *anim_data, b * - used to ease the process of doing multiple-character choreographies */ if (ads->filterflag & ADS_FILTER_ONLYOBGROUP) { - if (object_in_group(ob, ads->filter_grp) == 0) + if (BKE_group_object_exists(ads->filter_grp, ob) == 0) continue; } diff --git a/source/blender/editors/armature/editarmature_sketch.c b/source/blender/editors/armature/editarmature_sketch.c index a3515e0983d..7a20f0727c0 100644 --- a/source/blender/editors/armature/editarmature_sketch.c +++ b/source/blender/editors/armature/editarmature_sketch.c @@ -626,7 +626,7 @@ static void sk_drawStrokeSubdivision(ToolSettings *toolsettings, SK_Stroke *stk) } } -static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, int mval[2], int *dist, int *index, int all_pts) +static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, int mval[2], float *r_dist_px, int *index, int all_pts) { ARegion *ar = CTX_wm_region(C); SK_Point *pt = NULL; @@ -641,8 +641,8 @@ static SK_Point *sk_snapPointStroke(bContext *C, SK_Stroke *stk, int mval[2], in pdist = ABS(pval[0] - mval[0]) + ABS(pval[1] - mval[1]); - if (pdist < *dist) { - *dist = pdist; + if (pdist < *r_dist_px) { + *r_dist_px = pdist; pt = stk->points + i; if (index != NULL) { @@ -729,13 +729,13 @@ static void sk_updateOverdraw(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK if (sketch->over.target == NULL) { SK_Stroke *target; int closest_index = -1; - int dist = SNAP_MIN_DISTANCE * 2; + float dist_px = SNAP_MIN_DISTANCE * 2; for (target = sketch->strokes.first; target; target = target->next) { if (target != stk) { int index; - SK_Point *spt = sk_snapPointStroke(C, target, dd->mval, &dist, &index, 1); + SK_Point *spt = sk_snapPointStroke(C, target, dd->mval, &dist_px, &index, 1); if (spt != NULL) { sketch->over.target = target; @@ -764,10 +764,10 @@ static void sk_updateOverdraw(bContext *C, SK_Sketch *sketch, SK_Stroke *stk, SK } else if (sketch->over.target != NULL) { SK_Point *closest_pt = NULL; - int dist = SNAP_MIN_DISTANCE * 2; + float dist_px = SNAP_MIN_DISTANCE * 2; int index; - closest_pt = sk_snapPointStroke(C, sketch->over.target, dd->mval, &dist, &index, 1); + closest_pt = sk_snapPointStroke(C, sketch->over.target, dd->mval, &dist_px, &index, 1); if (closest_pt != NULL) { if (sk_lastStrokePoint(stk)->type == PT_EXACT) { @@ -1064,17 +1064,17 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S float no[3]; float mval[2]; int found = 0; - int dist = SNAP_MIN_DISTANCE; // Use a user defined value here + float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here /* snap to strokes */ // if (ts->snap_mode == SCE_SNAP_MODE_VERTEX) /* snap all the time to strokes */ for (snap_stk = sketch->strokes.first; snap_stk; snap_stk = snap_stk->next) { SK_Point *spt = NULL; if (snap_stk == stk) { - spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 0); + spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist_px, NULL, 0); } else { - spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist, NULL, 1); + spt = sk_snapPointStroke(C, snap_stk, dd->mval, &dist_px, NULL, 1); } if (spt != NULL) { @@ -1087,7 +1087,7 @@ static int sk_getStrokeSnapPoint(bContext *C, SK_Point *pt, SK_Sketch *sketch, S mval[1] = dd->mval[1]; /* try to snap to closer object */ - found = snapObjectsContext(C, mval, &dist, vec, no, SNAP_NOT_SELECTED); + found = snapObjectsContext(C, mval, &dist_px, vec, no, SNAP_NOT_SELECTED); if (found == 1) { pt->type = dd->type; pt->mode = PT_SNAP; diff --git a/source/blender/editors/include/BIF_glutil.h b/source/blender/editors/include/BIF_glutil.h index 5774a057eb5..af2dc884508 100644 --- a/source/blender/editors/include/BIF_glutil.h +++ b/source/blender/editors/include/BIF_glutil.h @@ -33,6 +33,9 @@ struct rcti; struct rctf; +struct ImBuf; +struct bContext; + void fdrawbezier(float vec[4][3]); void fdrawline(float x1, float y1, float x2, float y2); void fdrawbox(float x1, float y1, float x2, float y2); @@ -141,17 +144,17 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo * 1-to-1 mapping to screen space. */ -void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect); +void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect); /** * glaDrawPixelsAuto - Switches between texture or pixel drawing using UserDef. * only RGBA * needs glaDefine2DArea to be set. */ -void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect); +void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect); -void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect, float scaleX, float scaleY); +void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY); /* 2D Drawing Assistance */ @@ -170,35 +173,19 @@ void glaDefine2DArea(struct rcti *screen_rect); typedef struct gla2DDrawInfo gla2DDrawInfo; -/** Save the current OpenGL state and initialize OpenGL for 2D - * rendering. glaEnd2DDraw should be called on the returned structure - * to free it and to return OpenGL to its previous state. The - * scissor rectangle is set to match the viewport. - * - * See glaDefine2DArea for an explanation of why this function uses integers. - * - * \param screen_rect The screen rectangle to be used for 2D drawing. - * \param world_rect The world rectangle that the 2D area represented - * by \a screen_rect is supposed to represent. If NULL it is assumed the - * world has a 1 to 1 mapping to the screen. - */ -gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect); - -/** Translate the (\a wo_x, \a wo_y) point from world coordinates into screen space. */ -void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r); +/* UNUSED */ +#if 0 -/** Translate the \a world point from world coordiantes into screen space. */ +gla2DDrawInfo *glaBegin2DDraw(struct rcti *screen_rect, struct rctf *world_rect); +void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r); void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2]); -/* Restores the previous OpenGL state and free's the auxilary - * gla data. - */ -void glaEnd2DDraw(gla2DDrawInfo *di); +void glaEnd2DDraw(gla2DDrawInfo *di); /** Adjust the transformation mapping of a 2d area */ void gla2DGetMap(gla2DDrawInfo *di, struct rctf *rect); void gla2DSetMap(gla2DDrawInfo *di, struct rctf *rect); - +#endif /* use this for platform hacks. glPointSize is solved here */ void bglBegin(int mode); @@ -223,5 +210,13 @@ typedef struct bglMats { } bglMats; void bgl_get_mats(bglMats *mats); +/* **** Color management helper functions for GLSL display/transform ***** */ + +/* Draw imbuf on a screen, preferably using GLSL display transform */ +void glaDrawImBuf_glsl_ctx(const struct bContext *C, struct ImBuf *ibuf, float x, float y, int zoomfilter); + +/* Transform buffer from role to scene linear space using GLSL OCIO conversion */ +int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role); + #endif /* __BIF_GLUTIL_H__ */ diff --git a/source/blender/editors/include/ED_mesh.h b/source/blender/editors/include/ED_mesh.h index ab112fde48d..a39476dad66 100644 --- a/source/blender/editors/include/ED_mesh.h +++ b/source/blender/editors/include/ED_mesh.h @@ -251,7 +251,6 @@ void ED_mesh_vertices_remove(struct Mesh *mesh, struct ReportList *reports, int void ED_mesh_transform(struct Mesh *me, float *mat); void ED_mesh_calc_normals(struct Mesh *me); void ED_mesh_calc_tessface(struct Mesh *mesh); -void ED_mesh_material_link(struct Mesh *me, struct Material *ma); void ED_mesh_update(struct Mesh *mesh, struct bContext *C, int calc_edges, int calc_tessface); int ED_mesh_uv_texture_add(struct Mesh *me, const char *name, const bool active_set); diff --git a/source/blender/editors/include/ED_space_api.h b/source/blender/editors/include/ED_space_api.h index a40cf90f7ad..4fbe01a5fc7 100644 --- a/source/blender/editors/include/ED_space_api.h +++ b/source/blender/editors/include/ED_space_api.h @@ -74,6 +74,8 @@ void *ED_region_draw_cb_activate(struct ARegionType *, void ED_region_draw_cb_draw(const struct bContext *, struct ARegion *, int); void ED_region_draw_cb_exit(struct ARegionType *, void *); void *ED_region_draw_cb_customdata(void *handle); +/* generic callbacks */ +/* ed_util.c */ +void ED_region_draw_mouse_line_cb(const struct bContext *C, struct ARegion *ar, void *arg_info); #endif /* __ED_SPACE_API_H__ */ - diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h index d43582fa8d1..5fe44aa17f7 100644 --- a/source/blender/editors/include/ED_transform.h +++ b/source/blender/editors/include/ED_transform.h @@ -34,17 +34,18 @@ /* ******************* Registration Function ********************** */ -struct wmWindowManager; -struct wmOperatorType; +struct ARegion; +struct EnumPropertyItem; struct ListBase; -struct wmEvent; -struct bContext; struct Object; +struct View3D; +struct bContext; struct uiLayout; -struct EnumPropertyItem; -struct wmOperatorType; -struct wmKeyMap; +struct wmEvent; struct wmKeyConfig; +struct wmKeyMap; +struct wmOperatorType; +struct wmWindowManager; void transform_keymap_for_space(struct wmKeyConfig *keyconf, struct wmKeyMap *keymap, int spaceid); void transform_operatortypes(void); @@ -112,7 +113,8 @@ struct Base; struct Scene; struct Object; -int BIF_snappingSupported(struct Object *obedit); +/* UNUSED */ +// int BIF_snappingSupported(struct Object *obedit); struct TransformOrientation; struct bContext; @@ -179,10 +181,17 @@ typedef enum SnapMode { bool peelObjectsTransForm(struct TransInfo *t, struct ListBase *depth_peels, const float mval[2], SnapMode mode); bool peelObjectsContext(struct bContext *C, struct ListBase *depth_peels, const float mval[2], SnapMode mode); -bool snapObjectsTransform(struct TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode); -bool snapObjectsContext(struct bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode); -bool snapNodesTransform(struct TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode); -bool snapNodesContext(struct bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode); +bool snapObjectsTransform(struct TransInfo *t, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode); +bool snapObjectsContext(struct bContext *C, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode); +/* taks args for all settings */ +bool snapObjectsEx(struct Scene *scene, struct Base *base_act, struct View3D *v3d, struct ARegion *ar, struct Object *obedit, short snap_mode, + const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode); +bool snapObjectsRayEx(struct Scene *scene, struct Base *base_act, struct View3D *v3d, struct ARegion *ar, struct Object *obedit, short snap_mode, + const float ray_start[3], const float ray_normal[3], + const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode); + +bool snapNodesTransform(struct TransInfo *t, const int mval[2], float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode); +bool snapNodesContext(struct bContext *C, const int mval[2], float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode); #endif diff --git a/source/blender/editors/include/ED_util.h b/source/blender/editors/include/ED_util.h index d0ca079b8c9..67f790f0b46 100644 --- a/source/blender/editors/include/ED_util.h +++ b/source/blender/editors/include/ED_util.h @@ -90,7 +90,6 @@ void ED_clipboard_posebuf_free(void); /* ************** XXX OLD CRUFT WARNING ************* */ void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, float fac3, int invert); -int GetButStringLength(const char *str); /* where else to go ? */ void unpack_menu(struct bContext *C, const char *opname, const char *id_name, const char *abs_name, const char *folder, struct PackedFile *pf); diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h index 2572d4b4d99..7e1bd2b9eb6 100644 --- a/source/blender/editors/include/UI_interface.h +++ b/source/blender/editors/include/UI_interface.h @@ -280,7 +280,6 @@ typedef enum { * Functions to draw various shapes, taking theme settings into account. * Used for code that draws its own UI style elements. */ -void uiEmboss(float x1, float y1, float x2, float y2, int sel); void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad); void uiSetRoundBox(int type); int uiGetRoundBox(void); @@ -398,7 +397,7 @@ void uiFreeActiveButtons(const struct bContext *C, struct bScreen *screen); void uiBlockSetRegion(uiBlock *block, struct ARegion *region); -void uiBlockSetButLock(uiBlock *block, int val, const char *lockstr); +void uiBlockSetButLock(uiBlock *block, bool val, const char *lockstr); void uiBlockClearButLock(uiBlock *block); /* automatic aligning, horiz or verical */ @@ -448,7 +447,7 @@ void uiButSetDrawFlag(uiBut *but, int flag); void uiButClearDrawFlag(uiBut *but, int flag); /* special button case, only draw it when used actively, for outliner etc */ -int uiButActiveOnly(const struct bContext *C, struct ARegion *ar, uiBlock *block, uiBut *but); +bool uiButActiveOnly(const struct bContext *C, struct ARegion *ar, uiBlock *block, uiBut *but); void uiButExecute(const struct bContext *C, uiBut *but); @@ -621,7 +620,7 @@ void uiComposeLinks(uiBlock *block); uiBut *uiFindInlink(uiBlock *block, void *poin); /* use inside searchfunc to add items */ -int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid); +bool uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid); /* bfunc gets search item *poin as arg2, or if NULL the old string */ void uiButSetSearchFunc(uiBut *but, uiButSearchFunc sfunc, void *arg1, uiButHandleFunc bfunc, void *active); /* height in pixels, it's using hardcoded values still */ @@ -770,20 +769,20 @@ void uiLayoutOperatorButs(const struct bContext *C, struct uiLayout *layout, str struct MenuType *uiButGetMenuType(uiBut *but); void uiLayoutSetOperatorContext(uiLayout *layout, int opcontext); -void uiLayoutSetActive(uiLayout *layout, int active); -void uiLayoutSetEnabled(uiLayout *layout, int enabled); -void uiLayoutSetRedAlert(uiLayout *layout, int redalert); -void uiLayoutSetAlignment(uiLayout *layout, int alignment); -void uiLayoutSetKeepAspect(uiLayout *layout, int keepaspect); +void uiLayoutSetActive(uiLayout *layout, bool active); +void uiLayoutSetEnabled(uiLayout *layout, bool enabled); +void uiLayoutSetRedAlert(uiLayout *layout, bool redalert); +void uiLayoutSetAlignment(uiLayout *layout, char alignment); +void uiLayoutSetKeepAspect(uiLayout *layout, bool keepaspect); void uiLayoutSetScaleX(uiLayout *layout, float scale); void uiLayoutSetScaleY(uiLayout *layout, float scale); int uiLayoutGetOperatorContext(uiLayout *layout); -int uiLayoutGetActive(uiLayout *layout); -int uiLayoutGetEnabled(uiLayout *layout); -int uiLayoutGetRedAlert(uiLayout *layout); +bool uiLayoutGetActive(uiLayout *layout); +bool uiLayoutGetEnabled(uiLayout *layout); +bool uiLayoutGetRedAlert(uiLayout *layout); int uiLayoutGetAlignment(uiLayout *layout); -int uiLayoutGetKeepAspect(uiLayout *layout); +bool uiLayoutGetKeepAspect(uiLayout *layout); int uiLayoutGetWidth(uiLayout *layout); float uiLayoutGetScaleX(uiLayout *layout); float uiLayoutGetScaleY(uiLayout *layout); @@ -803,7 +802,6 @@ uiBlock *uiLayoutAbsoluteBlock(uiLayout *layout); /* templates */ void uiTemplateHeader(uiLayout *layout, struct bContext *C, int menus); -void uiTemplateDopeSheetFilter(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr); void uiTemplateID(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, const char *newop, const char *openop, const char *unlinkop); void uiTemplateIDBrowse(uiLayout *layout, struct bContext *C, struct PointerRNA *ptr, const char *propname, @@ -836,7 +834,6 @@ void uiOperatorSearch_But(uiBut *but); void uiTemplateOperatorSearch(uiLayout *layout); void uiTemplateHeader3D(uiLayout *layout, struct bContext *C); void uiTemplateEditModeSelection(uiLayout *layout, struct bContext *C); -void uiTemplateTextureImage(uiLayout *layout, struct bContext *C, struct Tex *tex); void uiTemplateReportsBanner(uiLayout *layout, struct bContext *C); void uiTemplateKeymapItemProperties(uiLayout *layout, struct PointerRNA *ptr); void uiTemplateComponentMenu(uiLayout *layout, struct PointerRNA *ptr, const char *propname, const char *name); @@ -922,7 +919,7 @@ uiStyle *UI_GetStyleDraw(void); /* DPI scaled settings for drawing */ void UI_template_fix_linking(void); /* UI_OT_editsource helpers */ -int UI_editsource_enable_check(void); +bool UI_editsource_enable_check(void); void UI_editsource_active_but_test(uiBut *but); #endif /* __UI_INTERFACE_H__ */ diff --git a/source/blender/editors/include/UI_interface_icons.h b/source/blender/editors/include/UI_interface_icons.h index 10026bbd50f..6104505ef58 100644 --- a/source/blender/editors/include/UI_interface_icons.h +++ b/source/blender/editors/include/UI_interface_icons.h @@ -79,6 +79,6 @@ int UI_iconfile_get_index(const char *filename); struct PreviewImage *UI_icon_to_preview(int icon_id); -int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big); +int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big); #endif /* __UI_INTERFACE_ICONS_H__ */ diff --git a/source/blender/editors/interface/interface.c b/source/blender/editors/interface/interface.c index be51651dee7..0c484a82778 100644 --- a/source/blender/editors/interface/interface.c +++ b/source/blender/editors/interface/interface.c @@ -549,22 +549,22 @@ static void ui_draw_links(uiBlock *block) /* ************** BLOCK ENDING FUNCTION ************* */ /* NOTE: if but->poin is allocated memory for every defbut, things fail... */ -static int ui_but_equals_old(uiBut *but, uiBut *oldbut) +static bool ui_but_equals_old(uiBut *but, uiBut *oldbut) { /* various properties are being compared here, hopefully sufficient * to catch all cases, but it is simple to add more checks later */ - if (but->retval != oldbut->retval) return 0; - if (but->rnapoin.data != oldbut->rnapoin.data) return 0; + if (but->retval != oldbut->retval) return false; + if (but->rnapoin.data != oldbut->rnapoin.data) return false; if (but->rnaprop != oldbut->rnaprop) - if (but->rnaindex != oldbut->rnaindex) return 0; - if (but->func != oldbut->func) return 0; - if (but->funcN != oldbut->funcN) return 0; - if (oldbut->func_arg1 != oldbut && but->func_arg1 != oldbut->func_arg1) return 0; - if (oldbut->func_arg2 != oldbut && but->func_arg2 != oldbut->func_arg2) return 0; - if (!but->funcN && ((but->poin != oldbut->poin && (uiBut *)oldbut->poin != oldbut) || but->pointype != oldbut->pointype)) return 0; - if (but->optype != oldbut->optype) return 0; + if (but->rnaindex != oldbut->rnaindex) return false; + if (but->func != oldbut->func) return false; + if (but->funcN != oldbut->funcN) return false; + if (oldbut->func_arg1 != oldbut && but->func_arg1 != oldbut->func_arg1) return false; + if (oldbut->func_arg2 != oldbut && but->func_arg2 != oldbut->func_arg2) return false; + if (!but->funcN && ((but->poin != oldbut->poin && (uiBut *)oldbut->poin != oldbut) || but->pointype != oldbut->pointype)) return false; + if (but->optype != oldbut->optype) return false; - return 1; + return true; } /* oldbut is being inserted in new block, so we use the lines from new button, and replace button pointers */ @@ -682,37 +682,38 @@ static int ui_but_update_from_old_block(const bContext *C, uiBlock *block, uiBut /* needed for temporarily rename buttons, such as in outliner or file-select, * they should keep calling uiDefButs to keep them alive */ /* returns 0 when button removed */ -int uiButActiveOnly(const bContext *C, ARegion *ar, uiBlock *block, uiBut *but) +bool uiButActiveOnly(const bContext *C, ARegion *ar, uiBlock *block, uiBut *but) { uiBlock *oldblock; uiBut *oldbut; - int activate = FALSE, found = FALSE, isactive = FALSE; + bool activate = false, found = false, isactive = false; oldblock = block->oldblock; - if (!oldblock) - activate = TRUE; + if (!oldblock) { + activate = true; + } else { for (oldbut = oldblock->buttons.first; oldbut; oldbut = oldbut->next) { if (ui_but_equals_old(oldbut, but)) { - found = TRUE; + found = true; if (oldbut->active) - isactive = TRUE; + isactive = true; break; } } } - if ((activate == TRUE) || (found == FALSE)) { + if ((activate == true) || (found == false)) { ui_button_activate_do((bContext *)C, ar, but); } - else if ((found == TRUE) && (isactive == FALSE)) { + else if ((found == true) && (isactive == false)) { BLI_remlink(&block->buttons, but); ui_free_but(C, but); - return 0; + return false; } - return 1; + return true; } /* simulate button click */ @@ -1243,17 +1244,17 @@ void uiComposeLinks(uiBlock *block) /* ************************************************ */ -void uiBlockSetButLock(uiBlock *block, int val, const char *lockstr) +void uiBlockSetButLock(uiBlock *block, bool val, const char *lockstr) { if (val) { - block->lock = val ? TRUE : FALSE; + block->lock = val; block->lockstr = lockstr; } } void uiBlockClearButLock(uiBlock *block) { - block->lock = FALSE; + block->lock = false; block->lockstr = NULL; } @@ -1392,63 +1393,63 @@ void ui_set_but_vectorf(uiBut *but, const float vec[3]) } } -int ui_is_but_float(uiBut *but) +bool ui_is_but_float(uiBut *but) { if (but->pointype == UI_BUT_POIN_FLOAT && but->poin) - return 1; + return true; if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_FLOAT) - return 1; + return true; - return 0; + return false; } -int ui_is_but_bool(uiBut *but) +bool ui_is_but_bool(uiBut *but) { if (ELEM5(but->type, TOG, TOGN, TOGR, ICONTOG, ICONTOGN)) - return 1; + return true; if (but->rnaprop && RNA_property_type(but->rnaprop) == PROP_BOOLEAN) - return 1; + return true; - return 0; + return false; } -int ui_is_but_unit(uiBut *but) +bool ui_is_but_unit(uiBut *but) { UnitSettings *unit = but->block->unit; const int unit_type = uiButGetUnitType(but); if (unit_type == PROP_UNIT_NONE) - return 0; + return false; #if 1 /* removed so angle buttons get correct snapping */ if (unit->system_rotation == USER_UNIT_ROT_RADIANS && unit_type == PROP_UNIT_ROTATION) - return 0; + return false; #endif /* for now disable time unit conversion */ if (unit_type == PROP_UNIT_TIME) - return 0; + return false; if (unit->system == USER_UNIT_NONE) { if (unit_type != PROP_UNIT_ROTATION) { - return 0; + return false; } } - return 1; + return true; } -int ui_is_but_rna_valid(uiBut *but) +bool ui_is_but_rna_valid(uiBut *but) { if (but->rnaprop == NULL || RNA_struct_contains_property(&but->rnapoin, but->rnaprop)) { - return TRUE; + return true; } else { printf("property removed %s: %p\n", but->drawstr, but->rnaprop); - return FALSE; + return false; } } @@ -1789,7 +1790,7 @@ void ui_get_but_string(uiBut *but, char *str, const size_t maxlen) #ifdef WITH_PYTHON -static int ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *value) +static bool ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char *str, double *value) { char str_unit_convert[256]; const int unit_type = uiButGetUnitType(but); @@ -1807,9 +1808,9 @@ static int ui_set_but_string_eval_num_unit(bContext *C, uiBut *but, const char * #endif /* WITH_PYTHON */ -int ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double *value) +bool ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double *value) { - int ok = FALSE; + bool ok = false; #ifdef WITH_PYTHON @@ -1825,7 +1826,7 @@ int ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double ok = ui_set_but_string_eval_num_unit(C, but, str_new, value); } else { - ok = TRUE; /* parse normal string via py (no unit conversion needed) */ + ok = true; /* parse normal string via py (no unit conversion needed) */ } } else if (is_unit_but) { @@ -1848,7 +1849,7 @@ int ui_set_but_string_eval_num(bContext *C, uiBut *but, const char *str, double } -int ui_set_but_string(bContext *C, uiBut *but, const char *str) +bool ui_set_but_string(bContext *C, uiBut *but, const char *str) { if (but->rnaprop && ELEM4(but->type, TEX, IDPOIN, SEARCH_MENU, SEARCH_MENU_UNLINK)) { if (RNA_property_editable(&but->rnapoin, but->rnaprop)) { @@ -1859,7 +1860,7 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) if (type == PROP_STRING) { /* RNA string */ RNA_property_string_set(&but->rnapoin, but->rnaprop, str); - return 1; + return true; } else if (type == PROP_POINTER) { /* RNA pointer */ @@ -1868,7 +1869,7 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) if (str == NULL || str[0] == '\0') { RNA_property_pointer_set(&but->rnapoin, but->rnaprop, PointerRNA_NULL); - return 1; + return true; } else { ptr = but->rnasearchpoin; @@ -1877,18 +1878,18 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) if (prop && RNA_property_collection_lookup_string(&ptr, prop, str, &rptr)) RNA_property_pointer_set(&but->rnapoin, but->rnaprop, rptr); - return 1; + return true; } - return 0; + return false; } else if (type == PROP_ENUM) { int value; if (RNA_property_enum_value(but->block->evil_C, &but->rnapoin, but->rnaprop, str, &value)) { RNA_property_enum_set(&but->rnapoin, but->rnaprop, value); - return 1; + return true; } - return 0; + return false; } else { BLI_assert(0); @@ -1898,23 +1899,23 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) else if (but->type == IDPOIN) { /* ID pointer */ but->idpoin_func(C, str, but->idpoin_idpp); - return 1; + return true; } else if (but->type == TEX) { /* string */ if (ui_is_but_utf8(but)) BLI_strncpy_utf8(but->poin, str, but->hardmax); else BLI_strncpy(but->poin, str, but->hardmax); - return 1; + return true; } else if (ELEM(but->type, SEARCH_MENU, SEARCH_MENU_UNLINK)) { /* string */ BLI_strncpy(but->poin, str, but->hardmax); - return 1; + return true; } else if (ui_but_anim_expression_set(but, str)) { /* driver expression */ - return 1; + return true; } else if (str[0] == '#') { /* shortcut to create new driver expression (versus immediate Py-execution) */ @@ -1924,8 +1925,8 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) /* number editing */ double value; - if (ui_set_but_string_eval_num(C, but, str, &value) == FALSE) { - return 0; + if (ui_set_but_string_eval_num(C, but, str, &value) == false) { + return false; } if (!ui_is_but_float(but)) value = (int)floor(value + 0.5); @@ -1936,10 +1937,10 @@ int ui_set_but_string(bContext *C, uiBut *but, const char *str) if (value > (double)but->hardmax) value = but->hardmax; ui_set_but_val(but, value); - return 1; + return true; } - return 0; + return false; } void ui_set_but_default(bContext *C, short all) @@ -2464,15 +2465,14 @@ void uiBlockBeginAlign(uiBlock *block) /* buttons declared after this call will get this align nr */ // XXX flag? } -static int buts_are_horiz(uiBut *but1, uiBut *but2) +static bool buts_are_horiz(uiBut *but1, uiBut *but2) { float dx, dy; dx = fabs(but1->rect.xmax - but2->rect.xmin); dy = fabs(but1->rect.ymin - but2->rect.ymax); - if (dx > dy) return 0; - return 1; + return (dx <= dy); } void uiBlockEndAlign(uiBlock *block) diff --git a/source/blender/editors/interface/interface_draw.c b/source/blender/editors/interface/interface_draw.c index b9b877c1fb6..cd2a2161315 100644 --- a/source/blender/editors/interface/interface_draw.c +++ b/source/blender/editors/interface/interface_draw.c @@ -61,15 +61,6 @@ /* own include */ #include "interface_intern.h" -/* only for bug workaround [#34346] */ -#if !defined(WIN32) && !defined(__APPLE__) -# define GPU_OSS_BUG_WOKAROUND -#endif - -#ifdef GPU_OSS_BUG_WOKAROUND -# include "GPU_extensions.h" -#endif - static int roundboxtype = UI_CNR_ALL; void uiSetRoundBox(int type) @@ -402,32 +393,6 @@ void uiRoundBox(float minx, float miny, float maxx, float maxy, float rad) ui_draw_anti_roundbox(GL_POLYGON, minx, miny, maxx, maxy, rad, roundboxtype & UI_RB_ALPHA); } - -/* ************** generic embossed rect, for window sliders etc ************* */ - - -/* text_draw.c uses this */ -void uiEmboss(float x1, float y1, float x2, float y2, int sel) -{ - - /* below */ - if (sel) glColor3ub(200, 200, 200); - else glColor3ub(50, 50, 50); - fdrawline(x1, y1, x2, y1); - - /* right */ - fdrawline(x2, y1, x2, y2); - - /* top */ - if (sel) glColor3ub(50, 50, 50); - else glColor3ub(200, 200, 200); - fdrawline(x1, y2, x2, y2); - - /* left */ - fdrawline(x1, y1, x1, y2); - -} - /* ************** SPECIAL BUTTON DRAWING FUNCTIONS ************* */ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect) @@ -463,7 +428,7 @@ void ui_draw_but_IMAGE(ARegion *UNUSED(ar), uiBut *but, uiWidgetColors *UNUSED(w float facy = (float)h / (float)ibuf->y; glPixelZoom(facx, facy); } - glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect); + glaDrawPixelsAuto((float)rect->xmin, (float)rect->ymin, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, ibuf->rect); glPixelZoom(1.0f, 1.0f); @@ -1245,7 +1210,6 @@ void ui_draw_but_COLORBAND(uiBut *but, uiWidgetColors *UNUSED(wcol), rcti *rect) void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect) { - static int use_displist = -1; static GLuint displist = 0; int a, old[8]; GLfloat diff[4], diffn[4] = {1.0f, 1.0f, 1.0f, 1.0f}; @@ -1294,20 +1258,12 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect) size = BLI_rcti_size_y(rect) / 200.f; glScalef(size, size, size); - -#ifdef GPU_OSS_BUG_WOKAROUND - if (use_displist == -1) { - use_displist = !GPU_type_matches(GPU_DEVICE_ANY, GPU_OS_UNIX, GPU_DRIVER_OPENSOURCE); - } -#endif - if (displist == 0 || use_displist == 0) { + if (displist == 0) { GLUquadricObj *qobj; - if (use_displist) { - displist = glGenLists(1); - glNewList(displist, GL_COMPILE_AND_EXECUTE); - } + displist = glGenLists(1); + glNewList(displist, GL_COMPILE); qobj = gluNewQuadric(); gluQuadricDrawStyle(qobj, GLU_FILL); @@ -1316,14 +1272,11 @@ void ui_draw_but_NORMAL(uiBut *but, uiWidgetColors *wcol, rcti *rect) glShadeModel(GL_FLAT); gluDeleteQuadric(qobj); - if (use_displist) { - glEndList(); - } - } - else { - glCallList(displist); + glEndList(); } + glCallList(displist); + /* restore */ glDisable(GL_LIGHTING); glDisable(GL_CULL_FACE); diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 6d30db9c4d6..a644feca080 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -215,8 +215,8 @@ typedef struct uiAfterFunc { int autokey; } uiAfterFunc; -static int ui_but_contains_pt(uiBut *but, int mx, int my); -static int ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y); +static bool ui_but_contains_pt(uiBut *but, int mx, int my); +static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y); static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState state); static int ui_handler_region_menu(bContext *C, const wmEvent *event, void *userdata); static void ui_handle_button_activate(bContext *C, ARegion *ar, uiBut *but, uiButtonActivateType type); @@ -333,7 +333,7 @@ static void ui_mouse_scale_warp(uiHandleButtonData *data, } /* file selectors are exempt from utf-8 checks */ -int ui_is_but_utf8(uiBut *but) +bool ui_is_but_utf8(uiBut *but) { if (but->rnaprop) { const int subtype = RNA_property_subtype(but->rnaprop); @@ -5507,7 +5507,7 @@ static int ui_do_button(bContext *C, uiBlock *block, uiBut *but, const wmEvent * /* ************************ button utilities *********************** */ -static int ui_but_contains_pt(uiBut *but, int mx, int my) +static bool ui_but_contains_pt(uiBut *but, int mx, int my) { return BLI_rctf_isect_pt(&but->rect, mx, my); } @@ -5525,7 +5525,7 @@ static uiBut *ui_but_find_activated(ARegion *ar) return NULL; } -int ui_button_is_active(ARegion *ar) +bool ui_button_is_active(ARegion *ar) { return (ui_but_find_activated(ar) != NULL); } @@ -5580,7 +5580,7 @@ static void ui_blocks_set_tooltips(ARegion *ar, int enable) block->tooltipdisabled = !enable; } -static int ui_mouse_inside_region(ARegion *ar, int x, int y) +static bool ui_mouse_inside_region(ARegion *ar, int x, int y) { uiBlock *block; @@ -5589,7 +5589,7 @@ static int ui_mouse_inside_region(ARegion *ar, int x, int y) for (block = ar->uiblocks.first; block; block = block->next) block->auto_open = FALSE; - return 0; + return false; } /* also, check that with view2d, that the mouse is not over the scrollbars @@ -5608,23 +5608,23 @@ static int ui_mouse_inside_region(ARegion *ar, int x, int y) /* check if in the rect */ if (!BLI_rcti_isect_pt(&v2d->mask, mx, my)) - return 0; + return false; } - return 1; + return true; } -static int ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y) +static bool ui_mouse_inside_button(ARegion *ar, uiBut *but, int x, int y) { if (!ui_mouse_inside_region(ar, x, y)) - return 0; + return false; ui_window_to_block(ar, but->block, &x, &y); if (!ui_but_contains_pt(but, x, y)) - return 0; + return false; - return 1; + return true; } /** diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c index 09686d7b416..52710a62855 100644 --- a/source/blender/editors/interface/interface_icons.c +++ b/source/blender/editors/interface/interface_icons.c @@ -1164,7 +1164,7 @@ static void ui_id_preview_image_render_size(bContext *C, ID *id, PreviewImage *p } } -static void ui_id_icon_render(bContext *C, ID *id, int big) +static void ui_id_icon_render(bContext *C, ID *id, const bool big) { PreviewImage *pi = BKE_previewimg_get(id); @@ -1248,7 +1248,7 @@ static int ui_id_brush_get_icon(bContext *C, ID *id) return id->icon_id; } -int ui_id_icon_get(bContext *C, ID *id, int big) +int ui_id_icon_get(bContext *C, ID *id, const bool big) { int iconid = 0; @@ -1273,7 +1273,7 @@ int ui_id_icon_get(bContext *C, ID *id, int big) return iconid; } -int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, int big) +int UI_rnaptr_icon_get(bContext *C, PointerRNA *ptr, int rnaicon, const bool big) { ID *id = NULL; diff --git a/source/blender/editors/interface/interface_intern.h b/source/blender/editors/interface/interface_intern.h index e7b659f99fc..41ceeb141c9 100644 --- a/source/blender/editors/interface/interface_intern.h +++ b/source/blender/editors/interface/interface_intern.h @@ -391,18 +391,18 @@ extern void ui_hsvcircle_vals_from_pos(float *val_rad, float *val_dist, const rc extern void ui_get_but_string_ex(uiBut *but, char *str, const size_t maxlen, const int float_precision); extern void ui_get_but_string(uiBut *but, char *str, const size_t maxlen); extern void ui_convert_to_unit_alt_name(uiBut *but, char *str, size_t maxlen); -extern int ui_set_but_string(struct bContext *C, uiBut *but, const char *str); -extern int ui_get_but_string_max_length(uiBut *but); -extern int ui_set_but_string_eval_num(struct bContext *C, uiBut *but, const char *str, double *value); +extern bool ui_set_but_string(struct bContext *C, uiBut *but, const char *str); +extern bool ui_set_but_string_eval_num(struct bContext *C, uiBut *but, const char *str, double *value); +extern int ui_get_but_string_max_length(uiBut *but); extern void ui_set_but_default(struct bContext *C, short all); extern void ui_check_but(uiBut *but); -extern int ui_is_but_float(uiBut *but); -extern int ui_is_but_bool(uiBut *but); -extern int ui_is_but_unit(uiBut *but); -extern int ui_is_but_rna_valid(uiBut *but); -extern int ui_is_but_utf8(uiBut *but); +extern bool ui_is_but_float(uiBut *but); +extern bool ui_is_but_bool(uiBut *but); +extern bool ui_is_but_unit(uiBut *but); +extern bool ui_is_but_rna_valid(uiBut *but); +extern bool ui_is_but_utf8(uiBut *but); extern bool ui_is_but_interactive(uiBut *but); extern int ui_is_but_push_ex(uiBut *but, double *value); @@ -464,7 +464,7 @@ void ui_popup_block_scrolltest(struct uiBlock *block); /* searchbox for string button */ ARegion *ui_searchbox_create(struct bContext *C, struct ARegion *butregion, uiBut *but); -int ui_searchbox_inside(struct ARegion *ar, int x, int y); +bool ui_searchbox_inside(struct ARegion *ar, int x, int y); void ui_searchbox_update(struct bContext *C, struct ARegion *ar, uiBut *but, int reset); void ui_searchbox_autocomplete(struct bContext *C, struct ARegion *ar, uiBut *but, char *str); void ui_searchbox_event(struct bContext *C, struct ARegion *ar, uiBut *but, const struct wmEvent *event); @@ -511,7 +511,7 @@ extern void ui_pan_to_scroll(const struct wmEvent *event, int *type, int *val); extern void ui_button_activate_do(struct bContext *C, struct ARegion *ar, uiBut *but); extern void ui_button_execute_do(struct bContext *C, struct ARegion *ar, uiBut *but); extern void ui_button_active_free(const struct bContext *C, uiBut *but); -extern int ui_button_is_active(struct ARegion *ar); +extern bool ui_button_is_active(struct ARegion *ar); extern int ui_button_open_menu_direction(uiBut *but); extern void ui_button_text_password_hide(char password_str[UI_MAX_DRAW_STR], uiBut *but, int restore); @@ -544,7 +544,7 @@ extern unsigned char checker_stipple_sml[32 * 32 / 8]; void uiStyleInit(void); /* interface_icons.c */ -int ui_id_icon_get(struct bContext *C, struct ID *id, int preview); +int ui_id_icon_get(struct bContext *C, struct ID *id, const bool big); /* resources.c */ void init_userdef_do_versions(void); diff --git a/source/blender/editors/interface/interface_layout.c b/source/blender/editors/interface/interface_layout.c index 53887163778..4b1b96f7975 100644 --- a/source/blender/editors/interface/interface_layout.c +++ b/source/blender/editors/interface/interface_layout.c @@ -140,11 +140,11 @@ struct uiLayout { int x, y, w, h; float scale[2]; short space; - char align; - char active; - char enabled; - char redalert; - char keepaspect; + bool align; + bool active; + bool enabled; + bool redalert; + bool keepaspect; char alignment; }; @@ -1333,7 +1333,7 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, const char *s BLI_strncpy(name_ui, id->name + 2, sizeof(name_ui)); #endif name = BLI_strdup(name_ui); - iconid = ui_id_icon_get((bContext *)C, id, 0); + iconid = ui_id_icon_get((bContext *)C, id, false); } else { name = RNA_struct_name_get_alloc(&itemptr, NULL, 0, NULL); /* could use the string length here */ @@ -1359,7 +1359,7 @@ static void rna_search_cb(const struct bContext *C, void *arg_but, const char *s /* add search items from temporary list */ for (cis = items_list->first; cis; cis = cis->next) { - if (!uiSearchItemAdd(items, cis->name, SET_INT_IN_POINTER(cis->index), cis->iconid)) { + if (false == uiSearchItemAdd(items, cis->name, SET_INT_IN_POINTER(cis->index), cis->iconid)) { break; } } @@ -2267,8 +2267,8 @@ uiLayout *uiLayoutRow(uiLayout *layout, int align) litem->item.type = ITEM_LAYOUT_ROW; litem->root = layout->root; litem->align = align; - litem->active = 1; - litem->enabled = 1; + litem->active = true; + litem->enabled = true; litem->context = layout->context; litem->space = (align) ? 0 : layout->root->style->buttonspacex; litem->redalert = layout->redalert; @@ -2288,8 +2288,8 @@ uiLayout *uiLayoutColumn(uiLayout *layout, int align) litem->item.type = ITEM_LAYOUT_COLUMN; litem->root = layout->root; litem->align = align; - litem->active = 1; - litem->enabled = 1; + litem->active = true; + litem->enabled = true; litem->context = layout->context; litem->space = (litem->align) ? 0 : layout->root->style->buttonspacey; litem->redalert = layout->redalert; @@ -2309,8 +2309,8 @@ uiLayout *uiLayoutColumnFlow(uiLayout *layout, int number, int align) flow->litem.item.type = ITEM_LAYOUT_COLUMN_FLOW; flow->litem.root = layout->root; flow->litem.align = align; - flow->litem.active = 1; - flow->litem.enabled = 1; + flow->litem.active = true; + flow->litem.enabled = true; flow->litem.context = layout->context; flow->litem.space = (flow->litem.align) ? 0 : layout->root->style->columnspace; flow->litem.redalert = layout->redalert; @@ -2402,8 +2402,8 @@ uiLayout *uiLayoutOverlap(uiLayout *layout) litem = MEM_callocN(sizeof(uiLayout), "uiLayoutOverlap"); litem->item.type = ITEM_LAYOUT_OVERLAP; litem->root = layout->root; - litem->active = 1; - litem->enabled = 1; + litem->active = true; + litem->enabled = true; litem->context = layout->context; litem->redalert = layout->redalert; BLI_addtail(&layout->items, litem); @@ -2421,8 +2421,8 @@ uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align) split->litem.item.type = ITEM_LAYOUT_SPLIT; split->litem.root = layout->root; split->litem.align = align; - split->litem.active = 1; - split->litem.enabled = 1; + split->litem.active = true; + split->litem.enabled = true; split->litem.context = layout->context; split->litem.space = layout->root->style->columnspace; split->litem.redalert = layout->redalert; @@ -2435,27 +2435,27 @@ uiLayout *uiLayoutSplit(uiLayout *layout, float percentage, int align) return &split->litem; } -void uiLayoutSetActive(uiLayout *layout, int active) +void uiLayoutSetActive(uiLayout *layout, bool active) { layout->active = active; } -void uiLayoutSetEnabled(uiLayout *layout, int enabled) +void uiLayoutSetEnabled(uiLayout *layout, bool enabled) { layout->enabled = enabled; } -void uiLayoutSetRedAlert(uiLayout *layout, int redalert) +void uiLayoutSetRedAlert(uiLayout *layout, bool redalert) { layout->redalert = redalert; } -void uiLayoutSetKeepAspect(uiLayout *layout, int keepaspect) +void uiLayoutSetKeepAspect(uiLayout *layout, bool keepaspect) { layout->keepaspect = keepaspect; } -void uiLayoutSetAlignment(uiLayout *layout, int alignment) +void uiLayoutSetAlignment(uiLayout *layout, char alignment) { layout->alignment = alignment; } @@ -2470,22 +2470,22 @@ void uiLayoutSetScaleY(uiLayout *layout, float scale) layout->scale[1] = scale; } -int uiLayoutGetActive(uiLayout *layout) +bool uiLayoutGetActive(uiLayout *layout) { return layout->active; } -int uiLayoutGetEnabled(uiLayout *layout) +bool uiLayoutGetEnabled(uiLayout *layout) { return layout->enabled; } -int uiLayoutGetRedAlert(uiLayout *layout) +bool uiLayoutGetRedAlert(uiLayout *layout) { return layout->redalert; } -int uiLayoutGetKeepAspect(uiLayout *layout) +bool uiLayoutGetKeepAspect(uiLayout *layout) { return layout->keepaspect; } @@ -2937,7 +2937,7 @@ void uiLayoutOperatorButs(const bContext *C, uiLayout *layout, wmOperator *op, /* poll() on this operator may still fail, at the moment there is no nice feedback when this happens * just fails silently */ if (!WM_operator_repeat_check(C, op)) { - uiBlockSetButLock(uiLayoutGetBlock(layout), TRUE, "Operator can't' redo"); + uiBlockSetButLock(uiLayoutGetBlock(layout), true, "Operator can't' redo"); /* XXX, could give some nicer feedback or not show redo panel at all? */ uiItemL(layout, IFACE_("* Redo Unsupported *"), ICON_NONE); diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c index 145deb35667..52a26f4f528 100644 --- a/source/blender/editors/interface/interface_ops.c +++ b/source/blender/editors/interface/interface_ops.c @@ -716,7 +716,7 @@ struct uiEditSourceButStore { /* should only ever be set while the edit source operator is running */ static struct uiEditSourceStore *ui_editsource_info = NULL; -int UI_editsource_enable_check(void) +bool UI_editsource_enable_check(void) { return (ui_editsource_info != NULL); } diff --git a/source/blender/editors/interface/interface_regions.c b/source/blender/editors/interface/interface_regions.c index febd1820e5c..2ccba2e35f0 100644 --- a/source/blender/editors/interface/interface_regions.c +++ b/source/blender/editors/interface/interface_regions.c @@ -514,7 +514,7 @@ ARegion *ui_tooltip_create(bContext *C, ARegion *butregion, uiBut *but) opptr = uiButGetOperatorPtrRNA(but); /* allocated when needed, the button owns it */ /* so the context is passed to itemf functions (some py itemf functions use it) */ - WM_operator_properties_sanitize(opptr, FALSE); + WM_operator_properties_sanitize(opptr, false); str = WM_operator_pystring(C, but->optype, opptr, 0); @@ -742,8 +742,8 @@ typedef struct uiSearchboxData { uiFontStyle fstyle; uiSearchItems items; int active; /* index in items array */ - int noback; /* when menu opened with enough space for this */ - int preview; /* draw thumbnail previews, rather than list */ + bool noback; /* when menu opened with enough space for this */ + bool preview; /* draw thumbnail previews, rather than list */ int prv_rows, prv_cols; } uiSearchboxData; @@ -751,12 +751,12 @@ typedef struct uiSearchboxData { /* exported for use by search callbacks */ /* returns zero if nothing to add */ -int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid) +bool uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int iconid) { /* hijack for autocomplete */ if (items->autocpl) { autocomplete_do_name(items->autocpl, name); - return 1; + return true; } /* hijack for finding active item */ @@ -764,18 +764,18 @@ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int icon if (poin == items->active) items->offset_i = items->totitem; items->totitem++; - return 1; + return true; } if (items->totitem >= items->maxitem) { items->more = 1; - return 0; + return false; } /* skip first items in list */ if (items->offset_i > 0) { items->offset_i--; - return 1; + return true; } if (items->names) @@ -787,7 +787,7 @@ int uiSearchItemAdd(uiSearchItems *items, const char *name, void *poin, int icon items->totitem++; - return 1; + return true; } int uiSearchBoxHeight(void) @@ -867,11 +867,11 @@ static void ui_searchbox_butrect(rcti *rect, uiSearchboxData *data, int itemnr) } /* x and y in screencoords */ -int ui_searchbox_inside(ARegion *ar, int x, int y) +bool ui_searchbox_inside(ARegion *ar, int x, int y) { uiSearchboxData *data = ar->regiondata; - return(BLI_rcti_isect_pt(&data->bbox, x - ar->winrct.xmin, y - ar->winrct.ymin)); + return BLI_rcti_isect_pt(&data->bbox, x - ar->winrct.xmin, y - ar->winrct.ymin); } /* string validated to be of correct length (but->hardmax) */ @@ -1023,7 +1023,7 @@ static void ui_searchbox_region_draw_cb(const bContext *UNUSED(C), ARegion *ar) /* pixel space */ wmOrtho2(-0.01f, ar->winx - 0.01f, -0.01f, ar->winy - 0.01f); - if (!data->noback) + if (data->noback == false) ui_draw_search_back(NULL, NULL, &data->bbox); /* style not used yet */ /* draw text */ @@ -1136,10 +1136,10 @@ ARegion *ui_searchbox_create(bContext *C, ARegion *butregion, uiBut *but) /* special case, hardcoded feature, not draw backdrop when called from menus, * assume for design that popup already added it */ if (but->block->flag & UI_BLOCK_SEARCH_MENU) - data->noback = 1; + data->noback = true; if (but->a1 > 0 && but->a2 > 0) { - data->preview = 1; + data->preview = true; data->prv_rows = but->a1; data->prv_cols = but->a2; } @@ -2236,7 +2236,7 @@ uiBlock *ui_block_func_COLOR(bContext *C, uiPopupBlockHandle *handle, void *arg_ { uiBut *but = arg_but; uiBlock *block; - int show_picker = TRUE; + bool show_picker = true; block = uiBeginBlock(C, handle->region, __func__, UI_EMBOSS); @@ -2703,7 +2703,7 @@ void uiPupMenuInvoke(bContext *C, const char *idname) uiPopupMenu *pup; uiLayout *layout; Menu menu; - MenuType *mt = WM_menutype_find(idname, TRUE); + MenuType *mt = WM_menutype_find(idname, true); if (mt == NULL) { printf("%s: named menu \"%s\" not found\n", __func__, idname); diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c index 4b70b6bd63b..dd575dbf522 100644 --- a/source/blender/editors/interface/interface_templates.c +++ b/source/blender/editors/interface/interface_templates.c @@ -106,7 +106,7 @@ typedef struct TemplateID { ListBase *idlb; int prv_rows, prv_cols; - int preview; + bool preview; } TemplateID; /* Search browse menu, assign */ @@ -156,7 +156,7 @@ static void id_search_cb(const bContext *C, void *arg_template, const char *str, iconid = ui_id_icon_get((bContext *)C, id, template->preview); - if (!uiSearchItemAdd(items, name_ui, id, iconid)) + if (false == uiSearchItemAdd(items, name_ui, id, iconid)) break; } } @@ -413,13 +413,13 @@ static void template_ID(bContext *C, uiLayout *layout, TemplateID *template, Str type = idptr.type; if (flag & UI_ID_PREVIEWS) { - template->preview = TRUE; + template->preview = true; but = uiDefBlockButN(block, id_search_menu, MEM_dupallocN(template), "", 0, 0, UI_UNIT_X * 6, UI_UNIT_Y * 6, TIP_(template_id_browse_tip(type))); if (type) { but->icon = RNA_struct_ui_icon(type); - if (id) but->icon = ui_id_icon_get(C, id, 1); + if (id) but->icon = ui_id_icon_get(C, id, true); uiButSetFlag(but, UI_HAS_ICON | UI_ICON_PREVIEW); } if ((idfrom && idfrom->lib) || !editable) @@ -1217,7 +1217,7 @@ static uiLayout *draw_constraint(uiLayout *layout, Object *ob, bConstraint *con) /* Set but-locks for protected settings (magic numbers are used here!) */ if (proxy_protected) - uiBlockSetButLock(block, 1, IFACE_("Cannot edit Proxy-Protected Constraint")); + uiBlockSetButLock(block, true, IFACE_("Cannot edit Proxy-Protected Constraint")); /* Draw constraint data */ if ((con->flag & CONSTRAINT_EXPAND) == 0) { @@ -2631,7 +2631,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co sub = uiLayoutRow(overlap, FALSE); - icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE); + icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false); if (icon == ICON_DOT) icon = ICON_NONE; draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i); @@ -2665,7 +2665,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co found = (activei == i); if (found) { - icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE); + icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false); if (icon == ICON_DOT) icon = ICON_NONE; draw_item(ui_list, C, row, dataptr, &itemptr, icon, active_dataptr, active_propname, i); @@ -2712,7 +2712,7 @@ void uiTemplateList(uiLayout *layout, bContext *C, const char *listtype_name, co sub = uiLayoutRow(overlap, FALSE); - icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, FALSE); + icon = UI_rnaptr_icon_get(C, &itemptr, rnaicon, false); draw_item(ui_list, C, sub, dataptr, &itemptr, icon, active_dataptr, active_propname, i); i++; @@ -2760,7 +2760,7 @@ static void operator_search_cb(const bContext *C, void *UNUSED(arg), const char } } - if (0 == uiSearchItemAdd(items, name, ot, 0)) + if (false == uiSearchItemAdd(items, name, ot, 0)) break; } } diff --git a/source/blender/editors/interface/interface_widgets.c b/source/blender/editors/interface/interface_widgets.c index b5b10b623d2..e5f9e48c3b0 100644 --- a/source/blender/editors/interface/interface_widgets.c +++ b/source/blender/editors/interface/interface_widgets.c @@ -1349,8 +1349,8 @@ static void widget_draw_text_icon(uiFontStyle *fstyle, uiWidgetColors *wcol, uiB /* unlink icon for this button type */ if (but->type == SEARCH_MENU_UNLINK && but->drawstr[0]) { rcti temp = *rect; - - temp.xmin = temp.xmax - BLI_rcti_size_y(rect); + + temp.xmin = temp.xmax - (BLI_rcti_size_y(rect) * 1.08f); widget_draw_icon(but, ICON_X, alpha, &temp); } diff --git a/source/blender/editors/mesh/editmesh_bevel.c b/source/blender/editors/mesh/editmesh_bevel.c index d79f12551dd..a34ca4dcb9e 100644 --- a/source/blender/editors/mesh/editmesh_bevel.c +++ b/source/blender/editors/mesh/editmesh_bevel.c @@ -34,6 +34,7 @@ #include "BLF_translation.h" #include "BKE_context.h" +#include "BKE_global.h" #include "BKE_tessmesh.h" #include "RNA_define.h" @@ -45,6 +46,7 @@ #include "ED_mesh.h" #include "ED_numinput.h" #include "ED_screen.h" +#include "ED_space_api.h" #include "ED_transform.h" #include "ED_view3d.h" @@ -55,13 +57,17 @@ typedef struct { BMEditMesh *em; - BMBackup mesh_backup; - int mcenter[2]; float initial_length; float pixel_size; /* use when mouse input is interpreted as spatial distance */ - int is_modal; + bool is_modal; NumInput num_input; float shift_factor; /* The current factor when shift is pressed. Negative when shift not active. */ + + /* modal only */ + int mcenter[2]; + BMBackup mesh_backup; + void *draw_handle_pixel; + short twtype; } BevelData; #define HEADER_LENGTH 180 @@ -85,7 +91,7 @@ static void edbm_bevel_update_header(wmOperator *op, bContext *C) } } -static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) +static int edbm_bevel_init(bContext *C, wmOperator *op, const bool is_modal) { Object *obedit = CTX_data_edit_object(C); BMEditMesh *em = BMEdit_FromObject(obedit); @@ -105,8 +111,16 @@ static int edbm_bevel_init(bContext *C, wmOperator *op, int is_modal) opdata->num_input.flag = NUM_NO_NEGATIVE; /* avoid the cost of allocating a bm copy */ - if (is_modal) + if (is_modal) { + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + opdata->mesh_backup = EDBM_redo_state_store(em); + opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL); + G.moving = true; + opdata->twtype = v3d->twtype; + v3d->twtype = 0; + } return 1; } @@ -163,7 +177,12 @@ static void edbm_bevel_exit(bContext *C, wmOperator *op) } if (opdata->is_modal) { + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); EDBM_redo_state_free(&opdata->mesh_backup, NULL, false); + ED_region_draw_cb_exit(ar->type, opdata->draw_handle_pixel); + v3d->twtype = opdata->twtype; + G.moving = false; } MEM_freeN(opdata); op->customdata = NULL; diff --git a/source/blender/editors/mesh/editmesh_inset.c b/source/blender/editors/mesh/editmesh_inset.c index 10f384f5b7c..f7cf32a074f 100644 --- a/source/blender/editors/mesh/editmesh_inset.c +++ b/source/blender/editors/mesh/editmesh_inset.c @@ -34,6 +34,7 @@ #include "BLF_translation.h" #include "BKE_context.h" +#include "BKE_global.h" #include "BKE_tessmesh.h" #include "RNA_define.h" @@ -45,6 +46,7 @@ #include "ED_mesh.h" #include "ED_numinput.h" #include "ED_screen.h" +#include "ED_space_api.h" #include "ED_transform.h" #include "ED_view3d.h" @@ -56,16 +58,20 @@ typedef struct { float old_thickness; float old_depth; - int mcenter[2]; - int modify_depth; + bool modify_depth; float initial_length; float pixel_size; /* use when mouse input is interpreted as spatial distance */ - int is_modal; - int shift; + bool is_modal; + bool shift; float shift_amount; - BMBackup backup; BMEditMesh *em; NumInput num_input; + + /* modal only */ + int mcenter[2]; + BMBackup mesh_backup; + void *draw_handle_pixel; + short twtype; } InsetData; @@ -100,7 +106,7 @@ static void edbm_inset_update_header(wmOperator *op, bContext *C) } -static int edbm_inset_init(bContext *C, wmOperator *op, int is_modal) +static int edbm_inset_init(bContext *C, wmOperator *op, const bool is_modal) { InsetData *opdata; Object *obedit = CTX_data_edit_object(C); @@ -119,8 +125,16 @@ static int edbm_inset_init(bContext *C, wmOperator *op, int is_modal) initNumInput(&opdata->num_input); opdata->num_input.idx_max = 1; /* Two elements. */ - if (is_modal) - opdata->backup = EDBM_redo_state_store(em); + if (is_modal) { + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + + opdata->mesh_backup = EDBM_redo_state_store(em); + opdata->draw_handle_pixel = ED_region_draw_cb_activate(ar->type, ED_region_draw_mouse_line_cb, opdata->mcenter, REGION_DRAW_POST_PIXEL); + G.moving = true; + opdata->twtype = v3d->twtype; + v3d->twtype = 0; + } return 1; } @@ -132,8 +146,14 @@ static void edbm_inset_exit(bContext *C, wmOperator *op) opdata = op->customdata; - if (opdata->is_modal) - EDBM_redo_state_free(&opdata->backup, NULL, false); + if (opdata->is_modal) { + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + EDBM_redo_state_free(&opdata->mesh_backup, NULL, false); + ED_region_draw_cb_exit(ar->type, opdata->draw_handle_pixel); + v3d->twtype = opdata->twtype; + G.moving = false; + } if (sa) { ED_area_headerprint(sa, NULL); @@ -147,7 +167,7 @@ static int edbm_inset_cancel(bContext *C, wmOperator *op) opdata = op->customdata; if (opdata->is_modal) { - EDBM_redo_state_free(&opdata->backup, opdata->em, true); + EDBM_redo_state_free(&opdata->mesh_backup, opdata->em, true); EDBM_update_generic(opdata->em, false, true); } @@ -176,7 +196,7 @@ static int edbm_inset_calc(wmOperator *op) em = opdata->em; if (opdata->is_modal) { - EDBM_redo_state_restore(opdata->backup, em, false); + EDBM_redo_state_restore(opdata->mesh_backup, em, false); } EDBM_op_init(em, &bmop, op, diff --git a/source/blender/editors/mesh/editmesh_tools.c b/source/blender/editors/mesh/editmesh_tools.c index 5befcd7b5f2..0e4161d232d 100644 --- a/source/blender/editors/mesh/editmesh_tools.c +++ b/source/blender/editors/mesh/editmesh_tools.c @@ -199,9 +199,9 @@ void EMBM_project_snap_verts(bContext *C, ARegion *ar, BMEditMesh *em) BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) { if (BM_elem_flag_test(eve, BM_ELEM_SELECT)) { float mval[2], co_proj[3], no_dummy[3]; - int dist_dummy; + float dist_px_dummy; if (ED_view3d_project_float_object(ar, eve->co, mval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - if (snapObjectsContext(C, mval, &dist_dummy, co_proj, no_dummy, SNAP_NOT_OBEDIT)) { + if (snapObjectsContext(C, mval, &dist_px_dummy, co_proj, no_dummy, SNAP_NOT_OBEDIT)) { mul_v3_m4v3(eve->co, obedit->imat, co_proj); } } diff --git a/source/blender/editors/object/object_add.c b/source/blender/editors/object/object_add.c index b33c7212f0e..d63a964c26a 100644 --- a/source/blender/editors/object/object_add.c +++ b/source/blender/editors/object/object_add.c @@ -1786,8 +1786,8 @@ static Base *object_add_duplicate_internal(Main *bmain, Scene *scene, Base *base if ((basen->flag & OB_FROMGROUP) || ob->rigidbody_object || ob->rigidbody_constraint) { Group *group; for (group = bmain->group.first; group; group = group->id.next) { - if (object_in_group(ob, group)) - add_to_group(group, obn, scene, basen); + if (BKE_group_object_exists(group, ob)) + BKE_group_object_add(group, obn, scene, basen); } } diff --git a/source/blender/editors/object/object_group.c b/source/blender/editors/object/object_group.c index 3112bb21091..8afd3049b84 100644 --- a/source/blender/editors/object/object_group.c +++ b/source/blender/editors/object/object_group.c @@ -78,7 +78,7 @@ static EnumPropertyItem *group_object_active_itemf(bContext *C, PointerRNA *UNUS Group *group = NULL; int i = 0; - while ((group = find_group(ob, group))) { + while ((group = BKE_group_object_find(group, ob))) { item_tmp.identifier = item_tmp.name = group->id.name + 2; /* item_tmp.icon = ICON_ARMATURE_DATA; */ item_tmp.value = i; @@ -98,7 +98,7 @@ static Group *group_object_active_find_index(Object *ob, const int group_object_ { Group *group = NULL; int i = 0; - while ((group = find_group(ob, group))) { + while ((group = BKE_group_object_find(group, ob))) { if (i == group_object_index) { break; } @@ -125,7 +125,7 @@ static int objects_add_active_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { if (base->object->dup_group != group) { - add_to_group(group, base->object, scene, base); + BKE_group_object_add(group, base->object, scene, base); } else { is_cycle = TRUE; @@ -184,11 +184,11 @@ static int objects_remove_active_exec(bContext *C, wmOperator *op) * looking up the active objects groups each time */ for (group = bmain->group.first; group; group = group->id.next) { - if (object_in_group(ob, group)) { + if (BKE_group_object_exists(group, ob)) { /* Assign groups to selected objects */ CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { - rem_from_group(group, base->object, scene, base); + BKE_group_object_unlink(group, base->object, scene, base); ok = 1; } CTX_DATA_END; @@ -265,7 +265,7 @@ static int group_objects_remove_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases) { - rem_from_group(group, base->object, scene, base); + BKE_group_object_unlink(group, base->object, scene, base); } CTX_DATA_END; @@ -311,11 +311,11 @@ static int group_create_exec(bContext *C, wmOperator *op) RNA_string_get(op->ptr, "name", name); - group = add_group(bmain, name); + group = BKE_group_add(bmain, name); CTX_DATA_BEGIN (C, Base *, base, selected_bases) { - add_to_group(group, base->object, scene, base); + BKE_group_object_add(group, base->object, scene, base); } CTX_DATA_END; @@ -354,8 +354,8 @@ static int group_add_exec(bContext *C, wmOperator *UNUSED(op)) if (ob == NULL) return OPERATOR_CANCELLED; - group = add_group(bmain, "Group"); - add_to_group(group, ob, scene, NULL); + group = BKE_group_add(bmain, "Group"); + BKE_group_object_add(group, ob, scene, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -386,7 +386,7 @@ static int group_link_exec(bContext *C, wmOperator *op) if (ELEM(NULL, ob, group)) return OPERATOR_CANCELLED; - add_to_group(group, ob, scene, NULL); + BKE_group_object_add(group, ob, scene, NULL); WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); @@ -425,7 +425,7 @@ static int group_remove_exec(bContext *C, wmOperator *UNUSED(op)) if (!ob || !group) return OPERATOR_CANCELLED; - rem_from_group(group, ob, scene, NULL); /* base will be used if found */ + BKE_group_object_unlink(group, ob, scene, NULL); /* base will be used if found */ WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob); diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index 34a6d359f6b..cdc920ba3ec 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1486,7 +1486,7 @@ static int make_links_data_exec(bContext *C, wmOperator *op) /* now add in the groups from the link nodes */ for (group_node = ob_groups; group_node; group_node = group_node->next) { if (ob_dst->dup_group != group_node->link) { - add_to_group(group_node->link, ob_dst, scene, base_dst); + BKE_group_object_add(group_node->link, ob_dst, scene, base_dst); } else { is_cycle = TRUE; diff --git a/source/blender/editors/object/object_select.c b/source/blender/editors/object/object_select.c index b7303b2af51..974dc3acef9 100644 --- a/source/blender/editors/object/object_select.c +++ b/source/blender/editors/object/object_select.c @@ -586,7 +586,7 @@ static short select_grouped_group(bContext *C, Object *ob) /* Select objects in uiLayout *layout; for (group = CTX_data_main(C)->group.first; group && group_count < GROUP_MENU_MAX; group = group->id.next) { - if (object_in_group(ob, group)) { + if (BKE_group_object_exists(group, ob)) { ob_groups[group_count] = group; group_count++; } @@ -598,7 +598,7 @@ static short select_grouped_group(bContext *C, Object *ob) /* Select objects in group = ob_groups[0]; CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (!(base->flag & SELECT) && object_in_group(base->object, group)) { + if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) { ED_base_object_select(base, BA_SELECT); changed = 1; } @@ -1040,7 +1040,7 @@ static int object_select_same_group_exec(bContext *C, wmOperator *op) CTX_DATA_BEGIN (C, Base *, base, visible_bases) { - if (!(base->flag & SELECT) && object_in_group(base->object, group)) + if (!(base->flag & SELECT) && BKE_group_object_exists(group, base->object)) ED_base_object_select(base, BA_SELECT); } CTX_DATA_END; diff --git a/source/blender/editors/physics/rigidbody_constraint.c b/source/blender/editors/physics/rigidbody_constraint.c index b3f92d3de46..d38ffa491e2 100644 --- a/source/blender/editors/physics/rigidbody_constraint.c +++ b/source/blender/editors/physics/rigidbody_constraint.c @@ -88,14 +88,14 @@ void ED_rigidbody_con_add(wmOperator *op, Scene *scene, Object *ob, int type) } /* create constraint group if it doesn't already exits */ if (rbw->constraints == NULL) { - rbw->constraints = add_group(G.main, "RigidBodyConstraints"); + rbw->constraints = BKE_group_add(G.main, "RigidBodyConstraints"); } /* make rigidbody constraint settings */ ob->rigidbody_constraint = BKE_rigidbody_create_constraint(scene, ob, type); ob->rigidbody_constraint->flag |= RBC_FLAG_NEEDS_VALIDATE; /* add constraint to rigid body constraint group */ - add_to_group(rbw->constraints, ob, scene, NULL); + BKE_group_object_add(rbw->constraints, ob, scene, NULL); DAG_id_tag_update(&ob->id, OB_RECALC_OB); } @@ -106,7 +106,7 @@ void ED_rigidbody_con_remove(Scene *scene, Object *ob) BKE_rigidbody_remove_constraint(scene, ob); if (rbw) - rem_from_group(rbw->constraints, ob, scene, NULL); + BKE_group_object_unlink(rbw->constraints, ob, scene, NULL); DAG_id_tag_update(&ob->id, OB_RECALC_OB); } diff --git a/source/blender/editors/physics/rigidbody_object.c b/source/blender/editors/physics/rigidbody_object.c index 9c03c6173a5..9f981256a31 100644 --- a/source/blender/editors/physics/rigidbody_object.c +++ b/source/blender/editors/physics/rigidbody_object.c @@ -111,7 +111,7 @@ void ED_rigidbody_ob_add(wmOperator *op, Scene *scene, Object *ob, int type) scene->rigidbody_world = rbw; } if (rbw->group == NULL) { - rbw->group = add_group(G.main, "RigidBodyWorld"); + rbw->group = BKE_group_add(G.main, "RigidBodyWorld"); } /* make rigidbody object settings */ @@ -122,7 +122,7 @@ void ED_rigidbody_ob_add(wmOperator *op, Scene *scene, Object *ob, int type) ob->rigidbody_object->flag |= RBO_FLAG_NEEDS_VALIDATE; /* add object to rigid body group */ - add_to_group(rbw->group, ob, scene, NULL); + BKE_group_object_add(rbw->group, ob, scene, NULL); DAG_id_tag_update(&ob->id, OB_RECALC_OB); } @@ -133,7 +133,7 @@ void ED_rigidbody_ob_remove(Scene *scene, Object *ob) BKE_rigidbody_remove_object(scene, ob); if (rbw) - rem_from_group(rbw->group, ob, scene, NULL); + BKE_group_object_unlink(rbw->group, ob, scene, NULL); DAG_id_tag_update(&ob->id, OB_RECALC_OB); } diff --git a/source/blender/editors/render/render_internal.c b/source/blender/editors/render/render_internal.c index 365ac02d15b..6832cd5baa0 100644 --- a/source/blender/editors/render/render_internal.c +++ b/source/blender/editors/render/render_internal.c @@ -143,7 +143,7 @@ void image_buffer_rect_update(Scene *scene, RenderResult *rr, ImBuf *ibuf, volat if (ibuf->rect == NULL) imb_addrectImBuf(ibuf); - + rectf += 4 * (rr->rectx * ymin + xmin); IMB_partial_display_buffer_update(ibuf, rectf, NULL, rr->rectx, rxmin, rymin, @@ -429,10 +429,38 @@ static void render_endjob(void *rjv) nodeUpdateID(rj->scene->nodetree, &rj->scene->id); WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene); } - + /* XXX render stability hack */ G.is_rendering = FALSE; WM_main_add_notifier(NC_WINDOW, NULL); + + /* Partial render result will always update display buffer + * for first render layer only. This is nice because you'll + * see render progress during rendering, but it ends up in + * wrong display buffer shown after rendering. + * + * The code below will mark display buffer as invalid after + * rendering in case multiple layers were rendered, which + * ensures display buffer matches render layer after + * rendering. + * + * Perhaps proper way would be to toggle active render + * layer in image editor and job, so we always display + * layer being currently rendered. But this is not so much + * trivial at this moment, especially because of external + * engine API, so lets use simple and robust way for now + * - sergey - + */ + if (rj->scene->r.layers.first != rj->scene->r.layers.last) { + void *lock; + Image *ima = rj->image; + ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); + + if (ibuf) + ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; + + BKE_image_release_ibuf(ima, ibuf, lock); + } } /* called by render, check job 'stop' value or the global */ diff --git a/source/blender/editors/render/render_opengl.c b/source/blender/editors/render/render_opengl.c index f47d737beca..9d443fab552 100644 --- a/source/blender/editors/render/render_opengl.c +++ b/source/blender/editors/render/render_opengl.c @@ -69,6 +69,8 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "BIF_gl.h" +#include "BIF_glutil.h" #include "GPU_extensions.h" @@ -261,11 +263,14 @@ static void screen_opengl_render_apply(OGLRender *oglrender) */ if (!oglrender->is_sequencer) { - /* sequencer has got tricker ocnversion happened above */ - - IMB_buffer_float_from_float(rr->rectf, rr->rectf, - 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, TRUE, - oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); + /* sequencer has got trickier conversion happened above + * also assume opengl's space matches byte buffer color space + */ + if (!glaBufferTransformFromRole_glsl(rr->rectf, oglrender->sizex, oglrender->sizey, COLOR_ROLE_DEFAULT_BYTE)) { + IMB_buffer_float_from_float(rr->rectf, rr->rectf, + 4, IB_PROFILE_LINEAR_RGB, IB_PROFILE_SRGB, TRUE, + oglrender->sizex, oglrender->sizey, oglrender->sizex, oglrender->sizex); + } } /* rr->rectf is now filled with image data */ diff --git a/source/blender/editors/screen/CMakeLists.txt b/source/blender/editors/screen/CMakeLists.txt index 33373354aa4..c9c4c253e28 100644 --- a/source/blender/editors/screen/CMakeLists.txt +++ b/source/blender/editors/screen/CMakeLists.txt @@ -25,6 +25,7 @@ set(INC ../../blenlib ../../blenloader ../../bmesh + ../../gpu ../../imbuf ../../makesdna ../../makesrna diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c index 89315e041de..3469604b3dd 100644 --- a/source/blender/editors/screen/glutil.c +++ b/source/blender/editors/screen/glutil.c @@ -42,11 +42,18 @@ #include "BLI_threads.h" #include "BKE_blender.h" +#include "BKE_global.h" #include "BKE_colortools.h" +#include "BKE_context.h" #include "BIF_gl.h" #include "BIF_glutil.h" +#include "GPU_extensions.h" + +#include "IMB_colormanagement.h" +#include "IMB_imbuf_types.h" + #ifndef GL_CLAMP_TO_EDGE #define GL_CLAMP_TO_EDGE 0x812F #endif @@ -482,7 +489,7 @@ static int get_cached_work_texture(int *w_r, int *h_r) return texid; } -void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect, float scaleX, float scaleY) +void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect, float scaleX, float scaleY) { unsigned char *uc_rect = (unsigned char *) rect; float *f_rect = (float *)rect; @@ -492,7 +499,8 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, int subpart_x, subpart_y, tex_w, tex_h; int seamless, offset_x, offset_y, nsubparts_x, nsubparts_y; int texid = get_cached_work_texture(&tex_w, &tex_h); - + int components; + /* Specify the color outside this function, and tex will modulate it. * This is useful for changing alpha without using glPixelTransferf() */ @@ -519,13 +527,24 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, nsubparts_x = (img_w + (offset_x - 1)) / (offset_x); nsubparts_y = (img_h + (offset_y - 1)) / (offset_y); - if (format == GL_FLOAT) { + if (format == GL_RGBA) + components = 4; + else if (format == GL_RGB) + components = 3; + else if (format == GL_LUMINANCE) + components = 1; + else { + BLI_assert(!"Incompatible format passed to glaDrawPixelsTexScaled"); + return; + } + + if (type == GL_FLOAT) { /* need to set internal format to higher range float */ - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, tex_w, tex_h, 0, GL_RGBA, GL_FLOAT, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F_ARB, tex_w, tex_h, 0, format, GL_FLOAT, NULL); } else { /* switch to 8bit RGBA for byte buffer */ - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, tex_w, tex_h, 0, format, GL_UNSIGNED_BYTE, NULL); } for (subpart_y = 0; subpart_y < nsubparts_y; subpart_y++) { @@ -545,26 +564,26 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, if (subpart_w <= seamless || subpart_h <= seamless) continue; - if (format == GL_FLOAT) { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * 4 + subpart_x * offset_x * 4]); + if (type == GL_FLOAT) { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]); /* add an extra border of pixels so linear looks ok at edges of full image. */ if (subpart_w < tex_w) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, GL_RGBA, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_FLOAT, &f_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); if (subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + subpart_x * offset_x * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w && subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, GL_RGBA, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_FLOAT, &f_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * 4 + subpart_x * offset_x * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, subpart_w, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, 0, 1, subpart_h, format, GL_UNSIGNED_BYTE, &uc_rect[subpart_y * offset_y * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); if (subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + subpart_x * offset_x * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, subpart_h, subpart_w, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + subpart_x * offset_x * components]); if (subpart_w < tex_w && subpart_h < tex_h) - glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * 4 + (subpart_x * offset_x + subpart_w - 1) * 4]); + glTexSubImage2D(GL_TEXTURE_2D, 0, subpart_w, subpart_h, 1, 1, format, GL_UNSIGNED_BYTE, &uc_rect[(subpart_y * offset_y + subpart_h - 1) * img_w * components + (subpart_x * offset_x + subpart_w - 1) * components]); } glEnable(GL_TEXTURE_2D); @@ -595,9 +614,9 @@ void glaDrawPixelsTexScaled(float x, float y, int img_w, int img_h, int format, #endif } -void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect) +void glaDrawPixelsTex(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect) { - glaDrawPixelsTexScaled(x, y, img_w, img_h, format, zoomfilter, rect, 1.0f, 1.0f); + glaDrawPixelsTexScaled(x, y, img_w, img_h, format, type, zoomfilter, rect, 1.0f, 1.0f); } void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int format, int type, void *rect) @@ -680,7 +699,7 @@ void glaDrawPixelsSafe(float x, float y, int img_w, int img_h, int row_w, int fo } /* uses either DrawPixelsSafe or DrawPixelsTex, based on user defined maximum */ -void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int zoomfilter, void *rect) +void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int type, int zoomfilter, void *rect) { if (U.image_gpubuffer_limit) { /* Megapixels, use float math to prevent overflow */ @@ -688,11 +707,11 @@ void glaDrawPixelsAuto(float x, float y, int img_w, int img_h, int format, int z if (U.image_gpubuffer_limit > (int)img_size) { glColor4f(1.0, 1.0, 1.0, 1.0); - glaDrawPixelsTex(x, y, img_w, img_h, format, zoomfilter, rect); + glaDrawPixelsTex(x, y, img_w, img_h, format, type, zoomfilter, rect); return; } } - glaDrawPixelsSafe(x, y, img_w, img_h, img_w, GL_RGBA, format, rect); + glaDrawPixelsSafe(x, y, img_w, img_h, img_w, format, type, rect); } /* 2D Drawing Assistance */ @@ -753,6 +772,18 @@ void gla2DSetMap(gla2DDrawInfo *di, rctf *rect) di->wo_to_sc[1] = sc_h / wo_h; } +/** Save the current OpenGL state and initialize OpenGL for 2D + * rendering. glaEnd2DDraw should be called on the returned structure + * to free it and to return OpenGL to its previous state. The + * scissor rectangle is set to match the viewport. + * + * See glaDefine2DArea for an explanation of why this function uses integers. + * + * \param screen_rect The screen rectangle to be used for 2D drawing. + * \param world_rect The world rectangle that the 2D area represented + * by \a screen_rect is supposed to represent. If NULL it is assumed the + * world has a 1 to 1 mapping to the screen. + */ gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect) { gla2DDrawInfo *di = MEM_mallocN(sizeof(*di), "gla2DDrawInfo"); @@ -788,17 +819,27 @@ gla2DDrawInfo *glaBegin2DDraw(rcti *screen_rect, rctf *world_rect) return di; } +/** + * Translate the (\a wo_x, \a wo_y) point from world coordinates into screen space. + */ void gla2DDrawTranslatePt(gla2DDrawInfo *di, float wo_x, float wo_y, int *sc_x_r, int *sc_y_r) { *sc_x_r = (wo_x - di->world_rect.xmin) * di->wo_to_sc[0]; *sc_y_r = (wo_y - di->world_rect.ymin) * di->wo_to_sc[1]; } + +/** + * Translate the \a world point from world coordiantes into screen space. + */ void gla2DDrawTranslatePtv(gla2DDrawInfo *di, float world[2], int screen_r[2]) { screen_r[0] = (world[0] - di->world_rect.xmin) * di->wo_to_sc[0]; screen_r[1] = (world[1] - di->world_rect.ymin) * di->wo_to_sc[1]; } +/** + * Restores the previous OpenGL state and free's the auxilary gla data. + */ void glaEnd2DDraw(gla2DDrawInfo *di) { glViewport(di->orig_vp[0], di->orig_vp[1], di->orig_vp[2], di->orig_vp[3]); @@ -983,3 +1024,163 @@ void bglFlush(void) #endif } #endif + +/* **** Color management helper functions for GLSL display/transform ***** */ + +/* Draw given image buffer on a screen using GLSL for display transform */ +void glaDrawImBuf_glsl_ctx(const bContext *C, ImBuf *ibuf, float x, float y, int zoomfilter) +{ + bool force_fallback = false; + bool need_fallback = true; + + /* Early out */ + if (ibuf->rect == NULL && ibuf->rect_float == NULL) + return; + + /* Dithering is not supported on GLSL yet */ + force_fallback = ibuf->dither != 0.0f; + + /* Single channel images could not be transformed using GLSL yet */ + force_fallback = ibuf->channels == 1; + + /* This is actually lots of crap, but currently not sure about + * more clear way to bypass partial buffer update crappyness + * while rendering. + * + * The thing is -- render engines are only updating byte and + * display buffers for active render result opened in image + * editor. This works fine to show render progress without + * switching render layers in image editor user, but this is + * completely useless for GLSL display, where we need to have + * original buffer which we could color manage. + * + * For the time of rendering, we'll stick back to slower CPU + * display buffer update. GLSL could be used as soon as some + * fixes (?) are done in render itself, so we'll always have + * image buffer with relevant float buffer opened while + * rendering. + * + * On the other hand, when using Cycles, stressing GPU with + * GLSL could backfire on a performance. + * - sergey - + */ + if (G.is_rendering) { + /* Try to detect whether we're drawing render result, + * other images could have both rect and rect_float + * but they'll be synchronized + */ + if (ibuf->rect_float && ibuf->rect && + ((ibuf->mall & IB_rectfloat) == 0)) + { + force_fallback = true; + } + } + + /* Try to draw buffer using GLSL display transform */ + if (force_fallback == false) { + int ok; + + if (ibuf->rect_float) + ok = IMB_colormanagement_setup_glsl_draw_ctx(C, TRUE); + else + ok = IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, ibuf->rect_colorspace, FALSE); + + if (ok) { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor4f(1.0, 1.0, 1.0, 1.0); + + if (ibuf->rect_float) { + int format = 0; + + if (ibuf->channels == 3) + format = GL_RGB; + else if (ibuf->channels == 4) + format = GL_RGBA; + else + BLI_assert(!"Incompatible number of channels for GLSL display"); + + if (format != 0) { + glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, format, GL_FLOAT, + zoomfilter, ibuf->rect_float); + } + } + else if (ibuf->rect) { + /* ibuf->rect is always RGBA */ + glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, + zoomfilter, ibuf->rect); + } + + IMB_colormanagement_finish_glsl_draw(); + + need_fallback = false; + } + } + + /* In case GLSL failed or not usable, fallback to glaDrawPixelsAuto */ + if (need_fallback) { + unsigned char *display_buffer; + void *cache_handle; + + display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); + + if (display_buffer) + glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, + zoomfilter, display_buffer); + + IMB_display_buffer_release(cache_handle); + } +} + +/* Transform buffer from role to scene linear space using GLSL OCIO conversion + * + * See IMB_colormanagement_setup_transform_from_role_glsl description for + * some more details + * + * NOTE: this only works for RGBA buffers! + */ +int glaBufferTransformFromRole_glsl(float *buffer, int width, int height, int role) +{ + GPUOffScreen *ofs; + char err_out[256]; + rcti display_rect; + + ofs = GPU_offscreen_create(width, height, err_out); + + if (!ofs) + return FALSE; + + GPU_offscreen_bind(ofs); + + if (!IMB_colormanagement_setup_transform_from_role_glsl(role, TRUE)) { + GPU_offscreen_unbind(ofs); + GPU_offscreen_free(ofs); + return FALSE; + } + + BLI_rcti_init(&display_rect, 0, width, 0, height); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + glaDefine2DArea(&display_rect); + + glaDrawPixelsTex(0, 0, width, height, GL_RGBA, GL_FLOAT, + GL_NEAREST, buffer); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + GPU_offscreen_read_pixels(ofs, GL_FLOAT, buffer); + + IMB_colormanagement_finish_glsl_transform(); + + /* unbind */ + GPU_offscreen_unbind(ofs); + GPU_offscreen_free(ofs); + + return TRUE; +} diff --git a/source/blender/editors/sculpt_paint/paint_ops.c b/source/blender/editors/sculpt_paint/paint_ops.c index cd9523f8ff6..40a18734948 100644 --- a/source/blender/editors/sculpt_paint/paint_ops.c +++ b/source/blender/editors/sculpt_paint/paint_ops.c @@ -62,7 +62,7 @@ static int brush_add_exec(bContext *C, wmOperator *UNUSED(op)) { /*int type = RNA_enum_get(op->ptr, "type");*/ Paint *paint = paint_get_active_from_context(C); - struct Brush *br = paint_brush(paint); + Brush *br = paint_brush(paint); Main *bmain = CTX_data_main(C); if (br) @@ -94,7 +94,7 @@ static int brush_scale_size_exec(bContext *C, wmOperator *op) { Scene *scene = CTX_data_scene(C); Paint *paint = paint_get_active_from_context(C); - struct Brush *brush = paint_brush(paint); + Brush *brush = paint_brush(paint); // Object *ob = CTX_data_active_object(C); float scalar = RNA_float_get(op->ptr, "scalar"); @@ -176,10 +176,10 @@ static void PAINT_OT_vertex_color_set(wmOperatorType *ot) static int brush_reset_exec(bContext *C, wmOperator *UNUSED(op)) { Paint *paint = paint_get_active_from_context(C); - struct Brush *brush = paint_brush(paint); + Brush *brush = paint_brush(paint); Object *ob = CTX_data_active_object(C); - if (!ob) return OPERATOR_CANCELLED; + if (!ob || !brush) return OPERATOR_CANCELLED; if (ob->mode & OB_MODE_SCULPT) BKE_brush_sculpt_reset(brush); @@ -215,7 +215,7 @@ static void brush_tool_set(const Brush *brush, size_t tool_offset, int tool) /* generic functions for setting the active brush based on the tool */ static Brush *brush_tool_cycle(Main *bmain, Brush *brush_orig, const int tool, const size_t tool_offset, const int ob_mode) { - struct Brush *brush; + Brush *brush; if (!brush_orig && !(brush_orig = bmain->brush.first)) { return NULL; @@ -266,7 +266,7 @@ static int brush_generic_tool_set(Main *bmain, Paint *paint, const int tool, const char *tool_name, int create_missing, int toggle) { - struct Brush *brush, *brush_orig = paint_brush(paint); + Brush *brush, *brush_orig = paint_brush(paint); if (toggle) brush = brush_tool_toggle(bmain, brush_orig, tool, tool_offset, ob_mode); @@ -467,7 +467,7 @@ typedef struct { static int stencil_control_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Paint *paint = paint_get_active_from_context(C); - Brush *br = paint->brush; + Brush *br = paint_brush(paint); int mdiff[2]; StencilControlData *scd = MEM_mallocN(sizeof(StencilControlData), "stencil_control"); @@ -520,7 +520,7 @@ static int stencil_control_modal(bContext *C, wmOperator *op, const wmEvent *eve float len, factor; sub_v2_v2v2_int(mdiff, event->mval, scd->br->stencil_pos); len = sqrtf(mdiff[0] * mdiff[0] + mdiff[1] * mdiff[1]); - factor = len/scd->lenorig; + factor = len / scd->lenorig; mdiff[0] = factor * scd->init_sdim[0]; mdiff[1] = factor * scd->init_sdim[1]; copy_v2_v2_int(scd->br->stencil_dimension, mdiff); @@ -567,15 +567,15 @@ static int stencil_control_modal(bContext *C, wmOperator *op, const wmEvent *eve static int stencil_control_poll(bContext *C) { Paint *paint = paint_get_active_from_context(C); - Brush *br = paint->brush; + Brush *br = paint_brush(paint); - return br->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL; + return (br && br->mtex.brush_map_mode == MTEX_MAP_MODE_STENCIL); } static void BRUSH_OT_stencil_control(wmOperatorType *ot) { static EnumPropertyItem stencil_control_items[] = { - {STENCIL_TRANSLATE, "TRANSLATION", 0, "Transation", ""}, + {STENCIL_TRANSLATE, "TRANSLATION", 0, "Translation", ""}, {STENCIL_SCALE, "SCALE", 0, "Scale", ""}, {STENCIL_ROTATE, "ROTATION", 0, "Rotation", ""}, {0, NULL, 0, NULL, NULL} diff --git a/source/blender/editors/sculpt_paint/paint_utils.c b/source/blender/editors/sculpt_paint/paint_utils.c index 47e20bcc5fb..315fdd2fb32 100644 --- a/source/blender/editors/sculpt_paint/paint_utils.c +++ b/source/blender/editors/sculpt_paint/paint_utils.c @@ -381,7 +381,9 @@ void paint_sample_color(const bContext *C, ARegion *ar, int x, int y) /* fron static int brush_curve_preset_exec(bContext *C, wmOperator *op) { Brush *br = paint_brush(paint_get_active_from_context(C)); - BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape")); + + if (br) + BKE_brush_curve_preset(br, RNA_enum_get(op->ptr, "shape")); return OPERATOR_FINISHED; } diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h index 82a07c9e3be..1060999e13f 100644 --- a/source/blender/editors/sculpt_paint/sculpt_intern.h +++ b/source/blender/editors/sculpt_paint/sculpt_intern.h @@ -54,8 +54,6 @@ struct SculptUndoNode; /* Interface */ struct MultiresModifierData *sculpt_multires_active(struct Scene *scene, struct Object *ob); -void sculpt(struct Sculpt *sd); - int sculpt_mode_poll(struct bContext *C); int sculpt_mode_poll_view3d(struct bContext *C); int sculpt_poll(struct bContext *C); diff --git a/source/blender/editors/space_action/action_select.c b/source/blender/editors/space_action/action_select.c index b6d2d31f0ad..eb755e162a3 100644 --- a/source/blender/editors/space_action/action_select.c +++ b/source/blender/editors/space_action/action_select.c @@ -277,7 +277,7 @@ static void borderselect_action(bAnimContext *ac, rcti rect, short mode, short s Mask *mask = ale->data; MaskLayer *masklay; for (masklay = mask->masklayers.first; masklay; masklay = masklay->next) { - ED_masklayer_frames_select_border(ale->data, rectf.xmin, rectf.xmax, selectmode); + ED_masklayer_frames_select_border(masklay, rectf.xmin, rectf.xmax, selectmode); } break; } diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c index b108f9fa4b5..5a7d70d279c 100644 --- a/source/blender/editors/space_buttons/buttons_texture.c +++ b/source/blender/editors/space_buttons/buttons_texture.c @@ -205,7 +205,6 @@ static void buttons_texture_users_from_context(ListBase *users, const bContext * /* particle systems */ if (psys) { - /* todo: these slots are not in the UI */ for (a = 0; a < MAX_MTEX; a++) { mtex = psys->part->mtex[a]; @@ -333,6 +332,17 @@ static void template_texture_select(bContext *C, void *user_p, void *UNUSED(arg) tex = (RNA_struct_is_a(texptr.type, &RNA_Texture)) ? texptr.data : NULL; ct->texture = tex; + + if (user->ptr.type == &RNA_ParticleSettingsTextureSlot) { + /* stupid exception for particle systems which still uses influence + * from the old texture system, set the active texture slots as well */ + ParticleSettings *part = user->ptr.id.data; + int a; + + for (a = 0; a < MAX_MTEX; a++) + if (user->ptr.data == part->mtex[a]) + part->texact = a; + } } ct->user = user; diff --git a/source/blender/editors/space_clip/clip_draw.c b/source/blender/editors/space_clip/clip_draw.c index cbca2f0c46e..1000aced3a9 100644 --- a/source/blender/editors/space_clip/clip_draw.c +++ b/source/blender/editors/space_clip/clip_draw.c @@ -248,53 +248,6 @@ static void draw_movieclip_notes(SpaceClip *sc, ARegion *ar) ED_region_info_draw(ar, str, block, 0.6f); } -static void draw_movieclip_buffer_glsl(SpaceClip *sc, ImBuf *ibuf, int x, int y, - float zoomx, float zoomy) -{ - MovieClip *clip = ED_space_clip_get_clip(sc); - int filter = GL_LINEAR; - - glPushMatrix(); - glTranslatef(x, y, 0.0f); - glScalef(zoomx, zoomy, 1.0f); - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - glColor4f(1.0, 1.0, 1.0, 1.0); - - /* non-scaled proxy shouldn;t use diltering */ - if ((clip->flag & MCLIP_USE_PROXY) == 0 || - ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100)) - { - filter = GL_NEAREST; - } - - glaDrawPixelsTex(0, 0, ibuf->x, ibuf->y, GL_FLOAT, filter, ibuf->rect_float); - - glPopMatrix(); -} - -static void draw_movieclip_buffer_fallback(const bContext *C, ImBuf *ibuf, int x, int y, - int width, int height, float zoomx, float zoomy) -{ - unsigned char *display_buffer; - void *cache_handle; - - display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); - - if (display_buffer) { - /* set zoom */ - glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y); - - glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer); - - /* reset zoom */ - glPixelZoom(1.0f, 1.0f); - } - - IMB_display_buffer_release(cache_handle); -} - static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, ImBuf *ibuf, int width, int height, float zoomx, float zoomy) { @@ -308,7 +261,8 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, glRectf(x, y, x + zoomx * width, y + zoomy * height); } else { - bool need_fallback = true; + MovieClip *clip = ED_space_clip_get_clip(sc); + int filter = GL_LINEAR; /* checkerboard for case alpha */ if (ibuf->planes == 32) { @@ -318,19 +272,20 @@ static void draw_movieclip_buffer(const bContext *C, SpaceClip *sc, ARegion *ar, fdrawcheckerboard(x, y, x + zoomx * ibuf->x, y + zoomy * ibuf->y); } - /* GLSL display transform for byte buffers is not supported yet */ - if (ibuf->rect_float && IMB_coloemanagement_setup_glsl_draw_from_ctx(C)) { - draw_movieclip_buffer_glsl(sc, ibuf, x, y, zoomx, zoomy); + /* non-scaled proxy shouldn't use filtering */ + if ((clip->flag & MCLIP_USE_PROXY) == 0 || + ELEM(sc->user.render_size, MCLIP_PROXY_RENDER_SIZE_FULL, MCLIP_PROXY_RENDER_SIZE_100)) + { + filter = GL_NEAREST; + } - IMB_coloemanagement_finish_glsl_draw(); + /* set zoom */ + glPixelZoom(zoomx * width / ibuf->x, zoomy * height / ibuf->y); - need_fallback = false; - } + glaDrawImBuf_glsl_ctx(C, ibuf, x, y, filter); - /* if GLSL display failed, fallback to regular glaDrawPixelsAuto method */ - if (need_fallback) { - draw_movieclip_buffer_fallback(C, ibuf, x, y, width, height, zoomx, zoomy); - } + /* reset zoom */ + glPixelZoom(1.0f, 1.0f); if (ibuf->planes == 32) glDisable(GL_BLEND); @@ -1501,8 +1456,6 @@ void clip_draw_main(const bContext *C, SpaceClip *sc, ARegion *ar) if (ibuf) { draw_movieclip_buffer(C, sc, ar, ibuf, width, height, zoomx, zoomy); IMB_freeImBuf(ibuf); - - clip_start_prefetch_job(C); } else { ED_region_grid_draw(ar, zoomx, zoomy); diff --git a/source/blender/editors/space_clip/clip_editor.c b/source/blender/editors/space_clip/clip_editor.c index d297d0485e3..08d0af817a8 100644 --- a/source/blender/editors/space_clip/clip_editor.c +++ b/source/blender/editors/space_clip/clip_editor.c @@ -528,6 +528,7 @@ MovieClip *ED_space_clip_get_clip(SpaceClip *sc) void ED_space_clip_set_clip(bContext *C, bScreen *screen, SpaceClip *sc, MovieClip *clip) { MovieClip *old_clip; + bool old_clip_visible = false; if (!screen && C) screen = CTX_wm_screen(C); @@ -546,9 +547,15 @@ void ED_space_clip_set_clip(bContext *C, bScreen *screen, SpaceClip *sc, MovieCl if (sl->spacetype == SPACE_CLIP) { SpaceClip *cur_sc = (SpaceClip *) sl; - if (cur_sc != sc && cur_sc->view != SC_VIEW_CLIP) { - if (cur_sc->clip == old_clip || cur_sc->clip == NULL) { - cur_sc->clip = clip; + if (cur_sc != sc) { + if (cur_sc->view == SC_VIEW_CLIP) { + if (cur_sc->clip == old_clip) + old_clip_visible = true; + } + else { + if (cur_sc->clip == old_clip || cur_sc->clip == NULL) { + cur_sc->clip = clip; + } } } } @@ -556,6 +563,11 @@ void ED_space_clip_set_clip(bContext *C, bScreen *screen, SpaceClip *sc, MovieCl } } + /* If clip is no longer visible on screen, free memory used by it's cache */ + if (old_clip && old_clip != clip && !old_clip_visible) { + BKE_movieclip_clear_cache(old_clip); + } + if (C) WM_event_add_notifier(C, NC_MOVIECLIP | NA_SELECTED, sc->clip); } @@ -605,26 +617,9 @@ typedef struct PrefetchThread { } PrefetchThread; /* check whether pre-fetching is allowed */ -static bool check_prefetch_allowed(void) +static bool check_prefetch_break(void) { - wmWindowManager *wm; - - /* if there's any job started, better to leave all CPU and - * HDD bandwidth to it - * - * also, display transform could be needed during playback, - * so better to avoid prefetching in this case and reserve - * all the power for display transform - */ - for (wm = G.main->wm.first; wm; wm = wm->id.next) { - if (WM_jobs_has_running_except(wm, WM_JOB_TYPE_CLIP_PREFETCH)) - return false; - - if (ED_screen_animation_playing(wm)) - return false; - } - - return true; + return G.is_break; } /* read file for specified frame number to the memory */ @@ -706,7 +701,7 @@ static unsigned char *prefetch_thread_next_frame(PrefetchQueue *queue, MovieClip unsigned char *mem = NULL; BLI_spin_lock(&queue->spin); - if (!*queue->stop && check_prefetch_allowed() && + if (!*queue->stop && !check_prefetch_break() && IN_RANGE_INCL(queue->current_frame, queue->start_frame, queue->end_frame)) { int current_frame; @@ -848,7 +843,7 @@ static bool prefetch_movie_frame(MovieClip *clip, int frame, short render_size, MovieClipUser user = {0}; ImBuf *ibuf; - if (!check_prefetch_allowed() || *stop) + if (check_prefetch_break() || *stop) return false; user.framenr = frame; @@ -968,26 +963,6 @@ static bool prefetch_check_early_out(const bContext *C) int first_uncached_frame, end_frame; int clip_len; - if (clip->prefetch_ok) - return true; - - if (clip->source == MCLIP_SRC_MOVIE) { - /* for movies we only prefetch undistorted proxy, - * in other cases prefetching could lead to issues - * due to timecodes issues. - */ - - if (clip->flag & MCLIP_USE_PROXY) { - MovieClipUser *user = &sc->user; - - if ((user->render_flag & MCLIP_PROXY_RENDER_UNDISTORT) == 0) - return true; - } - else { - return true; - } - } - clip_len = BKE_movieclip_get_duration(clip); /* check whether all the frames from prefetch range are cached */ @@ -1016,7 +991,6 @@ void clip_start_prefetch_job(const bContext *C) wmJob *wm_job; PrefetchJob *pj; SpaceClip *sc = CTX_wm_space_clip(C); - MovieClip *clip = ED_space_clip_get_clip(sc); if (prefetch_check_early_out(C)) return; @@ -1024,17 +998,6 @@ void clip_start_prefetch_job(const bContext *C) wm_job = WM_jobs_get(CTX_wm_manager(C), CTX_wm_window(C), CTX_wm_area(C), "Prefetching", WM_JOB_PROGRESS, WM_JOB_TYPE_CLIP_PREFETCH); - if (WM_jobs_is_running(wm_job)) { - /* if job is already running, it'll call clip editor redraw when - * it's finished, so cache line is nicely updated - * this will also trigger call of this function, which will ensure - * all needed frames are prefetched - */ - return; - } - - clip->prefetch_ok = true; - /* create new job */ pj = MEM_callocN(sizeof(PrefetchJob), "prefetch job"); pj->clip = ED_space_clip_get_clip(sc); @@ -1045,9 +1008,11 @@ void clip_start_prefetch_job(const bContext *C) pj->render_flag = sc->user.render_flag; WM_jobs_customdata_set(wm_job, pj, prefetch_freejob); - WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP, 0); + WM_jobs_timer(wm_job, 0.2, NC_MOVIECLIP | ND_DISPLAY, 0); WM_jobs_callbacks(wm_job, prefetch_startjob, NULL, NULL, NULL); + G.is_break = FALSE; + /* and finally start the job */ WM_jobs_start(CTX_wm_manager(C), wm_job); } diff --git a/source/blender/editors/space_clip/clip_intern.h b/source/blender/editors/space_clip/clip_intern.h index 99222ec63ac..3d589ff120c 100644 --- a/source/blender/editors/space_clip/clip_intern.h +++ b/source/blender/editors/space_clip/clip_intern.h @@ -108,6 +108,8 @@ void CLIP_OT_mode_set(struct wmOperatorType *ot); void CLIP_OT_view_ndof(struct wmOperatorType *ot); +void CLIP_OT_prefetch(struct wmOperatorType *ot); + /* clip_toolbar.c */ struct ARegion *ED_clip_has_properties_region(struct ScrArea *sa); void CLIP_OT_tools(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_clip/clip_ops.c b/source/blender/editors/space_clip/clip_ops.c index 8e03691e64f..ab00c078226 100644 --- a/source/blender/editors/space_clip/clip_ops.c +++ b/source/blender/editors/space_clip/clip_ops.c @@ -1378,6 +1378,47 @@ void CLIP_OT_view_ndof(wmOperatorType *ot) ot->invoke = clip_view_ndof_invoke; } +/********************** Prefetch operator *********************/ + +static int clip_prefetch_modal(bContext *C, wmOperator *UNUSED(op), const wmEvent *event) +{ + /* no running blender, remove handler and pass through */ + if (0 == WM_jobs_test(CTX_wm_manager(C), CTX_wm_area(C), WM_JOB_TYPE_CLIP_PREFETCH)) + return OPERATOR_FINISHED | OPERATOR_PASS_THROUGH; + + /* running render */ + switch (event->type) { + case ESCKEY: + return OPERATOR_RUNNING_MODAL; + break; + } + + return OPERATOR_PASS_THROUGH; +} + +static int clip_prefetch_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(_event)) +{ + clip_start_prefetch_job(C); + + /* add modal handler for ESC */ + WM_event_add_modal_handler(C, op); + + return OPERATOR_RUNNING_MODAL; +} + +void CLIP_OT_prefetch(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Prefetch Frames"; + ot->idname = "CLIP_OT_prefetch"; + ot->description = "Prefetch frames from disk for faster playback/tracking"; + + /* api callbacks */ + ot->poll = ED_space_clip_view_clip_poll; + ot->invoke = clip_prefetch_invoke; + ot->modal = clip_prefetch_modal; +} + /********************** macroses *********************/ void ED_operatormacros_clip(void) diff --git a/source/blender/editors/space_clip/space_clip.c b/source/blender/editors/space_clip/space_clip.c index 64b643f8a58..96e127cfde6 100644 --- a/source/blender/editors/space_clip/space_clip.c +++ b/source/blender/editors/space_clip/space_clip.c @@ -236,16 +236,6 @@ static void clip_stabilization_tag_refresh(ScrArea *sa) } } -static void clip_prefetch_tag_refresh(ScrArea *sa) -{ - SpaceClip *sc = (SpaceClip *) sa->spacedata.first; - MovieClip *clip = ED_space_clip_get_clip(sc); - - if (clip) { - clip->prefetch_ok = FALSE; - } -} - /* ******************** default callbacks for clip space ***************** */ static SpaceLink *clip_new(const bContext *C) @@ -358,7 +348,6 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) switch (wmn->data) { case ND_FRAME: clip_scopes_tag_refresh(sa); - clip_prefetch_tag_refresh(sa); /* no break! */ case ND_FRAME_RANGE: @@ -367,19 +356,11 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) } break; case NC_MOVIECLIP: - if (wmn->data == 0 && wmn->action == 0) { - /* a nit funky, happens from prefetch job to update - * cache line and job progress - */ - ED_area_tag_redraw(sa); - } - switch (wmn->data) { case ND_DISPLAY: case ND_SELECT: clip_scopes_tag_refresh(sa); ED_area_tag_redraw(sa); - clip_prefetch_tag_refresh(sa); break; } switch (wmn->action) { @@ -423,7 +404,6 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) case NC_SCREEN: switch (wmn->data) { case ND_ANIMPLAY: - clip_prefetch_tag_refresh(sa); ED_area_tag_redraw(sa); break; } @@ -432,7 +412,6 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) if (wmn->data == ND_SPACE_CLIP) { clip_scopes_tag_refresh(sa); clip_stabilization_tag_refresh(sa); - clip_prefetch_tag_refresh(sa); ED_area_tag_redraw(sa); } break; @@ -442,10 +421,6 @@ static void clip_listener(ScrArea *sa, wmNotifier *wmn) ED_area_tag_redraw(sa); } break; - case NC_WM: - if (wmn->data == ND_FILEREAD) - clip_prefetch_tag_refresh(sa); - break; } } @@ -465,6 +440,7 @@ static void clip_operatortypes(void) WM_operatortype_append(CLIP_OT_rebuild_proxy); WM_operatortype_append(CLIP_OT_mode_set); WM_operatortype_append(CLIP_OT_view_ndof); + WM_operatortype_append(CLIP_OT_prefetch); /* ** clip_toolbar.c ** */ WM_operatortype_append(CLIP_OT_tools); @@ -598,6 +574,9 @@ static void clip_keymap(struct wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "CLIP_OT_set_solver_keyframe", EKEY, KM_PRESS, 0, 0); RNA_enum_set(kmi->ptr, "keyframe", 1); + /* io/playback */ + WM_keymap_add_item(keymap, "CLIP_OT_prefetch", PKEY, KM_PRESS, 0, 0); + /* ******** Hotkeys avalaible for main region only ******** */ keymap = WM_keymap_find(keyconf, "Clip Editor", SPACE_CLIP, 0); diff --git a/source/blender/editors/space_file/file_draw.c b/source/blender/editors/space_file/file_draw.c index 1c677d7c006..4a0665d663e 100644 --- a/source/blender/editors/space_file/file_draw.c +++ b/source/blender/editors/space_file/file_draw.c @@ -376,7 +376,7 @@ static void file_draw_preview(uiBlock *block, struct direntry *file, int sx, int /* the image */ glColor4f(1.0, 1.0, 1.0, 1.0); - glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale); + glaDrawPixelsTexScaled((float)xco, (float)yco, imb->x, imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, imb->rect, scale, scale); /* border */ if (dropshadow) { @@ -538,7 +538,7 @@ void file_draw_list(const bContext *C, ARegion *ar) uiButSetRenameFunc(but, renamebutton_cb, file); uiButSetFlag(but, UI_BUT_NO_UTF8); /* allow non utf8 names */ uiButClearFlag(but, UI_BUT_UNDO); - if (0 == uiButActiveOnly(C, ar, block, but)) { + if (false == uiButActiveOnly(C, ar, block, but)) { file->selflag &= ~EDITING_FILE; } } diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c index f27a99ac44b..7fc83809b60 100644 --- a/source/blender/editors/space_image/image_draw.c +++ b/source/blender/editors/space_image/image_draw.c @@ -505,9 +505,6 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, sima_draw_zbuffloat_pixels(scene, x, y, ibuf->x, ibuf->y, ibuf->rect_float); } else { - unsigned char *display_buffer; - void *cache_handle; - if (sima->flag & SI_USE_ALPHA) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -515,12 +512,7 @@ static void draw_image_buffer(const bContext *C, SpaceImage *sima, ARegion *ar, fdrawcheckerboard(x, y, x + ibuf->x * zoomx, y + ibuf->y * zoomy); } - display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle); - - if (display_buffer) - glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer); - - IMB_display_buffer_release(cache_handle); + glaDrawImBuf_glsl_ctx(C, ibuf, x, y, GL_NEAREST); if (sima->flag & SI_USE_ALPHA) glDisable(GL_BLEND); diff --git a/source/blender/editors/space_image/space_image.c b/source/blender/editors/space_image/space_image.c index 761becdbf8e..1b4ff44bb6b 100644 --- a/source/blender/editors/space_image/space_image.c +++ b/source/blender/editors/space_image/space_image.c @@ -435,6 +435,12 @@ static void image_listener(ScrArea *sa, wmNotifier *wmn) /* context changes */ switch (wmn->category) { + case NC_WINDOW: + /* notifier comes from editing color space */ + image_scopes_tag_refresh(sa); + ED_area_tag_refresh(sa); + ED_area_tag_redraw(sa); + break; case NC_SCENE: switch (wmn->data) { case ND_FRAME: @@ -801,11 +807,15 @@ static void image_scope_area_draw(const bContext *C, ARegion *ar) Scene *scene = CTX_data_scene(C); void *lock; ImBuf *ibuf = ED_space_image_acquire_buffer(sima, &lock); + if (ibuf) { if (!sima->scopes.ok) { BKE_histogram_update_sample_line(&sima->sample_line_hist, ibuf, &scene->view_settings, &scene->display_settings); } - scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings); + if (sima->image->flag & IMA_VIEW_AS_RENDER) + scopes_update(&sima->scopes, ibuf, &scene->view_settings, &scene->display_settings); + else + scopes_update(&sima->scopes, ibuf, NULL, &scene->display_settings); } ED_space_image_release_buffer(sima, ibuf, lock); diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c index 5e5b2ece8c9..d7206c9b111 100644 --- a/source/blender/editors/space_node/drawnode.c +++ b/source/blender/editors/space_node/drawnode.c @@ -3011,7 +3011,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glPixelZoom(snode->zoom, snode->zoom); - glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer); + glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer); glPixelZoom(1.0f, 1.0f); glDisable(GL_BLEND); @@ -3019,7 +3019,7 @@ void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode) else { glPixelZoom(snode->zoom, snode->zoom); - glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer); + glaDrawPixelsAuto(x, y, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, display_buffer); glPixelZoom(1.0f, 1.0f); } diff --git a/source/blender/editors/space_node/node_draw.c b/source/blender/editors/space_node/node_draw.c index f1915a82f69..39b12b321dd 100644 --- a/source/blender/editors/space_node/node_draw.c +++ b/source/blender/editors/space_node/node_draw.c @@ -710,7 +710,7 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv) glColor4f(1.0, 1.0, 1.0, 1.0); glPixelZoom(scale, scale); - glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect); + glaDrawPixelsTex(draw_rect.xmin, draw_rect.ymin, preview->xsize, preview->ysize, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, preview->rect); glPixelZoom(1.0f, 1.0f); glDisable(GL_BLEND); diff --git a/source/blender/editors/space_node/node_edit.c b/source/blender/editors/space_node/node_edit.c index cba807a436f..25b2180dbb1 100644 --- a/source/blender/editors/space_node/node_edit.c +++ b/source/blender/editors/space_node/node_edit.c @@ -1978,7 +1978,7 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) bNodeLink *link; int num_nodes; float center[2]; - int is_clipboard_valid; + int is_clipboard_valid, all_nodes_valid; /* validate pointers in the clipboard */ is_clipboard_valid = BKE_node_clipboard_validate(); @@ -2000,6 +2000,17 @@ static int node_clipboard_paste_exec(bContext *C, wmOperator *op) BKE_report(op->reports, RPT_WARNING, "Some nodes references could not be restored, will be left empty"); } + /* make sure all clipboard nodes would be valid in the target tree */ + all_nodes_valid = TRUE; + for (node = clipboard_nodes_lb->first; node; node = node->next) { + if (!node->typeinfo->poll_instance(node, ntree)) { + all_nodes_valid = FALSE; + BKE_reportf(op->reports, RPT_ERROR, "Cannot add node %s into node tree %s", node->name, ntree->id.name + 2); + } + } + if (!all_nodes_valid) + return OPERATOR_CANCELLED; + ED_preview_kill_jobs(C); /* deselect old nodes */ diff --git a/source/blender/editors/space_node/node_intern.h b/source/blender/editors/space_node/node_intern.h index 7e4397a6cb0..b45ca8b228f 100644 --- a/source/blender/editors/space_node/node_intern.h +++ b/source/blender/editors/space_node/node_intern.h @@ -122,6 +122,7 @@ void NODE_OT_select_border(struct wmOperatorType *ot); void NODE_OT_select_lasso(struct wmOperatorType *ot); void NODE_OT_select_same_type(struct wmOperatorType *ot); void NODE_OT_select_same_type_step(struct wmOperatorType *ot); +void NODE_OT_find_node(struct wmOperatorType *ot); /* node_view.c */ int space_node_view_flag(struct bContext *C, SpaceNode *snode, ARegion *ar, const int node_flag); @@ -154,10 +155,6 @@ void NODE_OT_group_insert(struct wmOperatorType *ot); void NODE_OT_group_ungroup(struct wmOperatorType *ot); void NODE_OT_group_separate(struct wmOperatorType *ot); void NODE_OT_group_edit(struct wmOperatorType *ot); -void NODE_OT_group_socket_add(struct wmOperatorType *ot); -void NODE_OT_group_socket_remove(struct wmOperatorType *ot); -void NODE_OT_group_socket_move_up(struct wmOperatorType *ot); -void NODE_OT_group_socket_move_down(struct wmOperatorType *ot); /* node_relationships.c */ @@ -180,9 +177,7 @@ void snode_notify(struct bContext *C, struct SpaceNode *snode); void snode_dag_update(struct bContext *C, struct SpaceNode *snode); void snode_set_context(const struct bContext *C); -bNode *node_tree_get_editgroup(bNodeTree *ntree); void snode_update(struct SpaceNode *snode, struct bNode *node); -bNode *editnode_get_active(bNodeTree *ntree); int composite_node_active(struct bContext *C); int node_has_hidden_sockets(bNode *node); diff --git a/source/blender/editors/space_node/node_ops.c b/source/blender/editors/space_node/node_ops.c index 4d229c6fe18..513bde4375c 100644 --- a/source/blender/editors/space_node/node_ops.c +++ b/source/blender/editors/space_node/node_ops.c @@ -60,6 +60,8 @@ void node_operatortypes(void) WM_operatortype_append(NODE_OT_select_same_type); WM_operatortype_append(NODE_OT_select_same_type_step); + WM_operatortype_append(NODE_OT_find_node); + WM_operatortype_append(NODE_OT_view_all); WM_operatortype_append(NODE_OT_view_selected); @@ -280,7 +282,7 @@ void node_keymap(struct wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, 0, 0); RNA_boolean_set(kmi->ptr, "replace", FALSE); - kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, KM_CTRL, 0); + kmi = WM_keymap_add_item(keymap, "NODE_OT_link_make", FKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "replace", TRUE); WM_keymap_add_menu(keymap, "NODE_MT_add", AKEY, KM_PRESS, KM_SHIFT, 0); @@ -323,6 +325,8 @@ void node_keymap(struct wmKeyConfig *keyconf) kmi = WM_keymap_add_item(keymap, "NODE_OT_select_same_type_step", LEFTBRACKETKEY, KM_PRESS, KM_SHIFT, 0); RNA_boolean_set(kmi->ptr, "prev", TRUE); + WM_keymap_add_item(keymap, "NODE_OT_find_node", FKEY, KM_PRESS, KM_CTRL, 0); + node_group_operators(keymap, "ShaderNodeGroup"); node_group_operators(keymap, "CompositorNodeGroup"); node_group_operators(keymap, "TextureNodeGroup"); diff --git a/source/blender/editors/space_node/node_relationships.c b/source/blender/editors/space_node/node_relationships.c index 8ff964aa932..b552aff27f9 100644 --- a/source/blender/editors/space_node/node_relationships.c +++ b/source/blender/editors/space_node/node_relationships.c @@ -1408,17 +1408,23 @@ void ED_node_link_insert(ScrArea *sa) break; if (link) { - node = link->tonode; - sockto = link->tosock; - - link->tonode = select; - link->tosock = socket_best_match(&select->inputs); - node_remove_extra_links(snode, link->tosock, link); - link->flag &= ~NODE_LINKFLAG_HILITE; - - nodeAddLink(snode->edittree, select, socket_best_match(&select->outputs), node, sockto); - ntreeUpdateTree(snode->edittree); /* needed for pointers */ - snode_update(snode, select); - ED_node_tag_update_id(snode->id); + bNodeSocket *best_input = socket_best_match(&select->inputs); + bNodeSocket *best_output = socket_best_match(&select->outputs); + + if (best_input && best_output) { + node = link->tonode; + sockto = link->tosock; + + link->tonode = select; + link->tosock = best_input; + node_remove_extra_links(snode, link->tosock, link); + link->flag &= ~NODE_LINKFLAG_HILITE; + + nodeAddLink(snode->edittree, select, best_output, node, sockto); + + ntreeUpdateTree(snode->edittree); /* needed for pointers */ + snode_update(snode, select); + ED_node_tag_update_id(snode->id); + } } } diff --git a/source/blender/editors/space_node/node_select.c b/source/blender/editors/space_node/node_select.c index 62537fb713f..366fcce3dd5 100644 --- a/source/blender/editors/space_node/node_select.c +++ b/source/blender/editors/space_node/node_select.c @@ -28,10 +28,13 @@ * \ingroup spnode */ +#include <stdlib.h> + #include "DNA_node_types.h" #include "BLI_rect.h" #include "BLI_lasso.h" +#include "BLI_string.h" #include "BLI_utildefines.h" #include "BKE_context.h" @@ -48,6 +51,8 @@ #include "WM_api.h" #include "WM_types.h" +#include "UI_interface.h" +#include "UI_resources.h" #include "UI_view2d.h" #include "MEM_guardedalloc.h" @@ -853,3 +858,104 @@ void NODE_OT_select_same_type_step(wmOperatorType *ot) } +/* *************** find a node **************** */ + +/* generic search invoke */ +static void node_find_cb(const struct bContext *C, void *UNUSED(arg), const char *str, uiSearchItems *items) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNode *node; + + for (node = snode->edittree->nodes.first; node; node = node->next) { + + if (BLI_strcasestr(node->name, str) || BLI_strcasestr(node->label, str)) { + char name[256]; + + if (node->label[0]) + BLI_snprintf(name, 256, "%s (%s)", node->name, node->label); + else + BLI_strncpy(name, node->name, 256); + if (false == uiSearchItemAdd(items, name, node, 0)) + break; + } + } +} + +static void node_find_call_cb(struct bContext *C, void *UNUSED(arg1), void *arg2) +{ + SpaceNode *snode = CTX_wm_space_node(C); + bNode *active = arg2; + + if (active) { + ARegion *ar = CTX_wm_region(C); + node_select_single(C, active); + + /* is note outside view? */ + if (active->totr.xmax < ar->v2d.cur.xmin || active->totr.xmin > ar->v2d.cur.xmax || + active->totr.ymax < ar->v2d.cur.ymin || active->totr.ymin > ar->v2d.cur.ymax) + { + space_node_view_flag(C, snode, ar, NODE_SELECT); + } + + } +} + +static uiBlock *node_find_menu(bContext *C, ARegion *ar, void *arg_op) +{ + static char search[256] = ""; + wmEvent event; + wmWindow *win = CTX_wm_window(C); + uiBlock *block; + uiBut *but; + wmOperator *op = (wmOperator *)arg_op; + + block = uiBeginBlock(C, ar, "_popup", UI_EMBOSS); + uiBlockSetFlag(block, UI_BLOCK_LOOP | UI_BLOCK_MOVEMOUSE_QUIT | UI_BLOCK_SEARCH_MENU); + + but = uiDefSearchBut(block, search, 0, ICON_VIEWZOOM, sizeof(search), 10, 10, 9 * UI_UNIT_X, UI_UNIT_Y, 0, 0, ""); + uiButSetSearchFunc(but, node_find_cb, op->type, node_find_call_cb, NULL); + + /* fake button, it holds space for search items */ + uiDefBut(block, LABEL, 0, "", 10, 10 - uiSearchBoxHeight(), uiSearchBoxWidth(), uiSearchBoxHeight(), NULL, 0, 0, 0, 0, NULL); + + uiPopupBoundsBlock(block, 6, 0, -UI_UNIT_Y); /* move it downwards, mouse over button */ + uiEndBlock(C, block); + + // uiButActiveOnly(C, ar, block, but); XXX using this here makes Blender hang - investigate + event = *(win->eventstate); /* XXX huh huh? make api call */ + event.type = EVT_BUT_OPEN; + event.val = KM_PRESS; + event.customdata = but; + event.customdatafree = FALSE; + wm_event_add(win, &event); + + return block; +} + + +static int node_find_node_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) +{ + uiPupBlock(C, node_find_menu, op); + return OPERATOR_CANCELLED; +} + + +void NODE_OT_find_node(wmOperatorType *ot) +{ + /* identifiers */ + ot->name = "Find Node"; + ot->description = "Search for named node and allow to select and activate it"; + ot->idname = "NODE_OT_find_node"; + + /* api callbacks */ + ot->invoke = node_find_node_invoke; + ot->poll = ED_operator_node_active; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + RNA_def_boolean(ot->srna, "prev", 0, "Previous", ""); + +} + + diff --git a/source/blender/editors/space_outliner/outliner_draw.c b/source/blender/editors/space_outliner/outliner_draw.c index 418d4ff04a4..d22ea674668 100644 --- a/source/blender/editors/space_outliner/outliner_draw.c +++ b/source/blender/editors/space_outliner/outliner_draw.c @@ -754,7 +754,7 @@ static void operator_search_cb(const struct bContext *UNUSED(C), void *UNUSED(ar /* display name for menu */ WM_operator_py_idname(name, ot->idname); - if (0 == uiSearchItemAdd(items, name, ot, 0)) + if (false == uiSearchItemAdd(items, name, ot, 0)) break; } } @@ -1043,8 +1043,9 @@ static void outliner_buttons(const bContext *C, uiBlock *block, ARegion *ar, Spa uiButSetRenameFunc(bt, namebutton_cb, tselem); /* returns false if button got removed */ - if (0 == uiButActiveOnly(C, ar, block, bt) ) + if (false == uiButActiveOnly(C, ar, block, bt)) { tselem->flag &= ~TSE_TEXTBUT; + } } } diff --git a/source/blender/editors/space_outliner/outliner_edit.c b/source/blender/editors/space_outliner/outliner_edit.c index 1e67e099508..0a1d3a63f2c 100644 --- a/source/blender/editors/space_outliner/outliner_edit.c +++ b/source/blender/editors/space_outliner/outliner_edit.c @@ -113,6 +113,37 @@ static void outliner_open_reveal(SpaceOops *soops, ListBase *lb, TreeElement *te } #endif +static TreeElement *outliner_dropzone_element(const SpaceOops *soops, TreeElement *te, const float fmval[2], const int children) +{ + if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) { + /* name and first icon */ + if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) + return te; + } + /* Not it. Let's look at its children. */ + if (children && (TREESTORE(te)->flag & TSE_CLOSED) == 0 && (te->subtree.first)) { + for (te = te->subtree.first; te; te = te->next) { + TreeElement *te_valid = outliner_dropzone_element(soops, te, fmval, children); + if (te_valid) + return te_valid; + } + } + return NULL; +} + +/* Used for drag and drop parenting */ +TreeElement *outliner_dropzone_find(const SpaceOops *soops, const float fmval[2], const int children) +{ + TreeElement *te; + + for (te = soops->tree.first; te; te = te->next) { + TreeElement *te_valid = outliner_dropzone_element(soops, te, fmval, children); + if (te_valid) + return te_valid; + } + return NULL; +} + /* ************************************************************** */ /* Click Activated */ @@ -1447,36 +1478,6 @@ static int parent_drop_exec(bContext *C, wmOperator *op) return OPERATOR_FINISHED; } -/* Used for drag and drop parenting */ -TreeElement *outliner_dropzone_parent(bContext *C, const wmEvent *event, TreeElement *te, const float fmval[2]) -{ - SpaceOops *soops = CTX_wm_space_outliner(C); - TreeStoreElem *tselem = TREESTORE(te); - - if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) { - /* name and first icon */ - if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) { - /* always makes active object */ - if (te->idcode == ID_OB && tselem->type == 0) { - return te; - } - else { - return NULL; - } - } - } - - /* Not it. Let's look at its children. */ - if ((tselem->flag & TSE_CLOSED) == 0 && (te->subtree.first)) { - for (te = te->subtree.first; te; te = te->next) { - TreeElement *te_valid; - te_valid = outliner_dropzone_parent(C, event, te, fmval); - if (te_valid) return te_valid; - } - } - return NULL; -} - static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Object *par = NULL; @@ -1486,7 +1487,6 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) Main *bmain = CTX_data_main(C); Scene *scene = NULL; TreeElement *te = NULL; - TreeElement *te_found = NULL; char childname[MAX_ID_NAME]; char parname[MAX_ID_NAME]; int partype = 0; @@ -1495,13 +1495,10 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); /* Find object hovered over */ - for (te = soops->tree.first; te; te = te->next) { - te_found = outliner_dropzone_parent(C, event, te, fmval); - if (te_found) break; - } + te = outliner_dropzone_find(soops, fmval, 1); - if (te_found) { - RNA_string_set(op->ptr, "parent", te_found->name); + if (te) { + RNA_string_set(op->ptr, "parent", te->name); /* Identify parent and child */ RNA_string_get(op->ptr, "child", childname); ob = (Object *)BKE_libblock_find_name(ID_OB, childname); @@ -1516,7 +1513,7 @@ static int parent_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) return OPERATOR_CANCELLED; } - scene = (Scene *)outliner_search_back(soops, te_found, ID_SCE); + scene = (Scene *)outliner_search_back(soops, te, ID_SCE); if (scene == NULL) { /* currently outlier organized in a way, that if there's no parent scene @@ -1651,44 +1648,6 @@ void OUTLINER_OT_parent_drop(wmOperatorType *ot) RNA_def_enum(ot->srna, "type", prop_make_parent_types, 0, "Type", ""); } -int outliner_dropzone_parent_clear(bContext *C, const wmEvent *event, TreeElement *te, const float fmval[2]) -{ - SpaceOops *soops = CTX_wm_space_outliner(C); - TreeStoreElem *tselem = TREESTORE(te); - - /* Check for row */ - if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) { - /* Ignore drop on scene tree elements */ - if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) { - if ((te->idcode == ID_SCE) && - !ELEM3(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS)) - { - return 0; - } - // Other codes to ignore? - } - - /* Left or right of: (+), first icon, and name */ - if ((fmval[0] < (te->xs + UI_UNIT_X)) || (fmval[0] > te->xend)) { - return 1; - } - else if (te->idcode != ID_OB || ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE)) { - return 1; - } - - return 0; // ID_OB, but mouse in undefined dropzone. - } - - /* Not this row. Let's look at its children. */ - if ((tselem->flag & TSE_CLOSED) == 0 && (te->subtree.first)) { - for (te = te->subtree.first; te; te = te->next) { - if (outliner_dropzone_parent_clear(C, event, te, fmval)) - return 1; - } - } - return 0; -} - static int parent_clear_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event)) { Main *bmain = CTX_data_main(C); @@ -1738,22 +1697,6 @@ void OUTLINER_OT_parent_clear(wmOperatorType *ot) RNA_def_enum(ot->srna, "type", prop_clear_parent_types, 0, "Type", ""); } -TreeElement *outliner_dropzone_scene(bContext *C, const wmEvent *UNUSED(event), TreeElement *te, const float fmval[2]) -{ - SpaceOops *soops = CTX_wm_space_outliner(C); - TreeStoreElem *tselem = TREESTORE(te); - - if ((fmval[1] > te->ys) && (fmval[1] < (te->ys + UI_UNIT_Y))) { - /* name and first icon */ - if ((fmval[0] > te->xs + UI_UNIT_X) && (fmval[0] < te->xend)) { - if (te->idcode == ID_SCE && tselem->type == 0) { - return te; - } - } - } - return NULL; -} - static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) { Scene *scene = NULL; @@ -1762,24 +1705,19 @@ static int scene_drop_invoke(bContext *C, wmOperator *op, const wmEvent *event) ARegion *ar = CTX_wm_region(C); Main *bmain = CTX_data_main(C); TreeElement *te = NULL; - TreeElement *te_found = NULL; char obname[MAX_ID_NAME]; float fmval[2]; UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); /* Find object hovered over */ - for (te = soops->tree.first; te; te = te->next) { - te_found = outliner_dropzone_scene(C, event, te, fmval); - if (te_found) - break; - } + te = outliner_dropzone_find(soops, fmval, 0); - if (te_found) { + if (te) { Base *base; - RNA_string_set(op->ptr, "scene", te_found->name); - scene = (Scene *)BKE_libblock_find_name(ID_SCE, te_found->name); + RNA_string_set(op->ptr, "scene", te->name); + scene = (Scene *)BKE_libblock_find_name(ID_SCE, te->name); RNA_string_get(op->ptr, "object", obname); ob = (Object *)BKE_libblock_find_name(ID_OB, obname); @@ -1837,22 +1775,17 @@ static int material_drop_invoke(bContext *C, wmOperator *op, const wmEvent *even SpaceOops *soops = CTX_wm_space_outliner(C); ARegion *ar = CTX_wm_region(C); TreeElement *te = NULL; - TreeElement *te_found = NULL; char mat_name[MAX_ID_NAME - 2]; float fmval[2]; UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); /* Find object hovered over */ - for (te = soops->tree.first; te; te = te->next) { - te_found = outliner_dropzone_parent(C, event, te, fmval); - if (te_found) - break; - } + te = outliner_dropzone_find(soops, fmval, 1); - if (te_found) { - RNA_string_set(op->ptr, "object", te_found->name); - ob = (Object *)BKE_libblock_find_name(ID_OB, te_found->name); + if (te) { + RNA_string_set(op->ptr, "object", te->name); + ob = (Object *)BKE_libblock_find_name(ID_OB, te->name); RNA_string_get(op->ptr, "material", mat_name); ma = (Material *)BKE_libblock_find_name(ID_MA, mat_name); diff --git a/source/blender/editors/space_outliner/outliner_intern.h b/source/blender/editors/space_outliner/outliner_intern.h index a918357ced2..3ab412f0ddc 100644 --- a/source/blender/editors/space_outliner/outliner_intern.h +++ b/source/blender/editors/space_outliner/outliner_intern.h @@ -190,9 +190,7 @@ void group_toggle_renderability_cb(struct bContext *C, struct Scene *scene, Tree void item_rename_cb(struct bContext *C, struct Scene *scene, TreeElement *te, struct TreeStoreElem *tsep, struct TreeStoreElem *tselem); -TreeElement *outliner_dropzone_parent(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]); -int outliner_dropzone_parent_clear(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]); -TreeElement *outliner_dropzone_scene(struct bContext *C, const struct wmEvent *event, struct TreeElement *te, const float fmval[2]); +TreeElement *outliner_dropzone_find(const struct SpaceOops *soops, const float fmval[2], const int children); /* ...................................................... */ void OUTLINER_OT_item_activate(struct wmOperatorType *ot); diff --git a/source/blender/editors/space_outliner/space_outliner.c b/source/blender/editors/space_outliner/space_outliner.c index 3849aaf78c1..76a3da23d57 100644 --- a/source/blender/editors/space_outliner/space_outliner.c +++ b/source/blender/editors/space_outliner/space_outliner.c @@ -94,7 +94,6 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e { ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); - TreeElement *te = NULL; float fmval[2]; UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); @@ -102,25 +101,25 @@ static int outliner_parent_drop_poll(bContext *C, wmDrag *drag, const wmEvent *e ID *id = (ID *)drag->poin; if (GS(id->name) == ID_OB) { /* Ensure item under cursor is valid drop target */ - /* Find object hovered over */ - for (te = soops->tree.first; te; te = te->next) { - TreeElement *te_valid; - te_valid = outliner_dropzone_parent(C, event, te, fmval); - if (te_valid) { - /* check that parent/child are both in the same scene */ - Scene *scene = (Scene *)outliner_search_back(soops, te_valid, ID_SCE); - - if (!scene) { - /* currently outlier organized in a way, that if there's no parent scene - * element for object it means that all displayed objects belong to - * active scene and parenting them is allowed (sergey) - */ - return 1; - } + TreeElement *te = outliner_dropzone_find(soops, fmval, 1); - if (scene && BKE_scene_base_find(scene, (Object *)id)) { - return 1; - } + if (te && te->idcode == ID_OB && TREESTORE(te)->type == 0) { + Scene *scene; + ID *te_id = TREESTORE(te)->id; + + /* check if dropping self or parent */ + if (te_id == id || (Object *)te_id == ((Object *)id)->parent) + return 0; + + /* check that parent/child are both in the same scene */ + scene = (Scene *)outliner_search_back(soops, te, ID_SCE); + + /* currently outliner organized in a way that if there's no parent scene + * element for object it means that all displayed objects belong to + * active scene and parenting them is allowed (sergey) + */ + if (!scene || BKE_scene_base_find(scene, (Object *)id)) { + return 1; } } } @@ -147,19 +146,20 @@ static int outliner_parent_clear_poll(bContext *C, wmDrag *drag, const wmEvent * if (drag->type == WM_DRAG_ID) { ID *id = (ID *)drag->poin; if (GS(id->name) == ID_OB) { - if (((Object *)id)->parent == NULL) { - return 0; - } - /* Ensure location under cursor is valid dropzone */ - for (te = soops->tree.first; te; te = te->next) { - if (outliner_dropzone_parent_clear(C, event, te, fmval)) return 1; - } - /* Check if mouse cursor is below the tree */ - te = soops->tree.last; - while (((te->flag & TE_LAZY_CLOSED) == 0) && (te->subtree.last)) { - te = te->subtree.last; + if (((Object *)id)->parent) { + if ((te = outliner_dropzone_find(soops, fmval, 1))) { + TreeStoreElem *tselem = TREESTORE(te); + + switch (te->idcode) { + case ID_SCE: + return (ELEM3(tselem->type, TSE_R_LAYER_BASE, TSE_R_LAYER, TSE_R_PASS)); + case ID_OB: + return (ELEM(tselem->type, TSE_MODIFIER_BASE, TSE_CONSTRAINT_BASE)); + /* Other codes to ignore? */ + } + } + return (te == NULL); } - if (fmval[1] < te->ys) return 1; } } return 0; @@ -180,7 +180,6 @@ static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *ev { ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); - TreeElement *te = NULL; float fmval[2]; UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); @@ -188,11 +187,8 @@ static int outliner_scene_drop_poll(bContext *C, wmDrag *drag, const wmEvent *ev ID *id = (ID *)drag->poin; if (GS(id->name) == ID_OB) { /* Ensure item under cursor is valid drop target */ - /* Find object hovered over */ - for (te = soops->tree.first; te; te = te->next) { - if (outliner_dropzone_scene(C, event, te, fmval)) - return 1; - } + TreeElement *te = outliner_dropzone_find(soops, fmval, 0); + return (te && te->idcode == ID_SCE && TREESTORE(te)->type == 0); } } return 0; @@ -209,7 +205,6 @@ static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent { ARegion *ar = CTX_wm_region(C); SpaceOops *soops = CTX_wm_space_outliner(C); - TreeElement *te = NULL; float fmval[2]; UI_view2d_region_to_view(&ar->v2d, event->mval[0], event->mval[1], &fmval[0], &fmval[1]); @@ -217,11 +212,8 @@ static int outliner_material_drop_poll(bContext *C, wmDrag *drag, const wmEvent ID *id = (ID *)drag->poin; if (GS(id->name) == ID_MA) { /* Ensure item under cursor is valid drop target */ - /* Find object hovered over */ - for (te = soops->tree.first; te; te = te->next) { - if (outliner_dropzone_parent(C, event, te, fmval)) - return 1; - } + TreeElement *te = outliner_dropzone_find(soops, fmval, 1); + return (te && te->idcode == ID_OB && TREESTORE(te)->type == 0); } } return 0; diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c index 3c2c715efc2..141af5d5ba4 100644 --- a/source/blender/editors/space_sequencer/sequencer_draw.c +++ b/source/blender/editors/space_sequencer/sequencer_draw.c @@ -896,11 +896,9 @@ static ImBuf *sequencer_make_scope(Scene *scene, ImBuf *ibuf, ImBuf *(*make_scop { ImBuf *display_ibuf = IMB_dupImBuf(ibuf); ImBuf *scope; - - if (display_ibuf->rect_float) { - IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, + + IMB_colormanagement_imbuf_make_display_space(display_ibuf, &scene->view_settings, &scene->display_settings); - } scope = make_scope_cb(display_ibuf); diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h index 32a6c49da89..a0212bd17fa 100644 --- a/source/blender/editors/space_sequencer/sequencer_intern.h +++ b/source/blender/editors/space_sequencer/sequencer_intern.h @@ -54,7 +54,8 @@ struct ARegion *sequencer_has_buttons_region(struct ScrArea *sa); void draw_timeline_seq(const struct bContext *C, struct ARegion *ar); void draw_image_seq(const struct bContext *C, struct Scene *scene, struct ARegion *ar, struct SpaceSeq *sseq, int cfra, int offset, int draw_overlay); -void seq_reset_imageofs(struct SpaceSeq *sseq); +/* UNUSED */ +// void seq_reset_imageofs(struct SpaceSeq *sseq); struct ImBuf *sequencer_ibuf_get(struct Main *bmain, struct Scene *scene, struct SpaceSeq *sseq, int cfra, int frame_ofs); @@ -69,7 +70,8 @@ int seq_effect_find_selected(struct Scene *scene, struct Sequence *activeseq, in /* operator helpers */ int sequencer_edit_poll(struct bContext *C); -int sequencer_strip_poll(struct bContext *C); +/* UNUSED */ +//int sequencer_strip_poll(struct bContext *C); int sequencer_strip_has_path_poll(struct bContext *C); int sequencer_view_poll(struct bContext *C); diff --git a/source/blender/editors/space_sequencer/sequencer_scopes.c b/source/blender/editors/space_sequencer/sequencer_scopes.c index c8b70c0ce4a..79b50f2d3ae 100644 --- a/source/blender/editors/space_sequencer/sequencer_scopes.c +++ b/source/blender/editors/space_sequencer/sequencer_scopes.c @@ -531,7 +531,7 @@ BLI_INLINE int get_bin_float(float f) static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf) { ImBuf *rval = IMB_allocImBuf(515, 128, 32, IB_rect); - int n, c, x, y; + int nr, ng, nb, x, y; float *src = ibuf->rect_float; unsigned int bins[3][HIS_STEPS]; @@ -563,23 +563,30 @@ static ImBuf *make_histogram_view_from_ibuf_float(ImBuf *ibuf) } } - draw_histogram_marker(rval, get_bin_float(0.0)); - draw_histogram_marker(rval, get_bin_float(1.0)); - - n = 0; - for (c = 0; c < 3; c++) { - for (x = 0; x < HIS_STEPS; x++) { - if (bins[c][x] > n) { - n = bins[c][x]; - } - } + nr = nb = ng = 0; + for (x = 0; x < HIS_STEPS; x++) { + if (bins[0][x] > nr) + nr = bins[0][x]; + if (bins[1][x] > ng) + ng = bins[1][x]; + if (bins[2][x] > nb) + nb = bins[2][x]; } - for (c = 0; c < 3; c++) { - for (x = 0; x < HIS_STEPS; x++) { - draw_histogram_bar(rval, x + 1, (float) bins[c][x] / n, c); + + for (x = 0; x < HIS_STEPS; x++) { + if (nr) { + draw_histogram_bar(rval, x + 1, ((float) bins[0][x]) / nr, 0); + } + if (ng) { + draw_histogram_bar(rval, x + 1, ((float) bins[1][x]) / ng, 1); + } + if (nb) { + draw_histogram_bar(rval, x + 1, ((float) bins[2][x]) / nb, 2); } } - + + draw_histogram_marker(rval, get_bin_float(0.0)); + draw_histogram_marker(rval, get_bin_float(1.0)); wform_put_border((unsigned char *) rval->rect, rval->x, rval->y); return rval; diff --git a/source/blender/editors/space_sequencer/space_sequencer.c b/source/blender/editors/space_sequencer/space_sequencer.c index ffe89407715..c933bbff0b3 100644 --- a/source/blender/editors/space_sequencer/space_sequencer.c +++ b/source/blender/editors/space_sequencer/space_sequencer.c @@ -330,6 +330,7 @@ static void sequencer_listener(ScrArea *sa, wmNotifier *wmn) break; } break; + case NC_WINDOW: case NC_SPACE: if (wmn->data == ND_SPACE_SEQUENCER) sequencer_scopes_tag_refresh(sa); diff --git a/source/blender/editors/space_view3d/drawarmature.c b/source/blender/editors/space_view3d/drawarmature.c index cb685b59b64..2ff52b51069 100644 --- a/source/blender/editors/space_view3d/drawarmature.c +++ b/source/blender/editors/space_view3d/drawarmature.c @@ -1573,8 +1573,8 @@ static void draw_pose_dofs(Object *ob) for (i = 0; i < 3; i++) { /* *0.5f here comes from M_PI/360.0f when rotations were still in degrees */ - amin[i] = (float)sin(pchan->limitmin[i] * 0.5f); - amax[i] = (float)sin(pchan->limitmax[i] * 0.5f); + amin[i] = sinf(pchan->limitmin[i] * 0.5f); + amax[i] = sinf(pchan->limitmax[i] * 0.5f); } glScalef(1.0f, -1.0f, 1.0f); @@ -1605,8 +1605,8 @@ static void draw_pose_dofs(Object *ob) phi = fac * (pchan->limitmax[2] - pchan->limitmin[2]); i = (a == -16) ? 0 : 1; - corner[i][0] = (float)sin(phi); - corner[i][1] = (float)cos(phi); + corner[i][0] = sinf(phi); + corner[i][1] = cosf(phi); corner[i][2] = 0.0f; glVertex3fv(corner[i]); } @@ -1629,8 +1629,8 @@ static void draw_pose_dofs(Object *ob) i = (a == -16) ? 2 : 3; corner[i][0] = 0.0f; - corner[i][1] = (float)sin(phi); - corner[i][2] = (float)cos(phi); + corner[i][1] = sinf(phi); + corner[i][2] = cosf(phi); glVertex3fv(corner[i]); } glEnd(); diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c index 265fef0f59b..cd68fbf126e 100644 --- a/source/blender/editors/space_view3d/drawobject.c +++ b/source/blender/editors/space_view3d/drawobject.c @@ -622,7 +622,7 @@ static void draw_empty_image(Object *ob, const short dflag, const unsigned char glColor4fv(ob->col); /* Draw the Image on the screen */ - glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect); + glaDrawPixelsTex(ofs_x, ofs_y, ima_x, ima_y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect); glPixelTransferf(GL_ALPHA_SCALE, 1.0f); glDisable(GL_BLEND); @@ -6452,6 +6452,14 @@ void draw_object(Scene *scene, ARegion *ar, View3D *v3d, Base *base, const short ED_view3d_after_add(&v3d->afterdraw_xray, base, dflag); return; } + + /* allow transp option for empty images */ + if (ob->type == OB_EMPTY && ob->empty_drawtype == OB_EMPTY_IMAGE) { + if (!v3d->xray && !v3d->transp && !(ob->dtx & OB_DRAWXRAY) && (ob->dtx & OB_DRAWTRANSP)) { + ED_view3d_after_add(&v3d->afterdraw_transp, base, dflag); + return; + } + } } } diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index b6d46f82e6a..d0437c77af7 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1831,7 +1831,7 @@ static void view3d_draw_bgpic(Scene *scene, ARegion *ar, View3D *v3d, * glaDrawPixelsSafe in some cases, which will end up in misssing * alpha transparency for the background image (sergey) */ - glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect); + glaDrawPixelsTex(x1, y1, ibuf->x, ibuf->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_LINEAR, ibuf->rect); glPixelZoom(1.0, 1.0); glPixelTransferf(GL_ALPHA_SCALE, 1.0f); diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c index 9dbdd8a9789..3767f3011ff 100644 --- a/source/blender/editors/space_view3d/view3d_edit.c +++ b/source/blender/editors/space_view3d/view3d_edit.c @@ -365,7 +365,8 @@ typedef struct ViewOpsData { float viewquat[4]; /* working copy of rv3d->viewquat */ float trackvec[3]; float mousevec[3]; /* dolly only */ - float reverse, dist0, camzoom0; + float reverse; + float dist_prev, camzoom_prev; float grid, far; bool axis_snap; /* view rotate only */ float zfac; @@ -425,8 +426,8 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even * we may want to make this optional but for now its needed always */ ED_view3d_camera_lock_init(vod->v3d, vod->rv3d); - vod->dist0 = rv3d->dist; - vod->camzoom0 = rv3d->camzoom; + vod->dist_prev = rv3d->dist; + vod->camzoom_prev = rv3d->camzoom; copy_qt_qt(vod->viewquat, rv3d->viewquat); copy_qt_qt(vod->oldquat, rv3d->viewquat); vod->origx = vod->oldx = event->x; @@ -439,7 +440,7 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even Scene *scene = CTX_data_scene(C); Object *ob = OBACT; - if (ob && ob->mode & OB_MODE_ALL_PAINT) { + if (ob && (ob->mode & OB_MODE_ALL_PAINT) && (BKE_object_pose_armature_get(ob) == NULL)) { /* transformation is disabled for painting modes, which will make it * so previous offset is used. This is annoying when you open file * saved with active object in painting mode @@ -484,7 +485,7 @@ static void viewops_data_create(bContext *C, wmOperator *op, const wmEvent *even /* find a new ofs value that is along the view axis (rather than the mouse location) */ closest_to_line_v3(dvec, vod->dyn_ofs, my_pivot, my_origin); - vod->dist0 = rv3d->dist = len_v3v3(my_pivot, dvec); + vod->dist_prev = rv3d->dist = len_v3v3(my_pivot, dvec); negate_v3_v3(rv3d->ofs, dvec); } @@ -1711,7 +1712,7 @@ static void viewzoom_apply(ViewOpsData *vod, const int x, const int y, const sho if (use_cam_zoom) { float delta; delta = (x - vod->origx + y - vod->origy) / 10.0f; - vod->rv3d->camzoom = vod->camzoom0 + (zoom_invert ? -delta : delta); + vod->rv3d->camzoom = vod->camzoom_prev + (zoom_invert ? -delta : delta); CLAMP(vod->rv3d->camzoom, RV3D_CAMZOOM_MIN, RV3D_CAMZOOM_MAX); } @@ -1746,7 +1747,7 @@ static void viewzoom_apply(ViewOpsData *vod, const int x, const int y, const sho len1 = (int)sqrt((ctr[0] - x) * (ctr[0] - x) + (ctr[1] - y) * (ctr[1] - y)) + 5; len2 = (int)sqrt((ctr[0] - vod->origx) * (ctr[0] - vod->origx) + (ctr[1] - vod->origy) * (ctr[1] - vod->origy)) + 5; - zfac = vod->dist0 * ((float)len2 / len1) / vod->rv3d->dist; + zfac = vod->dist_prev * ((float)len2 / len1) / vod->rv3d->dist; } else { /* USER_ZOOM_DOLLY */ float len1, len2; @@ -1766,11 +1767,11 @@ static void viewzoom_apply(ViewOpsData *vod, const int x, const int y, const sho if (use_cam_zoom) { /* zfac is ignored in this case, see below */ #if 0 - zfac = vod->camzoom0 * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->camzoom; + zfac = vod->camzoom_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->camzoom; #endif } else { - zfac = vod->dist0 * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->dist; + zfac = vod->dist_prev * (2.0f * ((len1 / len2) - 1.0f) + 1.0f) / vod->rv3d->dist; } } diff --git a/source/blender/editors/space_view3d/view3d_ruler.c b/source/blender/editors/space_view3d/view3d_ruler.c index ef8c2b5eff6..ad3f941bd17 100644 --- a/source/blender/editors/space_view3d/view3d_ruler.c +++ b/source/blender/editors/space_view3d/view3d_ruler.c @@ -59,43 +59,53 @@ /* Snapping (could be own function) */ /* NOTE - this is not very nice use of transform snapping */ #include "ED_transform.h" -#include "../transform/transform.h" -static bool ED_view3d_snap_co(bContext *C, float r_co[3], const float co_ss[2], +static bool ED_view3d_snap_co(bContext *C, float r_co[3], const float co_ss[2], float r_no[3], bool use_vert, bool use_edge, bool use_face) { - TransInfo t = {0}; - int dist = 12; /* snap dist */ + float dist_px = 12; /* snap dist */ float r_no_dummy[3]; bool ret = false; - char backup_snap_mode; - Base *backup_baseact; + float *r_no_ptr = r_no ? r_no : r_no_dummy; - t.scene = CTX_data_scene(C); - t.view = CTX_wm_view3d(C); - t.ar = CTX_wm_region(C); - t.obedit = CTX_data_edit_object(C); - - backup_snap_mode = t.scene->toolsettings->snap_mode; - backup_baseact = t.scene->basact; - t.scene->basact = NULL; + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + struct Object *obedit = CTX_data_edit_object(C); /* try snap edge, then face if it fails */ if (use_vert) { - t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_VERTEX; - ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL); + ret = snapObjectsEx(scene, NULL, v3d, ar, obedit, SCE_SNAP_MODE_VERTEX, + co_ss, &dist_px, r_co, r_no_ptr, SNAP_ALL); } if (use_edge && (ret == false)) { - t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_EDGE; - ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL); + ret = snapObjectsEx(scene, NULL, v3d, ar, obedit, SCE_SNAP_MODE_EDGE, + co_ss, &dist_px, r_co, r_no_ptr, SNAP_ALL); } if (use_face && (ret == false)) { - t.scene->toolsettings->snap_mode = SCE_SNAP_MODE_FACE; - ret = snapObjectsTransform(&t, co_ss, &dist, r_co, r_no_dummy, SNAP_ALL); + ret = snapObjectsEx(scene, NULL, v3d, ar, obedit, SCE_SNAP_MODE_FACE, + co_ss, &dist_px, r_co, r_no_ptr, SNAP_ALL); } - t.scene->toolsettings->snap_mode = backup_snap_mode; - t.scene->basact = backup_baseact; + return ret; +} + +static bool ED_view3d_snap_ray(bContext *C, float r_co[3], + const float ray_start[3], const float ray_normal[3]) +{ + float dist_px = 12; /* snap dist */ + float r_no_dummy[3]; + bool ret = false; + + Scene *scene = CTX_data_scene(C); + View3D *v3d = CTX_wm_view3d(C); + ARegion *ar = CTX_wm_region(C); + struct Object *obedit = CTX_data_edit_object(C); + + /* try snap edge, then face if it fails */ + ret = snapObjectsRayEx(scene, NULL, v3d, ar, obedit, SCE_SNAP_MODE_FACE, + ray_start, ray_normal, + NULL, &dist_px, r_co, r_no_dummy, SNAP_ALL); return ret; } @@ -657,16 +667,36 @@ static void view3d_ruler_item_project(RulerInfo *ruler_info, float r_co[3], } /* use for mousemove events */ -static bool view3d_ruler_item_mousemove(bContext *C, RulerInfo *ruler_info, const int mval[2], const bool do_snap) +static bool view3d_ruler_item_mousemove(bContext *C, RulerInfo *ruler_info, const int mval[2], + const bool do_thickness, const bool do_snap) { RulerItem *ruler_item = ruler_item_active_get(ruler_info); if (ruler_item) { float *co = ruler_item->co[ruler_item->co_index]; view3d_ruler_item_project(ruler_info, co, mval); - if (do_snap) { + if (do_thickness && ruler_item->co_index != 1) { + const float mval_fl[2] = {UNPACK2(mval)}; + float ray_normal[3]; + float ray_start[3]; + float *co_other; + + co_other = ruler_item->co[ruler_item->co_index == 0 ? 2 : 0]; + + if (ED_view3d_snap_co(C, co, mval_fl, ray_normal, + false, false, true)) + { + negate_v3(ray_normal); + /* add some bias */ + madd_v3_v3v3fl(ray_start, co, ray_normal, 0.0001f); + ED_view3d_snap_ray(C, co_other, + ray_start, ray_normal); + } + } + else if (do_snap) { const float mval_fl[2] = {UNPACK2(mval)}; - ED_view3d_snap_co(C, co, mval_fl, true, true, true); + ED_view3d_snap_co(C, co, mval_fl, NULL, + true, true, true); } return true; } @@ -680,6 +710,7 @@ static void view3d_ruler_header_update(ScrArea *sa) const char *text = "Ctrl+LMB: Add, " "Del: Remove, " "Ctrl+Drag: Snap, " + "Shift+Drag: Thickness, " "Ctrl+C: Copy Value, " "Enter: Store, " "Esc: Cancel"; @@ -774,7 +805,7 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) /* snap the first point added, not essential but handy */ { ruler_item->co_index = 0; - view3d_ruler_item_mousemove(C, ruler_info, event->mval, true); + view3d_ruler_item_mousemove(C, ruler_info, event->mval, event->shift != 0, true); } copy_v3_v3(ruler_item->co[2], ruler_item->co[0]); @@ -814,7 +845,8 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) } /* update the new location */ - view3d_ruler_item_mousemove(C, ruler_info, event->mval, event->ctrl != 0); + view3d_ruler_item_mousemove(C, ruler_info, event->mval, + event->shift != 0, event->ctrl != 0); do_draw = true; } } @@ -857,7 +889,9 @@ static int view3d_ruler_modal(bContext *C, wmOperator *op, const wmEvent *event) case MOUSEMOVE: { if (ruler_info->state == RULER_STATE_DRAG) { - if (view3d_ruler_item_mousemove(C, ruler_info, event->mval, event->ctrl != 0)) { + if (view3d_ruler_item_mousemove(C, ruler_info, event->mval, + event->shift != 0, event->ctrl != 0)) + { do_draw = true; } } diff --git a/source/blender/editors/space_view3d/view3d_toolbar.c b/source/blender/editors/space_view3d/view3d_toolbar.c index 603d9a1595c..d30c1699d65 100644 --- a/source/blender/editors/space_view3d/view3d_toolbar.c +++ b/source/blender/editors/space_view3d/view3d_toolbar.c @@ -162,7 +162,7 @@ static void operator_search_cb(const struct bContext *C, void *UNUSED(arg), cons if (BLI_strcasestr(ot->name, str)) { if (WM_operator_poll((bContext *)C, ot)) { - if (0 == uiSearchItemAdd(items, ot->name, ot, 0)) + if (false == uiSearchItemAdd(items, ot->name, ot, 0)) break; } } diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c index 64e49abd761..be296025624 100644 --- a/source/blender/editors/transform/transform.c +++ b/source/blender/editors/transform/transform.c @@ -112,6 +112,7 @@ static bool transdata_check_local_center(TransInfo *t) return ((t->around == V3D_LOCAL) && ( (t->flag & (T_OBJECT | T_POSE)) || (t->obedit && t->obedit->type == OB_MESH && (t->settings->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_FACE))) || + (t->obedit && t->obedit->type == OB_MBALL) || (t->obedit && t->obedit->type == OB_ARMATURE) || (t->spacetype == SPACE_IPO)) ); @@ -2757,8 +2758,8 @@ int Warp(TransInfo *t, const int UNUSED(mval[2])) vec[1] = (vec[1] - cursor[1]); - co = (float)cos(phi0); - si = (float)sin(phi0); + co = cosf(phi0); + si = sinf(phi0); loc[0] = -si * vec[1] + cursor[0]; loc[1] = co * vec[1] + cursor[1]; loc[2] = vec[2]; diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h index a551ef5008e..1f08bfda6a6 100644 --- a/source/blender/editors/transform/transform.h +++ b/source/blender/editors/transform/transform.h @@ -72,7 +72,7 @@ typedef struct TransSnap { short target; short modePoint; short modeSelect; - short align; + bool align; char project; char snap_self; short peel; @@ -593,7 +593,7 @@ void flushTransGraphData(TransInfo *t); void remake_graph_transdata(TransInfo *t, struct ListBase *anim_data); void flushTransUVs(TransInfo *t); void flushTransParticles(TransInfo *t); -int clipUVTransform(TransInfo *t, float *vec, int resize); +bool clipUVTransform(TransInfo *t, float vec[2], const bool resize); void clipUVData(TransInfo *t); void flushTransNodes(TransInfo *t); void flushTransSeq(TransInfo *t); @@ -628,8 +628,8 @@ void setUserConstraint(TransInfo *t, short orientation, int mode, const char tex void constraintNumInput(TransInfo *t, float vec[3]); -int isLockConstraint(TransInfo *t); -int getConstraintSpaceDimension(TransInfo *t); +bool isLockConstraint(TransInfo *t); +int getConstraintSpaceDimension(TransInfo *t); char constraintModeToChar(TransInfo *t); void startConstraint(TransInfo *t); @@ -652,21 +652,21 @@ typedef enum { void snapGrid(TransInfo *t, float *val); void snapGridAction(TransInfo *t, float *val, GearsType action); -int activeSnap(TransInfo *t); -int validSnap(TransInfo *t); +bool activeSnap(TransInfo *t); +bool validSnap(TransInfo *t); void initSnapping(struct TransInfo *t, struct wmOperator *op); void applyProject(TransInfo *t); void applySnapping(TransInfo *t, float *vec); void resetSnapping(TransInfo *t); -int handleSnapping(TransInfo *t, const struct wmEvent *event); +bool handleSnapping(TransInfo *t, const struct wmEvent *event); void drawSnapping(const struct bContext *C, TransInfo *t); -int usingSnappingNormal(TransInfo *t); -int validSnappingNormal(TransInfo *t); +bool usingSnappingNormal(TransInfo *t); +bool validSnappingNormal(TransInfo *t); void getSnapPoint(TransInfo *t, float vec[3]); void addSnapPoint(TransInfo *t); -int updateSelectedSnapPoint(TransInfo *t); +bool updateSelectedSnapPoint(TransInfo *t); void removeSnapPoint(TransInfo *t); /********************** Mouse Input ******************************/ @@ -729,8 +729,8 @@ struct TransformOrientation *createMeshSpace(struct bContext *C, struct ReportLi struct TransformOrientation *createBoneSpace(struct bContext *C, struct ReportList *reports, char *name, int overwrite); /* Those two fill in mat and return non-zero on success */ -int createSpaceNormal(float mat[3][3], float normal[3]); -int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]); +bool createSpaceNormal(float mat[3][3], const float normal[3]); +bool createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]); struct TransformOrientation *addMatrixSpace(struct bContext *C, float mat[3][3], char name[], int overwrite); void applyTransformOrientation(const struct bContext *C, float mat[3][3], char *name); diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c index f3026205ea2..7678051fd38 100644 --- a/source/blender/editors/transform/transform_constraints.c +++ b/source/blender/editors/transform/transform_constraints.c @@ -557,13 +557,17 @@ void setConstraint(TransInfo *t, float space[3][3], int mode, const char text[]) void setLocalConstraint(TransInfo *t, int mode, const char text[]) { + /* edit-mode now allows local transforms too */ +#if 0 if (t->flag & T_EDIT) { float obmat[3][3]; copy_m3_m4(obmat, t->scene->obedit->obmat); normalize_m3(obmat); setConstraint(t, obmat, mode, text); } - else { + else +#endif + { if (t->total == 1) { setConstraint(t, t->data->axismtx, mode, text); } @@ -743,37 +747,42 @@ void drawPropCircle(const struct bContext *C, TransInfo *t) static void drawObjectConstraint(TransInfo *t) { - int i; - TransData *td = t->data; - /* Draw the first one lighter because that's the one who controls the others. * Meaning the transformation is projected on that one and just copied on the others * constraint space. * In a nutshell, the object with light axis is controlled by the user and the others follow. * Without drawing the first light, users have little clue what they are doing. */ - if (t->con.mode & CON_AXIS0) { - drawLine(t, td->ob->obmat[3], td->axismtx[0], 'X', DRAWLIGHT); - } - if (t->con.mode & CON_AXIS1) { - drawLine(t, td->ob->obmat[3], td->axismtx[1], 'Y', DRAWLIGHT); - } - if (t->con.mode & CON_AXIS2) { - drawLine(t, td->ob->obmat[3], td->axismtx[2], 'Z', DRAWLIGHT); - } + short options = DRAWLIGHT; + TransData *td = t->data; + int i; - td++; + for (i = 0; i < t->total; i++, td++) { + float co[3]; + + if (t->flag & T_OBJECT) { + copy_v3_v3(co, td->ob->obmat[3]); + } + else if (t->flag & T_EDIT) { + mul_v3_m4v3(co, t->obedit->obmat, td->center); + } + else if (t->flag & T_POSE) { + mul_v3_m4v3(co, t->poseobj->obmat, td->center); + } + else { + copy_v3_v3(co, td->center); + } - for (i = 1; i < t->total; i++, td++) { if (t->con.mode & CON_AXIS0) { - drawLine(t, td->ob->obmat[3], td->axismtx[0], 'X', 0); + drawLine(t, td->center, td->axismtx[0], 'X', options); } if (t->con.mode & CON_AXIS1) { - drawLine(t, td->ob->obmat[3], td->axismtx[1], 'Y', 0); + drawLine(t, td->center, td->axismtx[1], 'Y', options); } if (t->con.mode & CON_AXIS2) { - drawLine(t, td->ob->obmat[3], td->axismtx[2], 'Z', 0); + drawLine(t, td->center, td->axismtx[2], 'Z', options); } + options &= ~DRAWLIGHT; } } @@ -992,20 +1001,20 @@ char constraintModeToChar(TransInfo *t) } -int isLockConstraint(TransInfo *t) +bool isLockConstraint(TransInfo *t) { int mode = t->con.mode; if ((mode & (CON_AXIS0 | CON_AXIS1)) == (CON_AXIS0 | CON_AXIS1)) - return 1; + return true; if ((mode & (CON_AXIS1 | CON_AXIS2)) == (CON_AXIS1 | CON_AXIS2)) - return 1; + return true; if ((mode & (CON_AXIS0 | CON_AXIS2)) == (CON_AXIS0 | CON_AXIS2)) - return 1; + return true; - return 0; + return false; } /* diff --git a/source/blender/editors/transform/transform_conversions.c b/source/blender/editors/transform/transform_conversions.c index f84c967711c..661d7055036 100644 --- a/source/blender/editors/transform/transform_conversions.c +++ b/source/blender/editors/transform/transform_conversions.c @@ -125,7 +125,7 @@ /* local function prototype - for Object/Bone Constraints */ -static short constraints_list_needinv(TransInfo *t, ListBase *list); +static bool constraints_list_needinv(TransInfo *t, ListBase *list); /* ************************** Functions *************************** */ @@ -1236,6 +1236,8 @@ static void createTransMBallVerts(TransInfo *t) copy_v3_v3(td->iloc, td->loc); copy_v3_v3(td->center, td->loc); + quat_to_mat3(td->axismtx, ml->quat); + if (ml->flag & SELECT) td->flag = TD_SELECTED | TD_USEQUAT | TD_SINGLESIZE; else td->flag = TD_USEQUAT; @@ -1858,32 +1860,29 @@ static void editmesh_set_connectivity_distance(BMEditMesh *em, float mtx[3][3], MEM_freeN(tots); } -/* loop-in-a-loop I know, but we need it! (ton) */ -static void get_face_center(float r_cent[3], BMVert *eve) - +static BMElem *bm_vert_single_select_face(BMVert *eve) { - BMFace *efa; + BMElem *ele; BMIter iter; - BM_ITER_ELEM (efa, &iter, eve, BM_FACES_OF_VERT) { - if (BM_elem_flag_test(efa, BM_ELEM_SELECT)) { - BM_face_calc_center_mean(efa, r_cent); - break; + BM_ITER_ELEM (ele, &iter, eve, BM_FACES_OF_VERT) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { + return ele; } } + return NULL; } - -static void get_edge_center(float r_cent[3], BMVert *eve) +static BMElem *bm_vert_single_select_edge(BMVert *eve) { - BMEdge *eed; + BMElem *ele; BMIter iter; - BM_ITER_ELEM (eed, &iter, eve, BM_EDGES_OF_VERT) { - if (BM_elem_flag_test(eed, BM_ELEM_SELECT)) { - mid_v3_v3v3(r_cent, eed->v1->co, eed->v2->co); - break; + BM_ITER_ELEM (ele, &iter, eve, BM_EDGES_OF_VERT) { + if (BM_elem_flag_test(ele, BM_ELEM_SELECT)) { + return ele; } } + return NULL; } /* way to overwrite what data is edited with transform */ @@ -1895,25 +1894,51 @@ static void VertsToTransData(TransInfo *t, TransData *td, TransDataExtension *tx // td->loc = key->co; //else td->loc = eve->co; - + copy_v3_v3(td->iloc, td->loc); copy_v3_v3(td->center, td->loc); if (t->around == V3D_LOCAL) { - if (em->selectmode & SCE_SELECT_FACE) - get_face_center(td->center, eve); - else if (em->selectmode & SCE_SELECT_EDGE) - get_edge_center(td->center, eve); + BMElem *ele; + bool is_axismat_set = false; + + if (em->selectmode & (SCE_SELECT_FACE | SCE_SELECT_EDGE) && + (ele = ((em->selectmode & SCE_SELECT_FACE) ? + bm_vert_single_select_face(eve) : + bm_vert_single_select_edge(eve)))) + { + float normal[3], tangent[3]; + + BMEditSelection ese; + ese.next = ese.prev = NULL; + ese.ele = ele; + ese.htype = ele->head.htype; + + BM_editselection_center(&ese, td->center); + BM_editselection_normal(&ese, normal); + BM_editselection_plane(&ese, tangent); + + if (createSpaceNormalTangent(td->axismtx, normal, tangent)) { + is_axismat_set = true; + } + } + + /* for verts or fallback when createSpaceNormalTangent fails */ + if (is_axismat_set == false) { + axis_dominant_v3_to_m3(td->axismtx, eve->no); + invert_m3(td->axismtx); + } + } + else { + /* Setting normals */ + copy_v3_v3(td->axismtx[2], eve->no); + td->axismtx[0][0] = + td->axismtx[0][1] = + td->axismtx[0][2] = + td->axismtx[1][0] = + td->axismtx[1][1] = + td->axismtx[1][2] = 0.0f; } - copy_v3_v3(td->iloc, td->loc); - // Setting normals - copy_v3_v3(td->axismtx[2], eve->no); - td->axismtx[0][0] = - td->axismtx[0][1] = - td->axismtx[0][2] = - td->axismtx[1][0] = - td->axismtx[1][1] = - td->axismtx[1][2] = 0.0f; td->ext = NULL; td->val = NULL; @@ -2503,7 +2528,7 @@ void flushTransUVs(TransInfo *t) } } -int clipUVTransform(TransInfo *t, float *vec, int resize) +bool clipUVTransform(TransInfo *t, float vec[2], const bool resize) { TransData *td; int a, clipx = 1, clipy = 1; @@ -2574,16 +2599,16 @@ void clipUVData(TransInfo *t) /* ********************* ANIMATION EDITORS (GENERAL) ************************* */ /* This function tests if a point is on the "mouse" side of the cursor/frame-marking */ -static short FrameOnMouseSide(char side, float frame, float cframe) +static bool FrameOnMouseSide(char side, float frame, float cframe) { /* both sides, so it doesn't matter */ - if (side == 'B') return 1; + if (side == 'B') return true; /* only on the named side */ if (side == 'R') - return (frame >= cframe) ? 1 : 0; + return (frame >= cframe); else - return (frame <= cframe) ? 1 : 0; + return (frame <= cframe); } /* ********************* NLA EDITOR ************************* */ @@ -4523,7 +4548,7 @@ static void createTransSeqData(bContext *C, TransInfo *t) * These particular constraints benefit from this, but others don't, hence * this semi-hack ;-) - Aligorith */ -static short constraints_list_needinv(TransInfo *t, ListBase *list) +static bool constraints_list_needinv(TransInfo *t, ListBase *list) { bConstraint *con; @@ -4536,26 +4561,30 @@ static short constraints_list_needinv(TransInfo *t, ListBase *list) if ((con->flag & CONSTRAINT_DISABLE) == 0 && (con->enforce != 0.0f)) { /* (affirmative) returns for specific constraints here... */ /* constraints that require this regardless */ - if (con->type == CONSTRAINT_TYPE_CHILDOF) return 1; - if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) return 1; - if (con->type == CONSTRAINT_TYPE_CLAMPTO) return 1; - if (con->type == CONSTRAINT_TYPE_OBJECTSOLVER) return 1; - if (con->type == CONSTRAINT_TYPE_FOLLOWTRACK) return 1; - + if (ELEM5(con->type, + CONSTRAINT_TYPE_CHILDOF, + CONSTRAINT_TYPE_FOLLOWPATH, + CONSTRAINT_TYPE_CLAMPTO, + CONSTRAINT_TYPE_OBJECTSOLVER, + CONSTRAINT_TYPE_FOLLOWTRACK)) + { + return true; + } + /* constraints that require this only under special conditions */ if (con->type == CONSTRAINT_TYPE_ROTLIKE) { /* CopyRot constraint only does this when rotating, and offset is on */ bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data; if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION)) - return 1; + return true; } } } } /* no appropriate candidates found */ - return 0; + return false; } /* transcribe given object into TransData for Transforming */ @@ -4563,8 +4592,8 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) { Scene *scene = t->scene; float obmtx[3][3]; - short constinv; - short skip_invert = 0; + bool constinv; + bool skip_invert = false; if (t->mode != TFM_DUMMY && ob->rigidbody_object) { float rot[3][3], scale[3]; @@ -4602,15 +4631,15 @@ static void ObjectToTransData(TransInfo *t, TransData *td, Object *ob) /* disable constraints inversion for dummy pass */ if (t->mode == TFM_DUMMY) - skip_invert = 1; + skip_invert = true; - if (skip_invert == 0 && constinv == 0) { - if (constinv == 0) + if (skip_invert == false && constinv == false) { + if (constinv == false) ob->transflag |= OB_NO_CONSTRAINTS; /* BKE_object_where_is_calc_time checks this */ BKE_object_where_is_calc(t->scene, ob); - if (constinv == 0) + if (constinv == false) ob->transflag &= ~OB_NO_CONSTRAINTS; } else @@ -4762,19 +4791,19 @@ static void set_trans_object_base_flags(TransInfo *t) } } -static int mark_children(Object *ob) +static bool mark_children(Object *ob) { if (ob->flag & (SELECT | BA_TRANSFORM_CHILD)) - return 1; + return true; if (ob->parent) { if (mark_children(ob->parent)) { ob->flag |= BA_TRANSFORM_CHILD; - return 1; + return true; } } - return 0; + return false; } static int count_proportional_objects(TransInfo *t) diff --git a/source/blender/editors/transform/transform_manipulator.c b/source/blender/editors/transform/transform_manipulator.c index 41a3418ada9..889e4f01fc7 100644 --- a/source/blender/editors/transform/transform_manipulator.c +++ b/source/blender/editors/transform/transform_manipulator.c @@ -719,13 +719,13 @@ static void partial_doughnut(float radring, float radhole, int start, int end, i side_delta = 2.0f * (float)M_PI / (float)nsides; theta = (float)M_PI + 0.5f * ring_delta; - cos_theta = (float)cos(theta); - sin_theta = (float)sin(theta); + cos_theta = cosf(theta); + sin_theta = sinf(theta); for (i = nrings - 1; i >= 0; i--) { theta1 = theta + ring_delta; - cos_theta1 = (float)cos(theta1); - sin_theta1 = (float)sin(theta1); + cos_theta1 = cosf(theta1); + sin_theta1 = sinf(theta1); if (do_caps && i == start) { // cap glBegin(GL_POLYGON); @@ -766,8 +766,8 @@ static void partial_doughnut(float radring, float radhole, int start, int end, i float cos_phi, sin_phi, dist; phi -= side_delta; - cos_phi = (float)cos(phi); - sin_phi = (float)sin(phi); + cos_phi = cosf(phi); + sin_phi = sinf(phi); dist = radhole + radring * cos_phi; glVertex3f(cos_theta * dist, -sin_theta * dist, radring * sin_phi); @@ -841,27 +841,6 @@ static void manipulator_setcolor(View3D *v3d, char axis, int colcode, unsigned c glColor4ubv(col); } -static void axis_sort_v3(const float axis_values[3], int r_axis_order[3]) -{ - float v[3]; - copy_v3_v3(v, axis_values); - -#define SWAP_AXIS(a, b) { \ - SWAP(float, v[a], v[b]); \ - SWAP(int, r_axis_order[a], r_axis_order[b]); \ -} (void)0 - - if (v[0] < v[1]) { - if (v[2] < v[0]) { SWAP_AXIS(0, 2); } - } - else { - if (v[1] < v[2]) { SWAP_AXIS(0, 1); } - else { SWAP_AXIS(0, 2); } - } - if (v[2] < v[1]) { SWAP_AXIS(1, 2); } - -#undef SWAP_AXIS -} static void manipulator_axis_order(RegionView3D *rv3d, int r_axis_order[3]) { float axis_values[3]; @@ -1635,15 +1614,18 @@ void BIF_draw_manipulator(const bContext *C) switch (v3d->around) { case V3D_CENTER: case V3D_ACTIVE: - rv3d->twmat[3][0] = (scene->twmin[0] + scene->twmax[0]) / 2.0f; - rv3d->twmat[3][1] = (scene->twmin[1] + scene->twmax[1]) / 2.0f; - rv3d->twmat[3][2] = (scene->twmin[2] + scene->twmax[2]) / 2.0f; - if (v3d->around == V3D_ACTIVE && scene->obedit == NULL) { - Object *ob = OBACT; - if (ob && !(ob->mode & OB_MODE_POSE)) - copy_v3_v3(rv3d->twmat[3], ob->obmat[3]); + { + Object *ob; + if (((v3d->around == V3D_ACTIVE) && (scene->obedit == NULL)) && + ((ob = OBACT) && !(ob->mode & OB_MODE_POSE))) + { + copy_v3_v3(rv3d->twmat[3], ob->obmat[3]); + } + else { + mid_v3_v3v3(rv3d->twmat[3], scene->twmin, scene->twmax); } break; + } case V3D_LOCAL: case V3D_CENTROID: copy_v3_v3(rv3d->twmat[3], scene->twcent); diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c index 0c1f169935a..023083a98ff 100644 --- a/source/blender/editors/transform/transform_orientations.c +++ b/source/blender/editors/transform/transform_orientations.c @@ -213,13 +213,13 @@ TransformOrientation *createMeshSpace(bContext *C, ReportList *reports, char *na return addMatrixSpace(C, mat, name, overwrite); } -int createSpaceNormal(float mat[3][3], float normal[3]) +bool createSpaceNormal(float mat[3][3], const float normal[3]) { float tangent[3] = {0.0f, 0.0f, 1.0f}; copy_v3_v3(mat[2], normal); if (normalize_v3(mat[2]) == 0.0f) { - return 0; /* error return */ + return false; /* error return */ } cross_v3_v3v3(mat[0], mat[2], tangent); @@ -233,14 +233,14 @@ int createSpaceNormal(float mat[3][3], float normal[3]) normalize_m3(mat); - return 1; + return true; } -int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]) +bool createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]) { copy_v3_v3(mat[2], normal); if (normalize_v3(mat[2]) == 0.0f) { - return 0; /* error return */ + return false; /* error return */ } /* preempt zero length tangent from causing trouble */ @@ -250,14 +250,14 @@ int createSpaceNormalTangent(float mat[3][3], float normal[3], float tangent[3]) cross_v3_v3v3(mat[0], mat[2], tangent); if (normalize_v3(mat[0]) == 0.0f) { - return 0; /* error return */ + return false; /* error return */ } cross_v3_v3v3(mat[1], mat[2], mat[0]); normalize_m3(mat); - return 1; + return true; } TransformOrientation *addMatrixSpace(bContext *C, float mat[3][3], char name[], int overwrite) diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c index fdbfdfc8675..c6ab33124ef 100644 --- a/source/blender/editors/transform/transform_snap.c +++ b/source/blender/editors/transform/transform_snap.c @@ -78,7 +78,11 @@ #include "transform.h" -#define TRANSFORM_DIST_MAX_PX 1000 +/* this should be passed as an arg for use in snap functions */ +#undef BASACT + +#define TRANSFORM_DIST_MAX_PX 1000.0f +#define TRANSFORM_SNAP_MAX_PX 100.0f /********************* PROTOTYPES ***********************/ @@ -120,13 +124,13 @@ int BIF_snappingSupported(Object *obedit) } #endif -int validSnap(TransInfo *t) +bool validSnap(TransInfo *t) { return (t->tsnap.status & (POINT_INIT | TARGET_INIT)) == (POINT_INIT | TARGET_INIT) || (t->tsnap.status & (MULTI_POINTS | TARGET_INIT)) == (MULTI_POINTS | TARGET_INIT); } -int activeSnap(TransInfo *t) +bool activeSnap(TransInfo *t) { return (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP || (t->modifiers & (MOD_SNAP | MOD_SNAP_INVERT)) == MOD_SNAP_INVERT; } @@ -260,9 +264,9 @@ void drawSnapping(const struct bContext *C, TransInfo *t) } } -int handleSnapping(TransInfo *t, const wmEvent *event) +bool handleSnapping(TransInfo *t, const wmEvent *event) { - int status = 0; + bool status = false; #if 0 // XXX need a proper selector for all snap mode if (BIF_snappingSupported(t->obedit) && event->type == TABKEY && event->shift) { @@ -295,8 +299,8 @@ void applyProject(TransInfo *t) for (i = 0; i < t->total; i++, td++) { float iloc[3], loc[3], no[3]; - float mval[2]; - int dist = TRANSFORM_DIST_MAX_PX; + float mval_fl[2]; + float dist_px = TRANSFORM_DIST_MAX_PX; if (td->flag & TD_NOACTION) break; @@ -318,8 +322,8 @@ void applyProject(TransInfo *t) copy_v3_v3(iloc, td->ob->obmat[3]); } - if (ED_view3d_project_float_global(t->ar, iloc, mval, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - if (snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.modeSelect)) { + if (ED_view3d_project_float_global(t->ar, iloc, mval_fl, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + if (snapObjectsTransform(t, mval_fl, &dist_px, loc, no, t->tsnap.modeSelect)) { // if (t->flag & (T_EDIT|T_POSE)) { // mul_m4_v3(imat, loc); // } @@ -368,7 +372,7 @@ void applySnapping(TransInfo *t, float *vec) void resetSnapping(TransInfo *t) { t->tsnap.status = 0; - t->tsnap.align = 0; + t->tsnap.align = false; t->tsnap.project = 0; t->tsnap.mode = 0; t->tsnap.modeSelect = 0; @@ -383,20 +387,20 @@ void resetSnapping(TransInfo *t) t->tsnap.snapNodeBorder = 0; } -int usingSnappingNormal(TransInfo *t) +bool usingSnappingNormal(TransInfo *t) { return t->tsnap.align; } -int validSnappingNormal(TransInfo *t) +bool validSnappingNormal(TransInfo *t) { if (validSnap(t)) { if (dot_v3v3(t->tsnap.snapNormal, t->tsnap.snapNormal) > 0) { - return 1; + return true; } } - return 0; + return false; } static void initSnappingMode(TransInfo *t) @@ -404,6 +408,7 @@ static void initSnappingMode(TransInfo *t) ToolSettings *ts = t->settings; Object *obedit = t->obedit; Scene *scene = t->scene; + Base *base_act = scene->basact; if (t->spacetype == SPACE_NODE) { /* force project off when not supported */ @@ -444,7 +449,7 @@ static void initSnappingMode(TransInfo *t) } /* Particles edit mode*/ else if (t->tsnap.applySnap != NULL && // A snapping function actually exist - (obedit == NULL && BASACT && BASACT->object && BASACT->object->mode & OB_MODE_PARTICLE_EDIT)) + (obedit == NULL && base_act && base_act->object && base_act->object->mode & OB_MODE_PARTICLE_EDIT)) { t->tsnap.modeSelect = SNAP_ALL; } @@ -598,35 +603,32 @@ void addSnapPoint(TransInfo *t) } } -int updateSelectedSnapPoint(TransInfo *t) +bool updateSelectedSnapPoint(TransInfo *t) { - int status = 0; + bool status = false; if (t->tsnap.status & MULTI_POINTS) { TransSnapPoint *p, *closest_p = NULL; - int closest_dist = 0; - int screen_loc[2]; + float closest_dist = TRANSFORM_SNAP_MAX_PX; + const float mval_fl[2] = {t->mval[0], t->mval[1]}; + float screen_loc[2]; for (p = t->tsnap.points.first; p; p = p->next) { - int dx, dy; - int dist; + float dist; - if (ED_view3d_project_int_global(t->ar, p->co, screen_loc, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) { + if (ED_view3d_project_float_global(t->ar, p->co, screen_loc, V3D_PROJ_TEST_NOP) != V3D_PROJ_RET_OK) { continue; } - dx = t->mval[0] - screen_loc[0]; - dy = t->mval[1] - screen_loc[1]; - - dist = dx * dx + dy * dy; + dist = len_squared_v2v2(mval_fl, screen_loc); - if (dist < 100 && (closest_p == NULL || closest_dist > dist)) { + if (dist < closest_dist) { closest_p = p; closest_dist = dist; } } if (closest_p) { - status = t->tsnap.selectedPoint == closest_p ? 0 : 1; + status = (t->tsnap.selectedPoint != closest_p); t->tsnap.selectedPoint = closest_p; } } @@ -819,7 +821,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) float no[3]; float mval[2]; bool found = false; - int dist = SNAP_MIN_DISTANCE; // Use a user defined value here + float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here mval[0] = t->mval[0]; mval[1] = t->mval[1]; @@ -907,7 +909,7 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) BLI_freelistN(&depth_peels); } else { - found = snapObjectsTransform(t, mval, &dist, loc, no, t->tsnap.modeSelect); + found = snapObjectsTransform(t, mval, &dist_px, loc, no, t->tsnap.modeSelect); } if (found == true) { @@ -949,10 +951,10 @@ static void CalcSnapGeometry(TransInfo *t, float *UNUSED(vec)) } else if (t->spacetype == SPACE_NODE) { float loc[2]; - int dist = SNAP_MIN_DISTANCE; // Use a user defined value here + float dist_px = SNAP_MIN_DISTANCE; // Use a user defined value here char node_border; - if (snapNodesTransform(t, t->mval, &dist, loc, &node_border, t->tsnap.modeSelect)) { + if (snapNodesTransform(t, t->mval, &dist_px, loc, &node_border, t->tsnap.modeSelect)) { copy_v2_v2(t->tsnap.snapPoint, loc); t->tsnap.snapNodeBorder = node_border; @@ -1145,8 +1147,8 @@ static void TargetSnapClosest(TransInfo *t) } static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], short v2no[3], float obmat[4][4], float timat[3][3], - const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], - float r_loc[3], float r_no[3], int *r_dist, float *r_depth) + const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval_fl[2], + float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth) { float intersect[3] = {0, 0, 0}, ray_end[3], dvec[3]; int result; @@ -1182,8 +1184,8 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s if (dot_v3v3(ray_normal_local, dvec) > 0) { float location[3]; float new_depth; - int screen_loc[2]; - int new_dist; + float screen_loc[2]; + float new_dist; copy_v3_v3(location, intersect); @@ -1191,8 +1193,8 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s new_depth = len_v3v3(location, ray_start); - if (ED_view3d_project_int_global(ar, location, screen_loc, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]); + if (ED_view3d_project_float_global(ar, location, screen_loc, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + new_dist = len_manhattan_v2v2(mval_fl, screen_loc); } else { new_dist = TRANSFORM_DIST_MAX_PX; @@ -1202,7 +1204,7 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s * this takes care of series of connected edges a bit slanted w.r.t the viewport * otherwise, it would stick to the verts of the closest edge and not slide along merrily * */ - if (new_dist <= *r_dist && new_depth < *r_depth * 1.001f) { + if (new_dist <= *r_dist_px && new_depth < *r_depth * 1.001f) { float n1[3], n2[3]; *r_depth = new_depth; @@ -1223,7 +1225,7 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s copy_v3_v3(r_loc, location); - *r_dist = new_dist; + *r_dist_px = new_dist; } } } @@ -1232,8 +1234,8 @@ static bool snapEdge(ARegion *ar, float v1co[3], short v1no[3], float v2co[3], s } static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4], float timat[3][3], - const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval[2], - float r_loc[3], float r_no[3], int *r_dist, float *r_depth) + const float ray_start[3], const float ray_start_local[3], const float ray_normal_local[3], const float mval_fl[2], + float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth) { bool retval = false; float dvec[3]; @@ -1243,8 +1245,8 @@ static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4 if (dot_v3v3(ray_normal_local, dvec) > 0) { float location[3]; float new_depth; - int screen_loc[2]; - int new_dist; + float screen_loc[2]; + float new_dist; copy_v3_v3(location, vco); @@ -1252,15 +1254,15 @@ static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4 new_depth = len_v3v3(location, ray_start); - if (ED_view3d_project_int_global(ar, location, screen_loc, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { - new_dist = abs(screen_loc[0] - (int)mval[0]) + abs(screen_loc[1] - (int)mval[1]); + if (ED_view3d_project_float_global(ar, location, screen_loc, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) { + new_dist = len_manhattan_v2v2(mval_fl, screen_loc); } else { new_dist = TRANSFORM_DIST_MAX_PX; } - if (new_dist <= *r_dist && new_depth < *r_depth) { + if (new_dist <= *r_dist_px && new_depth < *r_depth) { *r_depth = new_depth; retval = true; @@ -1272,7 +1274,7 @@ static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4 normalize_v3(r_no); } - *r_dist = new_dist; + *r_dist_px = new_dist; } } @@ -1281,7 +1283,7 @@ static bool snapVertex(ARegion *ar, float vco[3], short vno[3], float obmat[4][4 static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *arm, float obmat[4][4], const float ray_start[3], const float ray_normal[3], const float mval[2], - float r_loc[3], float *UNUSED(r_no), int *r_dist, float *r_depth) + float r_loc[3], float *UNUSED(r_no), float *r_dist_px, float *r_depth) { float imat[4][4]; float ray_start_local[3], ray_normal_local[3]; @@ -1304,11 +1306,11 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar if ((eBone->flag & (BONE_HIDDEN_A | BONE_ROOTSEL | BONE_TIPSEL)) == 0) { switch (snap_mode) { case SCE_SNAP_MODE_VERTEX: - retval |= snapVertex(ar, eBone->head, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth); - retval |= snapVertex(ar, eBone->tail, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth); + retval |= snapVertex(ar, eBone->head, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth); + retval |= snapVertex(ar, eBone->tail, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth); break; case SCE_SNAP_MODE_EDGE: - retval |= snapEdge(ar, eBone->head, NULL, eBone->tail, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth); + retval |= snapEdge(ar, eBone->head, NULL, eBone->tail, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth); break; } } @@ -1328,11 +1330,11 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar switch (snap_mode) { case SCE_SNAP_MODE_VERTEX: - retval |= snapVertex(ar, head_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth); - retval |= snapVertex(ar, tail_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth); + retval |= snapVertex(ar, head_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth); + retval |= snapVertex(ar, tail_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth); break; case SCE_SNAP_MODE_EDGE: - retval |= snapEdge(ar, head_vec, NULL, tail_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist, r_depth); + retval |= snapEdge(ar, head_vec, NULL, tail_vec, NULL, obmat, NULL, ray_start, ray_start_local, ray_normal_local, mval, r_loc, NULL, r_dist_px, r_depth); break; } } @@ -1344,7 +1346,7 @@ static bool snapArmature(short snap_mode, ARegion *ar, Object *ob, bArmature *ar static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMesh *dm, BMEditMesh *em, float obmat[4][4], const float ray_start[3], const float ray_normal[3], const float mval[2], - float r_loc[3], float r_no[3], int *r_dist, float *r_depth) + float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth) { bool retval = false; int totvert = dm->getNumVerts(dm); @@ -1451,7 +1453,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes if (test) { - retval |= snapVertex(ar, v->co, v->no, obmat, timat, ray_start, ray_start_local, ray_normal_local, mval, r_loc, r_no, r_dist, r_depth); + retval |= snapVertex(ar, v->co, v->no, obmat, timat, ray_start, ray_start_local, ray_normal_local, mval, r_loc, r_no, r_dist_px, r_depth); } } @@ -1501,7 +1503,7 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes } if (test) { - retval |= snapEdge(ar, verts[e->v1].co, verts[e->v1].no, verts[e->v2].co, verts[e->v2].no, obmat, timat, ray_start, ray_start_local, ray_normal_local, mval, r_loc, r_no, r_dist, r_depth); + retval |= snapEdge(ar, verts[e->v1].co, verts[e->v1].no, verts[e->v2].co, verts[e->v2].no, obmat, timat, ray_start, ray_start_local, ray_normal_local, mval, r_loc, r_no, r_dist_px, r_depth); } } @@ -1514,11 +1516,10 @@ static bool snapDerivedMesh(short snap_mode, ARegion *ar, Object *ob, DerivedMes return retval; } -static bool snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, float obmat[4][4], +static bool snapObject(Scene *scene, short snap_mode, ARegion *ar, Object *ob, int editobject, float obmat[4][4], const float ray_start[3], const float ray_normal[3], const float mval[2], - float r_loc[3], float r_no[3], int *r_dist, float *r_depth) + float r_loc[3], float r_no[3], float *r_dist_px, float *r_depth) { - ToolSettings *ts = scene->toolsettings; bool retval = false; if (ob->type == OB_MESH) { @@ -1535,31 +1536,29 @@ static bool snapObject(Scene *scene, ARegion *ar, Object *ob, int editobject, fl dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH); } - retval = snapDerivedMesh(ts->snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, r_depth); + retval = snapDerivedMesh(snap_mode, ar, ob, dm, em, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth); dm->release(dm); } else if (ob->type == OB_ARMATURE) { - retval = snapArmature(ts->snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, r_depth); + retval = snapArmature(snap_mode, ar, ob, ob->data, obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, r_depth); } return retval; } -static bool snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, const float mval[2], - int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) +static bool snapObjectsRay(Scene *scene, short snap_mode, Base *base_act, View3D *v3d, ARegion *ar, Object *obedit, + const float ray_start[3], const float ray_normal[3], + const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode) { Base *base; float depth = (FLT_MAX / 2.0f); /* use half of flt-max so we can scale up without an exception */ bool retval = false; - float ray_start[3], ray_normal[3]; - - ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal); if (mode == SNAP_ALL && obedit) { Object *ob = obedit; - retval |= snapObject(scene, ar, ob, 1, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, &depth); + retval |= snapObject(scene, snap_mode, ar, ob, 1, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, &depth); } /* Need an exception for particle edit because the base is flagged with BA_HAS_RECALC_DATA @@ -1567,10 +1566,10 @@ static bool snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, * * To solve that problem, we do it first as an exception. * */ - base = BASACT; + base = base_act; if (base && base->object && base->object->mode & OB_MODE_PARTICLE_EDIT) { Object *ob = base->object; - retval |= snapObject(scene, ar, ob, 0, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, &depth); + retval |= snapObject(scene, snap_mode, ar, ob, 0, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, &depth); } for (base = FIRSTBASE; base != NULL; base = base->next) { @@ -1578,7 +1577,7 @@ static bool snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, (base->flag & (BA_HAS_RECALC_OB | BA_HAS_RECALC_DATA)) == 0 && ((mode == SNAP_NOT_SELECTED && (base->flag & (SELECT | BA_WAS_SEL)) == 0) || - (ELEM(mode, SNAP_ALL, SNAP_NOT_OBEDIT) && base != BASACT))) + (ELEM(mode, SNAP_ALL, SNAP_NOT_OBEDIT) && base != base_act))) { Object *ob = base->object; @@ -1589,30 +1588,58 @@ static bool snapObjects(Scene *scene, View3D *v3d, ARegion *ar, Object *obedit, for (dupli_ob = lb->first; dupli_ob; dupli_ob = dupli_ob->next) { Object *dob = dupli_ob->ob; - retval |= snapObject(scene, ar, dob, 0, dupli_ob->mat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, &depth); + retval |= snapObject(scene, snap_mode, ar, dob, 0, dupli_ob->mat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, &depth); } free_object_duplilist(lb); } - retval |= snapObject(scene, ar, ob, 0, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist, &depth); + retval |= snapObject(scene, snap_mode, ar, ob, 0, ob->obmat, ray_start, ray_normal, mval, r_loc, r_no, r_dist_px, &depth); } } return retval; } +static bool snapObjects(Scene *scene, short snap_mode, Base *base_act, View3D *v3d, ARegion *ar, Object *obedit, + const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode) +{ + float ray_start[3], ray_normal[3]; + + ED_view3d_win_to_ray(ar, v3d, mval, ray_start, ray_normal); + + return snapObjectsRay(scene, snap_mode, base_act, v3d, ar, obedit, + ray_start, ray_normal, + mval, r_dist_px, r_loc, r_no, mode); +} -bool snapObjectsTransform(TransInfo *t, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) +bool snapObjectsTransform(TransInfo *t, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode) { - return snapObjects(t->scene, t->view, t->ar, t->obedit, mval, r_dist, r_loc, r_no, mode); + return snapObjects(t->scene, t->scene->toolsettings->snap_mode, t->scene->basact, t->view, t->ar, t->obedit, + mval, r_dist_px, r_loc, r_no, mode); } -bool snapObjectsContext(bContext *C, const float mval[2], int *r_dist, float r_loc[3], float r_no[3], SnapMode mode) +bool snapObjectsContext(bContext *C, const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode) { ScrArea *sa = CTX_wm_area(C); View3D *v3d = sa->spacedata.first; + Scene *scene = CTX_data_scene(C); - return snapObjects(CTX_data_scene(C), v3d, CTX_wm_region(C), CTX_data_edit_object(C), mval, r_dist, r_loc, r_no, mode); + return snapObjects(scene, scene->toolsettings->snap_mode, scene->basact, v3d, CTX_wm_region(C), CTX_data_edit_object(C), mval, r_dist_px, r_loc, r_no, mode); +} + +bool snapObjectsEx(Scene *scene, Base *base_act, View3D *v3d, ARegion *ar, Object *obedit, short snap_mode, + const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode) +{ + return snapObjects(scene, snap_mode, base_act, v3d, ar, obedit, + mval, r_dist_px, r_loc, r_no, mode); +} +bool snapObjectsRayEx(Scene *scene, Base *base_act, View3D *v3d, ARegion *ar, Object *obedit, short snap_mode, + const float ray_start[3], const float ray_normal[3], + const float mval[2], float *r_dist_px, float r_loc[3], float r_no[3], SnapMode mode) +{ + return snapObjectsRay(scene, snap_mode, base_act, v3d, ar, obedit, + ray_start, ray_normal, + mval, r_dist_px, r_loc, r_no, mode); } /******************** PEELING *********************************/ @@ -1889,7 +1916,7 @@ static NodeBorder snapNodeBorder(int snap_node_mode) } static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bNode *node, const int mval[2], - float r_loc[2], int *r_dist, char *r_node_border) + float r_loc[2], float *r_dist_px, char *r_node_border) { View2D *v2d = &ar->v2d; NodeBorder border = snapNodeBorder(ts->snap_node_mode); @@ -1902,9 +1929,9 @@ static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bN if (border & NODE_LEFT) { new_dist = abs(totr.xmin - mval[0]); - if (new_dist < *r_dist) { + if (new_dist < *r_dist_px) { UI_view2d_region_to_view(v2d, totr.xmin, mval[1], &r_loc[0], &r_loc[1]); - *r_dist = new_dist; + *r_dist_px = new_dist; *r_node_border = NODE_LEFT; retval = true; } @@ -1912,9 +1939,9 @@ static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bN if (border & NODE_RIGHT) { new_dist = abs(totr.xmax - mval[0]); - if (new_dist < *r_dist) { + if (new_dist < *r_dist_px) { UI_view2d_region_to_view(v2d, totr.xmax, mval[1], &r_loc[0], &r_loc[1]); - *r_dist = new_dist; + *r_dist_px = new_dist; *r_node_border = NODE_RIGHT; retval = true; } @@ -1922,9 +1949,9 @@ static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bN if (border & NODE_BOTTOM) { new_dist = abs(totr.ymin - mval[1]); - if (new_dist < *r_dist) { + if (new_dist < *r_dist_px) { UI_view2d_region_to_view(v2d, mval[0], totr.ymin, &r_loc[0], &r_loc[1]); - *r_dist = new_dist; + *r_dist_px = new_dist; *r_node_border = NODE_BOTTOM; retval = true; } @@ -1932,9 +1959,9 @@ static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bN if (border & NODE_TOP) { new_dist = abs(totr.ymax - mval[1]); - if (new_dist < *r_dist) { + if (new_dist < *r_dist_px) { UI_view2d_region_to_view(v2d, mval[0], totr.ymax, &r_loc[0], &r_loc[1]); - *r_dist = new_dist; + *r_dist_px = new_dist; *r_node_border = NODE_TOP; retval = true; } @@ -1944,7 +1971,7 @@ static bool snapNode(ToolSettings *ts, SpaceNode *UNUSED(snode), ARegion *ar, bN } static bool snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int mval[2], - int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) + float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode) { bNodeTree *ntree = snode->edittree; bNode *node; @@ -1954,21 +1981,21 @@ static bool snapNodes(ToolSettings *ts, SpaceNode *snode, ARegion *ar, const int for (node = ntree->nodes.first; node; node = node->next) { if (snapNodeTest(&ar->v2d, node, mode)) - retval |= snapNode(ts, snode, ar, node, mval, r_loc, r_dist, r_node_border); + retval |= snapNode(ts, snode, ar, node, mval, r_loc, r_dist_px, r_node_border); } return retval; } -bool snapNodesTransform(TransInfo *t, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) +bool snapNodesTransform(TransInfo *t, const int mval[2], float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode) { - return snapNodes(t->settings, t->sa->spacedata.first, t->ar, mval, r_dist, r_loc, r_node_border, mode); + return snapNodes(t->settings, t->sa->spacedata.first, t->ar, mval, r_dist_px, r_loc, r_node_border, mode); } -bool snapNodesContext(bContext *C, const int mval[2], int *r_dist, float r_loc[2], char *r_node_border, SnapMode mode) +bool snapNodesContext(bContext *C, const int mval[2], float *r_dist_px, float r_loc[2], char *r_node_border, SnapMode mode) { Scene *scene = CTX_data_scene(C); - return snapNodes(scene->toolsettings, CTX_wm_space_node(C), CTX_wm_region(C), mval, r_dist, r_loc, r_node_border, mode); + return snapNodes(scene->toolsettings, CTX_wm_space_node(C), CTX_wm_region(C), mval, r_dist_px, r_loc, r_node_border, mode); } /*================================================================*/ diff --git a/source/blender/editors/util/CMakeLists.txt b/source/blender/editors/util/CMakeLists.txt index e0991c48fa6..bcc55c4ea6e 100644 --- a/source/blender/editors/util/CMakeLists.txt +++ b/source/blender/editors/util/CMakeLists.txt @@ -32,7 +32,7 @@ set(INC ) set(INC_SYS - + ${GLEW_INCLUDE_PATH} ) set(SRC @@ -90,6 +90,8 @@ set(SRC ../include/UI_view2d.h ) +add_definitions(-DGLEW_STATIC) + if(WITH_INTERNATIONAL) add_definitions(-DWITH_INTERNATIONAL) endif() diff --git a/source/blender/editors/util/SConscript b/source/blender/editors/util/SConscript index 1c1a8e46dd7..8460b307f0d 100644 --- a/source/blender/editors/util/SConscript +++ b/source/blender/editors/util/SConscript @@ -28,7 +28,7 @@ Import ('env') sources = env.Glob('*.c') -defs = [] +defs = [ 'GLEW_STATIC' ] incs = '../include ../../blenfont ../../blenlib ../../blenkernel ../../makesdna ../../imbuf' incs += ' ../../windowmanager #/intern/guardedalloc #/extern/glew/include' diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c index 73062c57526..35e6c40c36b 100644 --- a/source/blender/editors/util/ed_util.c +++ b/source/blender/editors/util/ed_util.c @@ -37,11 +37,15 @@ #include "DNA_mesh_types.h" #include "DNA_object_types.h" +#include "DNA_screen_types.h" #include "DNA_scene_types.h" #include "DNA_packedFile_types.h" #include "BLI_blenlib.h" +#include "BIF_gl.h" +#include "BIF_glutil.h" + #include "BLF_translation.h" #include "BKE_context.h" @@ -54,6 +58,7 @@ #include "ED_mesh.h" #include "ED_object.h" #include "ED_sculpt.h" +#include "ED_space_api.h" #include "ED_util.h" #include "UI_interface.h" @@ -157,17 +162,6 @@ void apply_keyb_grid(int shift, int ctrl, float *val, float fac1, float fac2, fl } } -#if 0 /* UNUSED */ -int GetButStringLength(const char *str) -{ - int rt; - - rt = UI_GetStringWidth(str); - - return rt + 15; -} -#endif - void unpack_menu(bContext *C, const char *opname, const char *id_name, const char *abs_name, const char *folder, struct PackedFile *pf) { PointerRNA props_ptr; @@ -255,3 +249,24 @@ void unpack_menu(bContext *C, const char *opname, const char *id_name, const cha uiPupMenuEnd(C, pup); } + +/* ********************* generic callbacks for drawcall api *********************** */ + +/** + * Callback that draws a line between the mouse and a position given as the initial argument. + */ +void ED_region_draw_mouse_line_cb(const bContext *C, ARegion *ar, void *arg_info) +{ + wmWindow *win = CTX_wm_window(C); + const int *mval_src = (int *)arg_info; + const int mval_dst[2] = {win->eventstate->x - ar->winrct.xmin, + win->eventstate->y - ar->winrct.ymin}; + + UI_ThemeColor(TH_WIRE); + setlinestyle(3); + glBegin(GL_LINE_STRIP); + glVertex2iv(mval_dst); + glVertex2iv(mval_src); + glEnd(); + setlinestyle(0); +} diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h index 17d3ce3cd73..29da72a00fe 100644 --- a/source/blender/gpu/GPU_material.h +++ b/source/blender/gpu/GPU_material.h @@ -129,8 +129,8 @@ void GPU_material_free(struct Material *ma); void GPU_materials_free(void); -void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap); -void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float viewinv[4][4], float obcol[4], float autobumpscale); +void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4]); +void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale); void GPU_material_unbind(GPUMaterial *material); int GPU_material_bound(GPUMaterial *material); diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c index ae1eb62bc18..f1b631192af 100644 --- a/source/blender/gpu/intern/gpu_codegen.c +++ b/source/blender/gpu/intern/gpu_codegen.c @@ -680,12 +680,6 @@ void GPU_code_generate_glsl_lib(void) ds = BLI_dynstr_new(); - if (GPU_bicubic_bump_support()) { - BLI_dynstr_append(ds, "/* These are needed for high quality bump mapping */\n" - "#version 130\n" - "#extension GL_ARB_texture_query_lod: enable\n" - "#define BUMP_BICUBIC\n"); - } BLI_dynstr_append(ds, datatoc_gpu_shader_material_glsl); diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c index b772507e0cc..c78961e6308 100644 --- a/source/blender/gpu/intern/gpu_draw.c +++ b/source/blender/gpu/intern/gpu_draw.c @@ -1457,10 +1457,10 @@ int GPU_enable_material(int nr, void *attribs) gpumat = GPU_material_from_blender(GMS.gscene, mat); GPU_material_vertex_attributes(gpumat, gattribs); - GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT)); + GPU_material_bind(gpumat, GMS.gob->lay, GMS.glay, 1.0, !(GMS.gob->mode & OB_MODE_TEXTURE_PAINT), GMS.gviewmat, GMS.gviewinv); auto_bump_scale = GMS.gob->derivedFinal != NULL ? GMS.gob->derivedFinal->auto_bump_scale : 1.0f; - GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gviewmat, GMS.gviewinv, GMS.gob->col, auto_bump_scale); + GPU_material_bind_uniforms(gpumat, GMS.gob->obmat, GMS.gob->col, auto_bump_scale); GMS.gboundmat= mat; /* for glsl use alpha blend mode, unless it's set to solid and diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c index e8d28877043..7ac852f551a 100644 --- a/source/blender/gpu/intern/gpu_extensions.c +++ b/source/blender/gpu/intern/gpu_extensions.c @@ -1136,6 +1136,18 @@ static void shader_print_errors(const char *task, char *log, const char *code) fprintf(stderr, "%s\n", log); } +static const char *gpu_shader_standard_extensions(void) +{ + /* need this extensions for high quality bump mapping */ + if(GPU_bicubic_bump_support()) { + return "#version 130\n" + "#extension GL_ARB_texture_query_lod: enable\n" + "#define BUMP_BICUBIC\n"; + } + + return ""; +} + static const char *gpu_shader_standard_defines(void) { /* some useful defines to detect GPU type */ @@ -1177,9 +1189,10 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const } if (vertexcode) { - const char *source[3]; + const char *source[4]; int num_source = 0; + source[num_source++] = gpu_shader_standard_extensions(); source[num_source++] = gpu_shader_standard_defines(); if (defines) source[num_source++] = defines; @@ -1201,9 +1214,10 @@ GPUShader *GPU_shader_create(const char *vertexcode, const char *fragcode, const } if (fragcode) { - const char *source[4]; + const char *source[5]; int num_source = 0; + source[num_source++] = gpu_shader_standard_extensions(); source[num_source++] = gpu_shader_standard_defines(); if (defines) source[num_source++] = defines; diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c index 999e3b5c20e..075a670e06e 100644 --- a/source/blender/gpu/intern/gpu_material.c +++ b/source/blender/gpu/intern/gpu_material.c @@ -257,11 +257,12 @@ void GPU_material_free(Material *ma) BLI_freelistN(&ma->gpumaterial); } -void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap) +void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double time, int mipmap, float viewmat[4][4], float viewinv[4][4]) { if (material->pass) { LinkData *nlink; GPULamp *lamp; + GPUShader *shader = GPU_pass_shader(material->pass); /* handle layer lamps */ for (nlink=material->lamps.first; nlink; nlink=nlink->next) { @@ -275,29 +276,52 @@ void GPU_material_bind(GPUMaterial *material, int oblay, int viewlay, double tim lamp->dynenergy = 0.0f; lamp->dyncol[0]= lamp->dyncol[1]= lamp->dyncol[2] = 0.0f; } + + if (material->dynproperty & DYN_LAMP_VEC) { + copy_v3_v3(lamp->dynvec, lamp->vec); + normalize_v3(lamp->dynvec); + negate_v3(lamp->dynvec); + mul_mat3_m4_v3(viewmat, lamp->dynvec); + } + + if (material->dynproperty & DYN_LAMP_CO) { + copy_v3_v3(lamp->dynco, lamp->co); + mul_m4_v3(viewmat, lamp->dynco); + } + + if (material->dynproperty & DYN_LAMP_IMAT) { + mult_m4_m4m4(lamp->dynimat, lamp->imat, viewinv); + } + + if (material->dynproperty & DYN_LAMP_PERSMAT) { + if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */ + GPU_lamp_update_buffer_mats(lamp); + mult_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv); + } + } + + /* handle per material built-ins */ + if (material->builtins & GPU_VIEW_MATRIX) { + GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat); + } + if (material->builtins & GPU_INVERSE_VIEW_MATRIX) { + GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv); } GPU_pass_bind(material->pass, time, mipmap); GPU_pass_update_uniforms(material->pass); + material->bound = 1; } } -void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float viewmat[4][4], float viewinv[4][4], float obcol[4], float autobumpscale) +void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float obcol[4], float autobumpscale) { if (material->pass) { GPUShader *shader = GPU_pass_shader(material->pass); - LinkData *nlink; - GPULamp *lamp; float invmat[4][4], col[4]; - /* handle builtins */ - if (material->builtins & GPU_VIEW_MATRIX) { - GPU_shader_uniform_vector(shader, material->viewmatloc, 16, 1, (float*)viewmat); - } - if (material->builtins & GPU_INVERSE_VIEW_MATRIX) { - GPU_shader_uniform_vector(shader, material->invviewmatloc, 16, 1, (float*)viewinv); - } + /* handle per object builtins */ if (material->builtins & GPU_OBJECT_MATRIX) { GPU_shader_uniform_vector(shader, material->obmatloc, 16, 1, (float*)obmat); } @@ -313,32 +337,6 @@ void GPU_material_bind_uniforms(GPUMaterial *material, float obmat[4][4], float if (material->builtins & GPU_AUTO_BUMPSCALE) { GPU_shader_uniform_vector(shader, material->obautobumpscaleloc, 1, 1, &autobumpscale); } - /* update lamps */ - for (nlink=material->lamps.first; nlink; nlink=nlink->next) { - lamp= nlink->data; - - if (material->dynproperty & DYN_LAMP_VEC) { - copy_v3_v3(lamp->dynvec, lamp->vec); - normalize_v3(lamp->dynvec); - negate_v3(lamp->dynvec); - mul_mat3_m4_v3(viewmat, lamp->dynvec); - } - - if (material->dynproperty & DYN_LAMP_CO) { - copy_v3_v3(lamp->dynco, lamp->co); - mul_m4_v3(viewmat, lamp->dynco); - } - - if (material->dynproperty & DYN_LAMP_IMAT) { - mult_m4_m4m4(lamp->dynimat, lamp->imat, viewinv); - } - - if (material->dynproperty & DYN_LAMP_PERSMAT) { - if (!GPU_lamp_has_shadow_buffer(lamp)) /* The lamp matrices are already updated if we're using shadow buffers */ - GPU_lamp_update_buffer_mats(lamp); - mult_m4_m4m4(lamp->dynpersmat, lamp->persmat, viewinv); - } - } } } diff --git a/source/blender/gpu/shaders/gpu_shader_material.glsl b/source/blender/gpu/shaders/gpu_shader_material.glsl index 147d002475b..08747b19df2 100644 --- a/source/blender/gpu/shaders/gpu_shader_material.glsl +++ b/source/blender/gpu/shaders/gpu_shader_material.glsl @@ -2074,6 +2074,11 @@ void node_bsdf_velvet(vec4 color, float sigma, vec3 N, out vec4 result) node_bsdf_diffuse(color, 0.0, N, result); } +void node_subsurface_scattering(vec4 color, float roughness, vec3 N, out vec4 result) +{ + node_bsdf_diffuse(color, 0.0, N, result); +} + /* emission */ void node_emission(vec4 color, float strength, vec3 N, out vec4 result) diff --git a/source/blender/imbuf/IMB_colormanagement.h b/source/blender/imbuf/IMB_colormanagement.h index 473bd7d0c7a..58b55b0f137 100644 --- a/source/blender/imbuf/IMB_colormanagement.h +++ b/source/blender/imbuf/IMB_colormanagement.h @@ -28,8 +28,8 @@ * */ -#ifndef IMB_COLORMANAGEMENT_H -#define IMB_COLORMANAGEMENT_H +#ifndef __IMB_COLORMANAGEMENT_H__ +#define __IMB_COLORMANAGEMENT_H__ #define BCM_CONFIG_FILE "config.ocio" @@ -150,11 +150,26 @@ void IMB_colormanagement_processor_free(struct ColormanageProcessor *cm_processo /* ** OpenGL drawing routines using GLSL for color space transform ** */ -int IMB_coloemanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings, - const struct ColorManagedDisplaySettings *display_settings); - -int IMB_coloemanagement_setup_glsl_draw_from_ctx(const struct bContext *C); -void IMB_coloemanagement_finish_glsl_draw(void); +/* Configures GLSL shader for conversion from scene linear to display space */ +int IMB_colormanagement_setup_glsl_draw(const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + int predivide); +/* Same as above, but display space conversion happens from a specified space */ +int IMB_colormanagement_setup_glsl_draw_from_space(const struct ColorManagedViewSettings *view_settings, + const struct ColorManagedDisplaySettings *display_settings, + struct ColorSpace *colorspace, + int predivide); +/* Same as setup_glsl_draw, but color management settings are guessing from a given context */ +int IMB_colormanagement_setup_glsl_draw_ctx(const struct bContext *C, int predivide); +/* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ +int IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *colorspace, int predivide); +/* Finish GLSL-based display space conversion */ +void IMB_colormanagement_finish_glsl_draw(void); + +/* Configures GLSL shader for conversion from space defined by role to scene linear space */ +int IMB_colormanagement_setup_transform_from_role_glsl(int role, int predivide); +/* Finish GLSL-based color space conversion */ +void IMB_colormanagement_finish_glsl_transform(void); /* Roles */ enum { @@ -166,4 +181,4 @@ enum { COLOR_ROLE_DEFAULT_FLOAT, }; -#endif /* IMB_COLORMANAGEMENT_H */ +#endif /* __IMB_COLORMANAGEMENT_H__ */ diff --git a/source/blender/imbuf/intern/colormanagement.c b/source/blender/imbuf/intern/colormanagement.c index 95f67b9b21d..a74f28e79c9 100644 --- a/source/blender/imbuf/intern/colormanagement.c +++ b/source/blender/imbuf/intern/colormanagement.c @@ -109,10 +109,12 @@ static struct global_glsl_state { /* Settings of processor for comparison. */ char view[MAX_COLORSPACE_NAME]; char display[MAX_COLORSPACE_NAME]; + char input[MAX_COLORSPACE_NAME]; float exposure, gamma; /* Container for GLSL state needed for OCIO module. */ struct OCIO_GLSLDrawState *ocio_glsl_state; + struct OCIO_GLSLDrawState *transform_ocio_glsl_state; } global_glsl_state; /*********************** Color managed cache *************************/ @@ -626,6 +628,9 @@ void colormanagement_exit(void) if (global_glsl_state.ocio_glsl_state) OCIO_freeOGLState(global_glsl_state.ocio_glsl_state); + if (global_glsl_state.transform_ocio_glsl_state) + OCIO_freeOGLState(global_glsl_state.transform_ocio_glsl_state); + colormanage_free_config(); } @@ -699,8 +704,10 @@ static ColorSpace *display_transform_get_colorspace(const ColorManagedViewSettin return NULL; } -static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, const char *display, - float exposure, float gamma) +static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *view_transform, + const char *display, + float exposure, float gamma, + const char *from_colorspace) { OCIO_ConstConfigRcPtr *config = OCIO_getCurrentConfig(); OCIO_DisplayTransformRcPtr *dt; @@ -708,8 +715,7 @@ static OCIO_ConstProcessorRcPtr *create_display_buffer_processor(const char *vie dt = OCIO_createDisplayTransform(); - /* assuming handling buffer was already converted to scene linear space */ - OCIO_displayTransformSetInputColorSpaceName(dt, global_role_scene_linear); + OCIO_displayTransformSetInputColorSpaceName(dt, from_colorspace); OCIO_displayTransformSetView(dt, view_transform); OCIO_displayTransformSetDisplay(dt, display); @@ -1843,10 +1849,10 @@ static void imbuf_verify_float(ImBuf *ibuf) */ BLI_lock_thread(LOCK_COLORMANAGE); - if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & IB_RECT_INVALID))) { + if (ibuf->rect_float && (ibuf->rect == NULL || (ibuf->userflags & (IB_DISPLAY_BUFFER_INVALID | IB_RECT_INVALID)))) { IMB_rect_from_float(ibuf); - ibuf->userflags &= ~IB_RECT_INVALID; + ibuf->userflags &= ~(IB_RECT_INVALID | IB_DISPLAY_BUFFER_INVALID); } BLI_unlock_thread(LOCK_COLORMANAGE); @@ -2617,7 +2623,8 @@ ColormanageProcessor *IMB_colormanagement_display_processor_new(const ColorManag cm_processor->is_data_result = display_space->is_data; cm_processor->processor = create_display_buffer_processor(applied_view_settings->view_transform, display_settings->display_device, - applied_view_settings->exposure, applied_view_settings->gamma); + applied_view_settings->exposure, applied_view_settings->gamma, + global_role_scene_linear); if (applied_view_settings->flag & COLORMANAGE_VIEW_USE_CURVES) { cm_processor->curve_mapping = curvemapping_copy(applied_view_settings->curve_mapping); @@ -2714,26 +2721,30 @@ void IMB_colormanagement_processor_free(ColormanageProcessor *cm_processor) /* **** OpenGL drawing routines using GLSL for color space transform ***** */ static bool check_glsl_display_processor_changed(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) + const ColorManagedDisplaySettings *display_settings, + const char *from_colorspace) { return !(global_glsl_state.exposure == view_settings->exposure && global_glsl_state.gamma == view_settings->gamma && STREQ(global_glsl_state.view, view_settings->view_transform) && - STREQ(global_glsl_state.display, display_settings->display_device)); + STREQ(global_glsl_state.display, display_settings->display_device) && + STREQ(global_glsl_state.input, from_colorspace)); } static void update_glsl_display_processor(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) + const ColorManagedDisplaySettings *display_settings, + const char *from_colorspace) { /* Update state if there's no processor yet or * processor settings has been changed. */ if (global_glsl_state.processor == NULL || - check_glsl_display_processor_changed(view_settings, display_settings)) + check_glsl_display_processor_changed(view_settings, display_settings, from_colorspace)) { /* Store settings of processor for further comparison. */ strcpy(global_glsl_state.view, view_settings->view_transform); strcpy(global_glsl_state.display, display_settings->display_device); + strcpy(global_glsl_state.input, from_colorspace); global_glsl_state.exposure = view_settings->exposure; global_glsl_state.gamma = view_settings->gamma; @@ -2746,12 +2757,27 @@ static void update_glsl_display_processor(const ColorManagedViewSettings *view_s create_display_buffer_processor(global_glsl_state.view, global_glsl_state.display, global_glsl_state.exposure, - global_glsl_state.gamma); + global_glsl_state.gamma, + global_glsl_state.input); } } -int IMB_coloemanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings, - const ColorManagedDisplaySettings *display_settings) +/** + * Configures GLSL shader for conversion from specified to + * display color space + * + * Will create appropriate OCIO processor and setup GLSL shader, + * so further 2D texture usage will use this conversion. + * + * When there's no need to apply transform on 2D textures, use + * IMB_colormanagement_finish_glsl_draw(). + * + * This is low-level function, use glaDrawImBuf_glsl_ctx if you + * only need to display given image buffer + */ +int IMB_colormanagement_setup_glsl_draw_from_space(const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + struct ColorSpace *from_colorspace, int predivide) { ColorManagedViewSettings default_view_settings; const ColorManagedViewSettings *applied_view_settings; @@ -2773,24 +2799,73 @@ int IMB_coloemanagement_setup_glsl_draw(const ColorManagedViewSettings *view_set return FALSE; /* Make sure OCIO processor is up-to-date. */ - update_glsl_display_processor(applied_view_settings, display_settings); + update_glsl_display_processor(applied_view_settings, display_settings, + from_colorspace ? from_colorspace->name : global_role_scene_linear); - OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor); + return OCIO_setupGLSLDraw(&global_glsl_state.ocio_glsl_state, global_glsl_state.processor, predivide); +} - return TRUE; +/* Configures GLSL shader for conversion from scene linear to display space */ +int IMB_colormanagement_setup_glsl_draw(const ColorManagedViewSettings *view_settings, + const ColorManagedDisplaySettings *display_settings, + int predivide) +{ + return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, + NULL, predivide); } -int IMB_coloemanagement_setup_glsl_draw_from_ctx(const bContext *C) +/* Same as setup_glsl_draw_from_space, but color management settings are guessing from a given context */ +int IMB_colormanagement_setup_glsl_draw_from_space_ctx(const struct bContext *C, struct ColorSpace *from_colorspace, int predivide) { ColorManagedViewSettings *view_settings; ColorManagedDisplaySettings *display_settings; display_transform_get_from_ctx(C, &view_settings, &display_settings); - return IMB_coloemanagement_setup_glsl_draw(view_settings, display_settings); + return IMB_colormanagement_setup_glsl_draw_from_space(view_settings, display_settings, from_colorspace, predivide); } -void IMB_coloemanagement_finish_glsl_draw(void) +/* Same as setup_glsl_draw, but color management settings are guessing from a given context */ +int IMB_colormanagement_setup_glsl_draw_ctx(const bContext *C, int predivide) +{ + return IMB_colormanagement_setup_glsl_draw_from_space_ctx(C, NULL, predivide); +} + +/* Finish GLSL-based display space conversion */ +void IMB_colormanagement_finish_glsl_draw(void) { OCIO_finishGLSLDraw(global_glsl_state.ocio_glsl_state); } + +/* ** Color space conversion using GLSL shader ** */ + +/** + * Configures GLSL shader for conversion from space defined by role + * to scene linear space + * + * Will create appropriate OCIO processor and setup GLSL shader, + * so further 2D texture usage will use this conversion. + * + * Role is an pseudonym for a color space, see bottom of file + * IMB_colormanagement.h for list of available roles. + * + * When there's no need to apply transform on 2D textures, use + * IMB_colormanagement_finish_glsl_transform(). + */ +int IMB_colormanagement_setup_transform_from_role_glsl(int role, int predivide) +{ + OCIO_ConstProcessorRcPtr *processor; + ColorSpace *colorspace; + + colorspace = colormanage_colorspace_get_roled(role); + + processor = colorspace_to_scene_linear_processor(colorspace); + + return OCIO_setupGLSLDraw(&global_glsl_state.transform_ocio_glsl_state, processor, predivide); +} + +/* Finish GLSL-based color space conversion */ +void IMB_colormanagement_finish_glsl_transform(void) +{ + OCIO_finishGLSLDraw(global_glsl_state.transform_ocio_glsl_state); +} diff --git a/source/blender/imbuf/intern/divers.c b/source/blender/imbuf/intern/divers.c index 20d51fddb35..e69460de040 100644 --- a/source/blender/imbuf/intern/divers.c +++ b/source/blender/imbuf/intern/divers.c @@ -664,13 +664,13 @@ void IMB_float_from_rect(ImBuf *ibuf) /* no profile conversion */ void IMB_color_to_bw(ImBuf *ibuf) { - float *rctf = ibuf->rect_float; + float *rct_fl = ibuf->rect_float; uchar *rct = (uchar *)ibuf->rect; int i; - if (rctf) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rctf += 4) - rctf[0] = rctf[1] = rctf[2] = rgb_to_grayscale(rctf); + if (rct_fl) { + for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4) + rct_fl[0] = rct_fl[1] = rct_fl[2] = rgb_to_grayscale(rct_fl); } if (rct) { @@ -713,7 +713,7 @@ void IMB_saturation(ImBuf *ibuf, float sat) { int i; unsigned char *rct = (unsigned char *)ibuf->rect; - float *rctf = ibuf->rect_float; + float *rct_fl = ibuf->rect_float; float hsv[3]; if (rct) { @@ -726,10 +726,10 @@ void IMB_saturation(ImBuf *ibuf, float sat) } } - if (rctf) { - for (i = ibuf->x * ibuf->y; i > 0; i--, rctf += 4) { - rgb_to_hsv_v(rctf, hsv); - hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rctf, rctf + 1, rctf + 2); + if (rct_fl) { + for (i = ibuf->x * ibuf->y; i > 0; i--, rct_fl += 4) { + rgb_to_hsv_v(rct_fl, hsv); + hsv_to_rgb(hsv[0], hsv[1] * sat, hsv[2], rct_fl, rct_fl + 1, rct_fl + 2); } } } diff --git a/source/blender/makesdna/DNA_movieclip_types.h b/source/blender/makesdna/DNA_movieclip_types.h index 119d2cdfdf7..499f1c50155 100644 --- a/source/blender/makesdna/DNA_movieclip_types.h +++ b/source/blender/makesdna/DNA_movieclip_types.h @@ -98,11 +98,6 @@ typedef struct MovieClip { /* color management */ ColorManagedColorspaceSettings colorspace_settings; - - /* runtime prefetching stuff */ - char prefetch_ok; - - char pad[7]; } MovieClip; typedef struct MovieClipScopes { diff --git a/source/blender/makesrna/intern/rna_access.c b/source/blender/makesrna/intern/rna_access.c index 68a5ac5f639..00ee1b49da2 100644 --- a/source/blender/makesrna/intern/rna_access.c +++ b/source/blender/makesrna/intern/rna_access.c @@ -609,6 +609,9 @@ bool RNA_struct_is_a(StructRNA *type, StructRNA *srna) { StructRNA *base; + if (srna == &RNA_AnyType) + return true; + if (!type) return false; diff --git a/source/blender/makesrna/intern/rna_group.c b/source/blender/makesrna/intern/rna_group.c index 1ac59f9caed..45bb5c613d5 100644 --- a/source/blender/makesrna/intern/rna_group.c +++ b/source/blender/makesrna/intern/rna_group.c @@ -54,7 +54,7 @@ static PointerRNA rna_Group_objects_get(CollectionPropertyIterator *iter) static void rna_Group_objects_link(Group *group, bContext *C, ReportList *reports, Object *object) { - if (!add_to_group(group, object, CTX_data_scene(C), NULL)) { + if (!BKE_group_object_add(group, object, CTX_data_scene(C), NULL)) { BKE_reportf(reports, RPT_ERROR, "Object '%s' already in group '%s'", object->id.name + 2, group->id.name + 2); return; } @@ -64,7 +64,7 @@ static void rna_Group_objects_link(Group *group, bContext *C, ReportList *report static void rna_Group_objects_unlink(Group *group, bContext *C, ReportList *reports, Object *object) { - if (!rem_from_group(group, object, CTX_data_scene(C), NULL)) { + if (!BKE_group_object_unlink(group, object, CTX_data_scene(C), NULL)) { BKE_reportf(reports, RPT_ERROR, "Object '%s' not in group '%s'", object->id.name + 2, group->id.name + 2); return; } diff --git a/source/blender/makesrna/intern/rna_main_api.c b/source/blender/makesrna/intern/rna_main_api.c index fb0aeffcffb..d504585f738 100644 --- a/source/blender/makesrna/intern/rna_main_api.c +++ b/source/blender/makesrna/intern/rna_main_api.c @@ -681,7 +681,7 @@ static void rna_Main_worlds_remove(Main *bmain, ReportList *reports, PointerRNA static Group *rna_Main_groups_new(Main *bmain, const char *name) { - return add_group(bmain, name); + return BKE_group_add(bmain, name); } static void rna_Main_groups_remove(Main *bmain, PointerRNA *group_ptr) { diff --git a/source/blender/makesrna/intern/rna_movieclip.c b/source/blender/makesrna/intern/rna_movieclip.c index cc3d5e5ca5e..9b2bcab4604 100644 --- a/source/blender/makesrna/intern/rna_movieclip.c +++ b/source/blender/makesrna/intern/rna_movieclip.c @@ -49,6 +49,11 @@ #include "BKE_depsgraph.h" +#include "ED_clip.h" + +#include "DNA_screen_types.h" +#include "DNA_space_types.h" + static void rna_MovieClip_reload_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) { MovieClip *clip = (MovieClip *)ptr->id.data; @@ -65,6 +70,39 @@ static void rna_MovieClip_size_get(PointerRNA *ptr, int *values) values[1] = clip->lastsize[1]; } +static void rna_MovieClipUser_proxy_render_settings_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr) +{ + ID *id = (ID *) ptr->id.data; + MovieClipUser *user = (MovieClipUser *) ptr->data; + + /* when changing render settings of space clip user + * clear cache for clip, so all the memory is available + * for new render settings + */ + if (GS(id->name) == ID_SCR) { + bScreen *screen = (bScreen *) id; + ScrArea *area; + SpaceLink *sl; + + for (area = screen->areabase.first; area; area = area->next) { + for (sl = area->spacedata.first; sl; sl = sl->next) { + if (sl->spacetype == SPACE_CLIP) { + SpaceClip *sc = (SpaceClip *) sl; + + if (&sc->user == user) { + MovieClip *clip = ED_space_clip_get_clip(sc); + + if (clip && (clip->flag & MCLIP_USE_PROXY)) + BKE_movieclip_clear_cache(clip); + + break; + } + } + } + } + } +} + #else static void rna_def_movieclip_proxy(BlenderRNA *brna) @@ -197,13 +235,13 @@ static void rna_def_moviecliUser(BlenderRNA *brna) RNA_def_property_enum_items(prop, clip_render_size_items); RNA_def_property_ui_text(prop, "Proxy render size", "Draw preview using full resolution or different proxy resolutions"); - RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClipUser_proxy_render_settings_update"); /* render undistorted */ prop = RNA_def_property(srna, "use_render_undistorted", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "render_flag", MCLIP_PROXY_RENDER_UNDISTORT); RNA_def_property_ui_text(prop, "Render Undistorted", "Render preview using undistorted proxy"); - RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, NULL); + RNA_def_property_update(prop, NC_MOVIECLIP | ND_DISPLAY, "rna_MovieClipUser_proxy_render_settings_update"); } static void rna_def_movieClipScopes(BlenderRNA *brna) diff --git a/source/blender/makesrna/intern/rna_object.c b/source/blender/makesrna/intern/rna_object.c index 594b86f000c..0c01d03888d 100644 --- a/source/blender/makesrna/intern/rna_object.c +++ b/source/blender/makesrna/intern/rna_object.c @@ -43,7 +43,7 @@ #include "BKE_paint.h" #include "BKE_tessmesh.h" -#include "BKE_group.h" /* needed for object_in_group() */ +#include "BKE_group.h" /* needed for BKE_group_object_exists() */ #include "RNA_access.h" #include "RNA_define.h" @@ -520,7 +520,7 @@ static void rna_Object_dup_group_set(PointerRNA *ptr, PointerRNA value) /* must not let this be set if the object belongs in this group already, * thus causing a cycle/infinite-recursion leading to crashes on load [#25298] */ - if (object_in_group(ob, grp) == 0) + if (BKE_group_object_exists(grp, ob) == 0) ob->dup_group = grp; else BKE_report(NULL, RPT_ERROR, diff --git a/source/blender/makesrna/intern/rna_space.c b/source/blender/makesrna/intern/rna_space.c index 309de9c7fd1..e036bb1c999 100644 --- a/source/blender/makesrna/intern/rna_space.c +++ b/source/blender/makesrna/intern/rna_space.c @@ -536,6 +536,21 @@ static void rna_RegionView3D_update(ID *id, RegionView3D *rv3d) } } +static int rna_SpaceView3D_viewport_shade_get(PointerRNA *ptr) +{ + Scene *scene = ((bScreen *)ptr->id.data)->scene; + RenderEngineType *type = RE_engines_find(scene->r.engine); + View3D *v3d = (View3D *)ptr->data; + int drawtype = v3d->drawtype; + + if (drawtype == OB_MATERIAL && !BKE_scene_use_new_shading_nodes(scene)) + return OB_SOLID; + else if (drawtype == OB_RENDER && !(type && type->view_draw)) + return OB_SOLID; + + return drawtype; +} + static EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C), PointerRNA *ptr, PropertyRNA *UNUSED(prop), int *free) { @@ -553,7 +568,7 @@ static EnumPropertyItem *rna_SpaceView3D_viewport_shade_itemf(bContext *UNUSED(C if (BKE_scene_use_new_shading_nodes(scene)) RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_MATERIAL); - if (type->view_draw) + if (type && type->view_draw) RNA_enum_items_add_value(&item, &totitem, viewport_shade_items, OB_RENDER); RNA_enum_item_end(&item, &totitem); @@ -1696,7 +1711,7 @@ static void rna_def_space_view3d(BlenderRNA *brna) prop = RNA_def_property(srna, "viewport_shade", PROP_ENUM, PROP_NONE); RNA_def_property_enum_sdna(prop, NULL, "drawtype"); RNA_def_property_enum_items(prop, viewport_shade_items); - RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_SpaceView3D_viewport_shade_itemf"); + RNA_def_property_enum_funcs(prop, "rna_SpaceView3D_viewport_shade_get", NULL, "rna_SpaceView3D_viewport_shade_itemf"); RNA_def_property_ui_text(prop, "Viewport Shading", "Method to display/shade objects in the 3D View"); RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_SpaceView3D_viewport_shade_update"); diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c index b2f17bfed8b..9c354e7f70e 100644 --- a/source/blender/makesrna/intern/rna_ui_api.c +++ b/source/blender/makesrna/intern/rna_ui_api.c @@ -269,7 +269,7 @@ static void rna_uiTemplatePathBuilder(uiLayout *layout, PointerRNA *ptr, const c static int rna_ui_get_rnaptr_icon(bContext *C, PointerRNA *ptr_icon) { - return UI_rnaptr_icon_get(C, ptr_icon, RNA_struct_ui_icon(ptr_icon->type), FALSE); + return UI_rnaptr_icon_get(C, ptr_icon, RNA_struct_ui_icon(ptr_icon->type), false); } static const char *rna_ui_get_enum_name(bContext *C, PointerRNA *ptr, const char *propname, const char *identifier) diff --git a/source/blender/nodes/CMakeLists.txt b/source/blender/nodes/CMakeLists.txt index f3b3d6b1f53..f2ce9665e2b 100644 --- a/source/blender/nodes/CMakeLists.txt +++ b/source/blender/nodes/CMakeLists.txt @@ -175,6 +175,7 @@ set(SRC shader/nodes/node_shader_output_world.c shader/nodes/node_shader_particle_info.c shader/nodes/node_shader_script.c + shader/nodes/node_shader_subsurface_scattering.c shader/nodes/node_shader_tangent.c shader/nodes/node_shader_tex_brick.c shader/nodes/node_shader_tex_checker.c diff --git a/source/blender/nodes/NOD_composite.h b/source/blender/nodes/NOD_composite.h index f272ec670e7..896714338e5 100644 --- a/source/blender/nodes/NOD_composite.h +++ b/source/blender/nodes/NOD_composite.h @@ -52,7 +52,6 @@ void register_node_type_cmp_value(void); void register_node_type_cmp_rgb(void); void register_node_type_cmp_curve_time(void); void register_node_type_cmp_movieclip(void); -void register_node_type_cmp_usermask(struct bNodeTreeType *ttype); void register_node_type_cmp_composite(void); void register_node_type_cmp_viewer(void); diff --git a/source/blender/nodes/NOD_shader.h b/source/blender/nodes/NOD_shader.h index 9561fe00409..eb324182e39 100644 --- a/source/blender/nodes/NOD_shader.h +++ b/source/blender/nodes/NOD_shader.h @@ -101,6 +101,7 @@ void register_node_type_sh_emission(void); void register_node_type_sh_holdout(void); void register_node_type_sh_volume_transparent(void); void register_node_type_sh_volume_isotropic(void); +void register_node_type_sh_subsurface_scattering(void); void register_node_type_sh_mix_shader(void); void register_node_type_sh_add_shader(void); diff --git a/source/blender/nodes/NOD_static_types.h b/source/blender/nodes/NOD_static_types.h index 9d044772274..811cd3f3b4a 100644 --- a/source/blender/nodes/NOD_static_types.h +++ b/source/blender/nodes/NOD_static_types.h @@ -84,6 +84,7 @@ DefNode( ShaderNode, SH_NODE_BSDF_REFRACTION, def_glossy, "BS DefNode( ShaderNode, SH_NODE_BSDF_TRANSLUCENT, 0, "BSDF_TRANSLUCENT", BsdfTranslucent, "Translucent BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_TRANSPARENT, 0, "BSDF_TRANSPARENT", BsdfTransparent, "Transparent BSDF", "" ) DefNode( ShaderNode, SH_NODE_BSDF_VELVET, 0, "BSDF_VELVET", BsdfVelvet, "Velvet BSDF", "" ) +DefNode( ShaderNode, SH_NODE_SUBSURFACE_SCATTERING, 0, "SUBSURFACE_SCATTERING",SubsurfaceScattering,"Subsurface Scattering","") DefNode( ShaderNode, SH_NODE_VOLUME_TRANSPARENT, 0, "VOLUME_TRANSPARENT", VolumeTransparent,"Transparent Volume","" ) DefNode( ShaderNode, SH_NODE_VOLUME_ISOTROPIC, 0, "VOLUME_ISOTROPIC", VolumeIsotropic, "Isotropic Volume", "" ) DefNode( ShaderNode, SH_NODE_EMISSION, 0, "EMISSION", Emission, "Emission", "" ) diff --git a/source/blender/nodes/composite/nodes/node_composite_common.c b/source/blender/nodes/composite/nodes/node_composite_common.c index 44643724073..df1c5d3316b 100644 --- a/source/blender/nodes/composite/nodes/node_composite_common.c +++ b/source/blender/nodes/composite/nodes/node_composite_common.c @@ -51,6 +51,7 @@ void register_node_type_cmp_group(void) node_type_base_custom(&ntype, "CompositorNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT); ntype.type = NODE_GROUP; ntype.poll = cmp_node_poll_default; + ntype.poll_instance = node_group_poll_instance; ntype.update_internal_links = node_update_internal_links_default; ntype.ext.srna = RNA_struct_find("CompositorNodeGroup"); BLI_assert(ntype.ext.srna != NULL); diff --git a/source/blender/nodes/intern/node_common.c b/source/blender/nodes/intern/node_common.c index 4e4443f7c3f..24f35cc81af 100644 --- a/source/blender/nodes/intern/node_common.c +++ b/source/blender/nodes/intern/node_common.c @@ -89,11 +89,15 @@ const char *node_group_label(bNode *node) int node_group_poll_instance(bNode *node, bNodeTree *nodetree) { - bNodeTree *grouptree = (bNodeTree*)node->id; - if (grouptree) - return nodeGroupPoll(nodetree, grouptree); + if (node->typeinfo->poll(node->typeinfo, nodetree)) { + bNodeTree *grouptree = (bNodeTree*)node->id; + if (grouptree) + return nodeGroupPoll(nodetree, grouptree); + else + return TRUE; /* without a linked node tree, group node is always ok */ + } else - return 1; + return FALSE; } int nodeGroupPoll(bNodeTree *nodetree, bNodeTree *grouptree) diff --git a/source/blender/nodes/intern/node_socket.c b/source/blender/nodes/intern/node_socket.c index 74d44fe5f53..f28d6a20dab 100644 --- a/source/blender/nodes/intern/node_socket.c +++ b/source/blender/nodes/intern/node_socket.c @@ -420,6 +420,9 @@ static bNodeSocketType *make_socket_type_virtual(void) /* associate the RNA type with the socket type */ RNA_struct_blender_type_set(srna, stype); + /* extra type info for standard socket types */ + stype->type = SOCK_CUSTOM; + ED_init_node_socket_type_virtual(stype); return stype; diff --git a/source/blender/nodes/shader/node_shader_util.h b/source/blender/nodes/shader/node_shader_util.h index 57b129335bb..cfd97ab0d9e 100644 --- a/source/blender/nodes/shader/node_shader_util.h +++ b/source/blender/nodes/shader/node_shader_util.h @@ -92,7 +92,6 @@ typedef struct ShaderCallData { } ShaderCallData; -extern void node_ID_title_cb(void *node_v, void *unused_v); void nodestack_get_vec(float *in, short type_in, bNodeStack *ns); void node_gpu_stack_from_data(struct GPUNodeStack *gs, int type, struct bNodeStack *ns); diff --git a/source/blender/nodes/shader/nodes/node_shader_common.c b/source/blender/nodes/shader/nodes/node_shader_common.c index 155aa508ed9..cd2953c839a 100644 --- a/source/blender/nodes/shader/nodes/node_shader_common.c +++ b/source/blender/nodes/shader/nodes/node_shader_common.c @@ -231,6 +231,7 @@ void register_node_type_sh_group(void) node_type_base_custom(&ntype, "ShaderNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT); ntype.type = NODE_GROUP; ntype.poll = sh_node_poll_default; + ntype.poll_instance = node_group_poll_instance; ntype.update_internal_links = node_update_internal_links_default; ntype.ext.srna = RNA_struct_find("ShaderNodeGroup"); BLI_assert(ntype.ext.srna != NULL); diff --git a/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c new file mode 100644 index 00000000000..cde6ec8be45 --- /dev/null +++ b/source/blender/nodes/shader/nodes/node_shader_subsurface_scattering.c @@ -0,0 +1,69 @@ +/* + * ***** 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) 2005 Blender Foundation. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#include "../node_shader_util.h" + +/* **************** OUTPUT ******************** */ + +static bNodeSocketTemplate sh_node_subsurface_scattering_in[] = { + { SOCK_RGBA, 1, N_("Color"), 0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f}, + { SOCK_FLOAT, 1, N_("Scale"), 1.0, 0.0f, 0.0f, 0.0f, 0.0f, 1000000.0f}, + { SOCK_VECTOR, 1, N_("Radius"), 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f}, + //{ SOCK_FLOAT, 1, N_("IOR"), 1.3f, 0.0f, 0.0f, 0.0f, 1.0f, 1000.0f}, + { SOCK_VECTOR, 1, N_("Normal"), 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f, PROP_NONE, SOCK_HIDE_VALUE}, + { -1, 0, "" } +}; + +static bNodeSocketTemplate sh_node_subsurface_scattering_out[] = { + { SOCK_SHADER, 0, N_("BSSRDF")}, + { -1, 0, "" } +}; + +static int node_shader_gpu_subsurface_scattering(GPUMaterial *mat, bNode *UNUSED(node), bNodeExecData *UNUSED(execdata), GPUNodeStack *in, GPUNodeStack *out) +{ + if (!in[1].link) + in[1].link = GPU_builtin(GPU_VIEW_NORMAL); + + return GPU_stack_link(mat, "node_subsurface_scattering", in, out); +} + +/* node type definition */ +void register_node_type_sh_subsurface_scattering(void) +{ + static bNodeType ntype; + + sh_node_type_base(&ntype, SH_NODE_SUBSURFACE_SCATTERING, "Subsurface Scattering", NODE_CLASS_SHADER, 0); + node_type_compatibility(&ntype, NODE_NEW_SHADING); + node_type_socket_templates(&ntype, sh_node_subsurface_scattering_in, sh_node_subsurface_scattering_out); + node_type_size(&ntype, 150, 60, 200); + node_type_init(&ntype, NULL); + node_type_storage(&ntype, "", NULL, NULL); + node_type_gpu(&ntype, node_shader_gpu_subsurface_scattering); + + nodeRegisterType(&ntype); +} + diff --git a/source/blender/nodes/texture/nodes/node_texture_common.c b/source/blender/nodes/texture/nodes/node_texture_common.c index e884d50dc05..ee03323fb5d 100644 --- a/source/blender/nodes/texture/nodes/node_texture_common.c +++ b/source/blender/nodes/texture/nodes/node_texture_common.c @@ -159,6 +159,7 @@ void register_node_type_tex_group(void) node_type_base_custom(&ntype, "TextureNodeGroup", "Group", NODE_CLASS_GROUP, NODE_OPTIONS | NODE_CONST_OUTPUT); ntype.type = NODE_GROUP; ntype.poll = tex_node_poll_default; + ntype.poll_instance = node_group_poll_instance; ntype.update_internal_links = node_update_internal_links_default; ntype.ext.srna = RNA_struct_find("TextureNodeGroup"); BLI_assert(ntype.ext.srna != NULL); diff --git a/source/blender/python/intern/bpy_rna.c b/source/blender/python/intern/bpy_rna.c index 735df7aeb10..d6a82ce43ea 100644 --- a/source/blender/python/intern/bpy_rna.c +++ b/source/blender/python/intern/bpy_rna.c @@ -1778,8 +1778,10 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb if (flag & PROP_THICK_WRAP) { if (value == Py_None) memset(data, 0, sizeof(PointerRNA)); - else + else if (RNA_struct_is_a(param->ptr.type, ptr_type)) *((PointerRNA *)data) = param->ptr; + else + raise_error = true; } else { /* for function calls, we sometimes want to pass the 'ptr' directly, @@ -1787,8 +1789,10 @@ static int pyrna_py_to_prop(PointerRNA *ptr, PropertyRNA *prop, void *data, PyOb BLI_assert(value_new == NULL); if (value == Py_None) *((void **)data) = NULL; - else + else if (RNA_struct_is_a(param->ptr.type, ptr_type)) *((PointerRNA **)data) = ¶m->ptr; + else + raise_error = true; } } else if (value == Py_None) { diff --git a/source/blender/render/extern/include/RE_pipeline.h b/source/blender/render/extern/include/RE_pipeline.h index 2bcd39ab71b..96106296443 100644 --- a/source/blender/render/extern/include/RE_pipeline.h +++ b/source/blender/render/extern/include/RE_pipeline.h @@ -158,9 +158,6 @@ typedef struct RenderStats { struct Render *RE_NewRender (const char *name); struct Render *RE_GetRender(const char *name); -/* returns 1 while render is working (or renders called from within render) */ -int RE_RenderInProgress(struct Render *re); - /* assign default dummy callbacks */ void RE_InitRenderCB(struct Render *re); diff --git a/source/blender/render/extern/include/RE_render_ext.h b/source/blender/render/extern/include/RE_render_ext.h index 2dfbdd0d6f5..eb861d440d8 100644 --- a/source/blender/render/extern/include/RE_render_ext.h +++ b/source/blender/render/extern/include/RE_render_ext.h @@ -37,20 +37,12 @@ /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ /* called by meshtools */ -struct View3D; -struct Scene; +struct DerivedMesh; +struct ImagePool; struct LinkNode; - -void RE_make_sticky(struct Scene *scene, struct Object *camera, struct LinkNode *objects); - -/* for radiosity module */ -struct RadView; -struct RNode; -struct Render; struct MTex; -struct ImBuf; -struct ImagePool; -struct DerivedMesh; +struct Scene; +struct View3D; /* particle.c, effect.c, editmesh_modes.c and brush.c, returns 1 if rgb, 0 otherwise */ int externtex(struct MTex *mtex, const float vec[3], float *tin, float *tr, float *tg, float *tb, float *ta, const int thread, struct ImagePool *pool); diff --git a/source/blender/render/intern/source/shadeoutput.c b/source/blender/render/intern/source/shadeoutput.c index 003e74bd69a..7505b0fa567 100644 --- a/source/blender/render/intern/source/shadeoutput.c +++ b/source/blender/render/intern/source/shadeoutput.c @@ -1743,15 +1743,15 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) shr->col[0]= shr->col[1]= shr->col[2]= shr->col[3]= 1.0f; } else { - shi->r= pow(shi->r, ma->sss_texfac); - shi->g= pow(shi->g, ma->sss_texfac); - shi->b= pow(shi->b, ma->sss_texfac); - shi->alpha= pow(shi->alpha, ma->sss_texfac); + shi->r= pow(max_ff(shi->r, 0.0f), ma->sss_texfac); + shi->g= pow(max_ff(shi->g, 0.0f), ma->sss_texfac); + shi->b= pow(max_ff(shi->b, 0.0f), ma->sss_texfac); + shi->alpha= pow(max_ff(shi->alpha, 0.0f), ma->sss_texfac); - shr->col[0]= pow(shr->col[0], ma->sss_texfac); - shr->col[1]= pow(shr->col[1], ma->sss_texfac); - shr->col[2]= pow(shr->col[2], ma->sss_texfac); - shr->col[3]= pow(shr->col[3], ma->sss_texfac); + shr->col[0]= pow(max_ff(shr->col[0], 0.0f), ma->sss_texfac); + shr->col[1]= pow(max_ff(shr->col[1], 0.0f), ma->sss_texfac); + shr->col[2]= pow(max_ff(shr->col[2], 0.0f), ma->sss_texfac); + shr->col[3]= pow(max_ff(shr->col[3], 0.0f), ma->sss_texfac); } } } @@ -1841,9 +1841,9 @@ void shade_lamp_loop(ShadeInput *shi, ShadeResult *shr) else { copy_v3_v3(col, shr->col); mul_v3_fl(col, invalpha); - col[0]= pow(col[0], 1.0f-texfac); - col[1]= pow(col[1], 1.0f-texfac); - col[2]= pow(col[2], 1.0f-texfac); + col[0]= pow(max_ff(col[0], 0.0f), 1.0f-texfac); + col[1]= pow(max_ff(col[1], 0.0f), 1.0f-texfac); + col[2]= pow(max_ff(col[2], 0.0f), 1.0f-texfac); } shr->diff[0]= sss[0]*col[0]; diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index 25c8c5db0a1..2af513cebe6 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -70,7 +70,7 @@ typedef struct wmJob wmJob; void WM_init_state_size_set (int stax, int stay, int sizx, int sizy); void WM_init_state_fullscreen_set(void); void WM_init_state_normal_set(void); -void WM_init_native_pixels(int do_it); +void WM_init_native_pixels(bool do_it); void WM_init (struct bContext *C, int argc, const char **argv); void WM_exit_ext (struct bContext *C, const short do_python); @@ -87,7 +87,7 @@ __attribute__((noreturn)) #endif ; -int WM_init_game (struct bContext *C); +bool WM_init_game (struct bContext *C); void WM_init_splash (struct bContext *C); @@ -106,7 +106,7 @@ int WM_window_pixels_y (struct wmWindow *win); void WM_window_open_temp (struct bContext *C, struct rcti *position, int type); /* returns true if draw method is triple buffer */ -int WM_is_draw_triple(struct wmWindow *win); +bool WM_is_draw_triple(struct wmWindow *win); @@ -118,7 +118,7 @@ void WM_autosave_init(struct wmWindowManager *wm); void WM_cursor_set (struct wmWindow *win, int curs); void WM_cursor_modal (struct wmWindow *win, int curs); void WM_cursor_restore (struct wmWindow *win); -void WM_cursor_wait (int val); +void WM_cursor_wait (bool val); void WM_cursor_grab_enable(struct wmWindow *win, int wrap, int hide, int bounds[4]); void WM_cursor_grab_disable(struct wmWindow *win, int mouse_ungrab_xy[2]); void WM_cursor_time (struct wmWindow *win, int nr); @@ -204,7 +204,7 @@ void WM_operator_free (struct wmOperator *op); void WM_operator_stack_clear(struct wmWindowManager *wm); void WM_operator_handlers_clear(wmWindowManager *wm, struct wmOperatorType *ot); -struct wmOperatorType *WM_operatortype_find(const char *idnamem, int quiet); +struct wmOperatorType *WM_operatortype_find(const char *idnamem, bool quiet); struct GHashIterator *WM_operatortype_iter(void); void WM_operatortype_append(void (*opfunc)(struct wmOperatorType *)); void WM_operatortype_append_ptr(void (*opfunc)(struct wmOperatorType *, void *), void *userdata); @@ -225,8 +225,8 @@ int WM_operator_name_call (struct bContext *C, const char *opstring, short con int WM_operator_call_py(struct bContext *C, struct wmOperatorType *ot, short context, struct PointerRNA *properties, struct ReportList *reports, short is_undo); void WM_operator_properties_alloc(struct PointerRNA **ptr, struct IDProperty **properties, const char *opstring); /* used for keymap and macro items */ -void WM_operator_properties_sanitize(struct PointerRNA *ptr, const short no_context); /* make props context sensitive or not */ -int WM_operator_properties_default(struct PointerRNA *ptr, const int do_update); +void WM_operator_properties_sanitize(struct PointerRNA *ptr, const bool no_context); /* make props context sensitive or not */ +int WM_operator_properties_default(struct PointerRNA *ptr, const bool do_update); void WM_operator_properties_reset(struct wmOperator *op); void WM_operator_properties_create(struct PointerRNA *ptr, const char *opstring); void WM_operator_properties_create_ptr(struct PointerRNA *ptr, struct wmOperatorType *ot); @@ -239,11 +239,11 @@ void WM_operator_properties_mouse_select(struct wmOperatorType *ot); void WM_operator_properties_gesture_straightline(struct wmOperatorType *ot, bool cursor); void WM_operator_properties_select_all(struct wmOperatorType *ot); -int WM_operator_check_ui_enabled(const struct bContext *C, const char *idname); +bool WM_operator_check_ui_enabled(const struct bContext *C, const char *idname); wmOperator *WM_operator_last_redo(const struct bContext *C); -int WM_operator_last_properties_init(struct wmOperator *op); -int WM_operator_last_properties_store(struct wmOperator *op); +bool WM_operator_last_properties_init(struct wmOperator *op); +bool WM_operator_last_properties_store(struct wmOperator *op); /* MOVE THIS SOMEWHERE ELSE */ #define SEL_TOGGLE 0 @@ -269,14 +269,14 @@ void WM_operator_py_idname(char *to, const char *from); /* *************** uilist types ******************** */ void WM_uilisttype_init(void); -struct uiListType *WM_uilisttype_find(const char *idname, int quiet); +struct uiListType *WM_uilisttype_find(const char *idname, bool quiet); int WM_uilisttype_add(struct uiListType *ult); void WM_uilisttype_freelink(struct uiListType *ult); void WM_uilisttype_free(void); /* *************** menu types ******************** */ void WM_menutype_init(void); -struct MenuType *WM_menutype_find(const char *idname, int quiet); +struct MenuType *WM_menutype_find(const char *idname, bool quiet); int WM_menutype_add(struct MenuType *mt); void WM_menutype_freelink(struct MenuType *mt); void WM_menutype_free(void); diff --git a/source/blender/windowmanager/intern/wm.c b/source/blender/windowmanager/intern/wm.c index 29e0fcf302f..f7b7aa87cf8 100644 --- a/source/blender/windowmanager/intern/wm.c +++ b/source/blender/windowmanager/intern/wm.c @@ -179,7 +179,7 @@ void WM_operator_handlers_clear(wmWindowManager *wm, wmOperatorType *ot) static GHash *uilisttypes_hash = NULL; -uiListType *WM_uilisttype_find(const char *idname, int quiet) +uiListType *WM_uilisttype_find(const char *idname, bool quiet) { uiListType *ult; @@ -234,7 +234,7 @@ void WM_uilisttype_free(void) static GHash *menutypes_hash = NULL; -MenuType *WM_menutype_find(const char *idname, int quiet) +MenuType *WM_menutype_find(const char *idname, bool quiet) { MenuType *mt; diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c index 2e15d6158e8..f8081cb8012 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -164,7 +164,7 @@ void WM_cursor_restore(wmWindow *win) } /* to allow usage all over, we do entire WM */ -void WM_cursor_wait(int val) +void WM_cursor_wait(bool val) { if (!G.background) { wmWindowManager *wm = G.main->wm.first; diff --git a/source/blender/windowmanager/intern/wm_dragdrop.c b/source/blender/windowmanager/intern/wm_dragdrop.c index ed066117b28..0c78338c18a 100644 --- a/source/blender/windowmanager/intern/wm_dragdrop.c +++ b/source/blender/windowmanager/intern/wm_dragdrop.c @@ -323,7 +323,7 @@ void wm_drags_draw(bContext *C, wmWindow *win, rcti *rect) drag_rect_minmax(rect, x, y, x + drag->sx, y + drag->sy); else { glColor4f(1.0, 1.0, 1.0, 0.65); /* this blends texture */ - glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_UNSIGNED_BYTE, GL_NEAREST, drag->imb->rect, drag->scale, drag->scale); + glaDrawPixelsTexScaled(x, y, drag->imb->x, drag->imb->y, GL_RGBA, GL_UNSIGNED_BYTE, GL_NEAREST, drag->imb->rect, drag->scale, drag->scale); } } else { diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c index 173a8237c02..1e3c2479e66 100644 --- a/source/blender/windowmanager/intern/wm_draw.c +++ b/source/blender/windowmanager/intern/wm_draw.c @@ -769,12 +769,12 @@ static int wm_automatic_draw_method(wmWindow *win) return win->drawmethod; } -int WM_is_draw_triple(wmWindow *win) +bool WM_is_draw_triple(wmWindow *win) { /* function can get called before this variable is set in drawing code below */ if (win->drawmethod != U.wmdrawmethod) win->drawmethod = U.wmdrawmethod; - return USER_DRAW_TRIPLE == wm_automatic_draw_method(win); + return (USER_DRAW_TRIPLE == wm_automatic_draw_method(win)); } void wm_tag_redraw_overlay(wmWindow *win, ARegion *ar) diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index 6c129ec0a92..d7b642fc5cf 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -796,10 +796,10 @@ static void wm_region_mouse_co(bContext *C, wmEvent *event) } } -#if 1 /* disabling for 2.63 release, since we keep getting reports some menu items are leaving props undefined */ -int WM_operator_last_properties_init(wmOperator *op) +#if 1 /* may want to disable operator remembering previous state for testing */ +bool WM_operator_last_properties_init(wmOperator *op) { - int change = FALSE; + bool change = false; if (op->type->last_properties) { PropertyRNA *iterprop; @@ -825,7 +825,7 @@ int WM_operator_last_properties_init(wmOperator *op) idp_dst->flag |= IDP_FLAG_GHOST; IDP_ReplaceInGroup(op->properties, idp_dst); - change = TRUE; + change = true; } } } @@ -836,7 +836,7 @@ int WM_operator_last_properties_init(wmOperator *op) return change; } -int WM_operator_last_properties_store(wmOperator *op) +bool WM_operator_last_properties_store(wmOperator *op) { if (op->type->last_properties) { IDP_FreeProperty(op->type->last_properties); @@ -849,10 +849,10 @@ int WM_operator_last_properties_store(wmOperator *op) printf("%s: storing properties for '%s'\n", __func__, op->type->idname); } op->type->last_properties = IDP_CopyProperty(op->properties); - return TRUE; + return true; } else { - return FALSE; + return false; } } diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 193af2f92c6..16afad88069 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -248,7 +248,7 @@ void WM_init_splash(bContext *C) } } -int WM_init_game(bContext *C) +bool WM_init_game(bContext *C) { wmWindowManager *wm = CTX_wm_manager(C); wmWindow *win; @@ -318,7 +318,7 @@ int WM_init_game(bContext *C) sound_exit(); - return 1; + return true; } else { ReportTimerInfo *rti; @@ -333,8 +333,9 @@ int WM_init_game(bContext *C) rti = MEM_callocN(sizeof(ReportTimerInfo), "ReportTimerInfo"); wm->reports.reporttimer->customdata = rti; + + return false; } - return 0; } /* free strings of open recent files */ diff --git a/source/blender/windowmanager/intern/wm_keymap.c b/source/blender/windowmanager/intern/wm_keymap.c index 20e715c18d0..ff711c5ca4d 100644 --- a/source/blender/windowmanager/intern/wm_keymap.c +++ b/source/blender/windowmanager/intern/wm_keymap.c @@ -958,7 +958,7 @@ static wmKeyMapItem *wm_keymap_item_find( RNA_pointer_create(NULL, ot->srna, properties_default, &opptr); - if (WM_operator_properties_default(&opptr, TRUE)) { + if (WM_operator_properties_default(&opptr, true)) { found = wm_keymap_item_find_props(C, opname, opcontext, properties_default, 0, hotkey, keymap_r); } diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c index b4a4e4612e3..d0f258dc375 100644 --- a/source/blender/windowmanager/intern/wm_operators.c +++ b/source/blender/windowmanager/intern/wm_operators.c @@ -115,7 +115,7 @@ static GHash *global_ops_hash = NULL; /* ************ operator API, exported ********** */ -wmOperatorType *WM_operatortype_find(const char *idname, int quiet) +wmOperatorType *WM_operatortype_find(const char *idname, bool quiet) { if (idname[0]) { wmOperatorType *ot; @@ -779,7 +779,7 @@ void WM_operator_properties_alloc(PointerRNA **ptr, IDProperty **properties, con } -void WM_operator_properties_sanitize(PointerRNA *ptr, const short no_context) +void WM_operator_properties_sanitize(PointerRNA *ptr, const bool no_context) { RNA_STRUCT_BEGIN(ptr, prop) { @@ -815,7 +815,7 @@ void WM_operator_properties_sanitize(PointerRNA *ptr, const short no_context) * \note, theres nothing specific to operators here. * this could be made a general function. */ -int WM_operator_properties_default(PointerRNA *ptr, const int do_update) +int WM_operator_properties_default(PointerRNA *ptr, const bool do_update) { int is_change = FALSE; RNA_STRUCT_BEGIN(ptr, prop) @@ -831,7 +831,7 @@ int WM_operator_properties_default(PointerRNA *ptr, const int do_update) break; } default: - if ((do_update == FALSE) || (RNA_property_is_set(ptr, prop) == FALSE)) { + if ((do_update == false) || (RNA_property_is_set(ptr, prop) == FALSE)) { if (RNA_property_reset(ptr, prop, -1)) { is_change = 1; } @@ -964,7 +964,7 @@ static void operator_enum_search_cb(const struct bContext *C, void *arg_ot, cons for (item = item_array; item->identifier; item++) { /* note: need to give the index rather than the identifier because the enum can be freed */ if (BLI_strcasestr(item->name, str)) - if (0 == uiSearchItemAdd(items, item->name, SET_INT_IN_POINTER(item->value), 0)) + if (false == uiSearchItemAdd(items, item->name, SET_INT_IN_POINTER(item->value), 0)) break; } @@ -1226,7 +1226,7 @@ int WM_operator_winactive(bContext *C) } /* return FALSE, if the UI should be disabled */ -int WM_operator_check_ui_enabled(const bContext *C, const char *idname) +bool WM_operator_check_ui_enabled(const bContext *C, const char *idname) { wmWindowManager *wm = CTX_wm_manager(C); Scene *scene = CTX_data_scene(C); diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c index 53698ca7e9e..70cb10476d7 100644 --- a/source/blender/windowmanager/intern/wm_window.c +++ b/source/blender/windowmanager/intern/wm_window.c @@ -97,8 +97,8 @@ static struct WMInitStruct { int windowstate; WinOverrideFlag override_flag; - int native_pixels; -} wm_init_state = {0, 0, 0, 0, GHOST_kWindowStateNormal, 0, 1}; + bool native_pixels; +} wm_init_state = {0, 0, 0, 0, GHOST_kWindowStateNormal, 0, true}; /* ******** win open & close ************ */ @@ -1332,7 +1332,7 @@ void WM_init_state_normal_set(void) wm_init_state.override_flag |= WIN_OVERRIDE_WINSTATE; } -void WM_init_native_pixels(int do_it) +void WM_init_native_pixels(bool do_it) { wm_init_state.native_pixels = do_it; } diff --git a/source/blenderplayer/bad_level_call_stubs/stubs.c b/source/blenderplayer/bad_level_call_stubs/stubs.c index de40f7d6d3c..40eb9c673e2 100644 --- a/source/blenderplayer/bad_level_call_stubs/stubs.c +++ b/source/blenderplayer/bad_level_call_stubs/stubs.c @@ -413,11 +413,11 @@ void uiItemR(struct uiLayout *layout, struct PointerRNA *ptr, char *propname, in struct PointerRNA uiItemFullO(struct uiLayout *layout, char *idname, char *name, int icon, struct IDProperty *properties, int context, int flag) {struct PointerRNA a = {{0}}; return a;} PointerRNA uiItemFullO_ptr(struct uiLayout *layout, struct wmOperatorType *ot, const char *name, int icon, struct IDProperty *properties, int context, int flag) {struct PointerRNA a = {{0}}; return a;} -struct uiLayout *uiLayoutRow(struct uiLayout *layout, int align) {return (struct uiLayout *) NULL;} -struct uiLayout *uiLayoutColumn(struct uiLayout *layout, int align) {return (struct uiLayout *) NULL;} -struct uiLayout *uiLayoutColumnFlow(struct uiLayout *layout, int number, int align) {return (struct uiLayout *) NULL;} +struct uiLayout *uiLayoutRow(struct uiLayout *layout, bool align) {return (struct uiLayout *) NULL;} +struct uiLayout *uiLayoutColumn(struct uiLayout *layout, bool align) {return (struct uiLayout *) NULL;} +struct uiLayout *uiLayoutColumnFlow(struct uiLayout *layout, int number, bool align) {return (struct uiLayout *) NULL;} struct uiLayout *uiLayoutBox(struct uiLayout *layout) {return (struct uiLayout *) NULL;} -struct uiLayout *uiLayoutSplit(struct uiLayout *layout, float percentage, int align) {return (struct uiLayout *) NULL;} +struct uiLayout *uiLayoutSplit(struct uiLayout *layout, float percentage, bool align) {return (struct uiLayout *) NULL;} int uiLayoutGetRedAlert(struct uiLayout *layout) {return 0;} void uiLayoutSetRedAlert(struct uiLayout *layout, int redalert) {} void uiItemsEnumR(struct uiLayout *layout, struct PointerRNA *ptr, char *propname) {} @@ -439,7 +439,7 @@ void uiItemFullR(struct uiLayout *layout, struct PointerRNA *ptr, struct Propert void uiLayoutSetContextPointer(struct uiLayout *layout, char *name, struct PointerRNA *ptr) {} char *uiLayoutIntrospect(struct uiLayout *layout) {return (char *)NULL;} void UI_reinit_font(void) {} -int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, int big) {return 0;} +int UI_rnaptr_icon_get(struct bContext *C, struct PointerRNA *ptr, int rnaicon, const bool big) {return 0;} struct bTheme *UI_GetTheme(void) {return (struct bTheme *) NULL;}; /* rna template */ @@ -462,9 +462,7 @@ void uiTemplateRunningJobs(struct uiLayout *layout, struct bContext *C) {} void uiTemplateOperatorSearch(struct uiLayout *layout) {} void uiTemplateHeader3D(struct uiLayout *layout, struct bContext *C) {} 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 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) {} diff --git a/source/creator/creator.c b/source/creator/creator.c index 7abb653e9b8..1fec281a71c 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -660,7 +660,7 @@ static int prefsize(int argc, const char **argv, void *UNUSED(data)) static int native_pixels(int UNUSED(argc), const char **UNUSED(argv), void *UNUSED(data)) { - WM_init_native_pixels(0); + WM_init_native_pixels(false); return 0; } diff --git a/source/gameengine/Ketsji/BL_BlenderShader.cpp b/source/gameengine/Ketsji/BL_BlenderShader.cpp index f5f9b344b87..3f2a9a6df6a 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.cpp +++ b/source/gameengine/Ketsji/BL_BlenderShader.cpp @@ -46,11 +46,20 @@ void BL_BlenderShader::ReloadMaterial() mGPUMat = (mMat) ? GPU_material_from_blender(mBlenderScene, mMat) : NULL; } -void BL_BlenderShader::SetProg(bool enable, double time) +void BL_BlenderShader::SetProg(bool enable, double time, RAS_IRasterizer* rasty) { if (VerifyShader()) { - if (enable) - GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1); + if (enable) { + assert(rasty != NULL); // XXX Kinda hacky, but SetProg() should always have the rasterizer if enable is true + + float viewmat[4][4], viewinvmat[4][4]; + const MT_Matrix4x4& view = rasty->GetViewMatrix(); + const MT_Matrix4x4& viewinv = rasty->GetViewInvMatrix(); + view.getValue((float*)viewmat); + viewinv.getValue((float*)viewinvmat); + + GPU_material_bind(mGPUMat, mLightLayer, mBlenderScene->lay, time, 1, viewmat, viewinvmat); + } else GPU_material_unbind(mGPUMat); } @@ -120,7 +129,7 @@ void BL_BlenderShader::SetAttribs(RAS_IRasterizer* ras, const BL_Material *mat) void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) { - float obmat[4][4], viewmat[4][4], viewinvmat[4][4], obcol[4]; + float obmat[4][4], obcol[4]; GPUMaterial *gpumat; gpumat = mGPUMat; @@ -130,13 +139,9 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) MT_Matrix4x4 model; model.setValue(ms.m_OpenGLMatrix); - const MT_Matrix4x4& view = rasty->GetViewMatrix(); - const MT_Matrix4x4& viewinv = rasty->GetViewInvMatrix(); // note: getValue gives back column major as needed by OpenGL model.getValue((float*)obmat); - view.getValue((float*)viewmat); - viewinv.getValue((float*)viewinvmat); if (ms.m_bObjectColor) ms.m_RGBAcolor.getValue((float *)obcol); @@ -144,7 +149,7 @@ void BL_BlenderShader::Update(const RAS_MeshSlot & ms, RAS_IRasterizer* rasty ) obcol[0] = obcol[1] = obcol[2] = obcol[3] = 1.0f; float auto_bump_scale = ms.m_pDerivedMesh!=0 ? ms.m_pDerivedMesh->auto_bump_scale : 1.0f; - GPU_material_bind_uniforms(gpumat, obmat, viewmat, viewinvmat, obcol, auto_bump_scale); + GPU_material_bind_uniforms(gpumat, obmat, obcol, auto_bump_scale); mAlphaBlend = GPU_material_alpha_blend(gpumat, obcol); } diff --git a/source/gameengine/Ketsji/BL_BlenderShader.h b/source/gameengine/Ketsji/BL_BlenderShader.h index 626c65baadd..71f66c2a49d 100644 --- a/source/gameengine/Ketsji/BL_BlenderShader.h +++ b/source/gameengine/Ketsji/BL_BlenderShader.h @@ -78,7 +78,7 @@ public: // same as VerifyShared return (NULL != mGPUMat); } - void SetProg(bool enable, double time=0.0); + void SetProg(bool enable, double time=0.0, RAS_IRasterizer* rasty=NULL); int GetAttribNum(); void SetAttribs(class RAS_IRasterizer* ras, const BL_Material *mat); diff --git a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp index 231ec27030d..853cfa53da2 100644 --- a/source/gameengine/Ketsji/KX_BlenderMaterial.cpp +++ b/source/gameengine/Ketsji/KX_BlenderMaterial.cpp @@ -314,7 +314,7 @@ void KX_BlenderMaterial::setBlenderShaderData( bool enable, RAS_IRasterizer *ras else BL_Texture::DisableAllTextures(); - mBlenderShader->SetProg(true, ras->GetTime()); + mBlenderShader->SetProg(true, ras->GetTime(), ras); mLastBlenderShader= mBlenderShader; } } |